OpenWrt之自定义Hostname
OpenWrt之自定义Client的Hostname
OpenWrt默认的DHCP列表,部分设备无法显示client的hostname,例如iOS设备:
这样对笔者而言,有些不方便,决定增加一列,以显示其hostname的alias,并支持修改,先上效果图:
- 新增了
Customized Hostname
一列,显示自定义的Hostname,即Alias; - 新增了
Set Alias
按钮,支持输入自定义的Hostname;
首先,找到对应的代码,在feeds/luci/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js
中,做以下改动:
24d23
< L.resolveDefault(uci.load('client')),
29,46d27
< handleSetAlias: function(lease, alias, ev) {
< ev.currentTarget.classList.add('spinning');
< ev.currentTarget.disabled = true;
< ev.currentTarget.blur();
<
< var sections = lease.macaddr.toUpperCase().replace(/:/g, '');
< if (!uci.get('client', sections, 'alias'))
< uci.add('client', 'client', sections);
<
< var say = 'Enter a new alias for client(%s)'.format(lease.macaddr.toUpperCase());
< var new_alias = prompt(say, alias);
< uci.set('client', sections, 'alias', new_alias || alias);
<
< return uci.save()
< .then(L.bind(L.ui.changes.init, L.ui.changes))
< .then(L.bind(L.ui.changes.displayChanges, L.ui.changes));
< },
<
107d87
< E('th', { 'class': 'th' }, _('Customized Hostname')),
134,141d113
< var alias = null;
< if (lease.macaddr)
< var mac = lease.macaddr.toUpperCase().replace(/:/g, '');
< alias = uci.get('client', mac, 'alias');
<
< if (!alias)
< alias = 'Network Device';
<
144d115
< alias,
149,153d119
<
< rows.push(E('button', {
< 'class': 'cbi-button cbi-button-apply',
< 'click': L.bind(this.handleSetAlias, this, lease, alias)
< }, [ _('Set Alias') ]));
以下为文件源码:
'use strict';
'require baseclass';
'require rpc';
'require uci';
'require network';
'require validation';
var callLuciDHCPLeases = rpc.declare({
object: 'luci-rpc',
method: 'getDHCPLeases',
expect: { '': {} }
});
return baseclass.extend({
title: '',
isMACStatic: {},
isDUIDStatic: {},
load: function() {
return Promise.all([
callLuciDHCPLeases(),
network.getHostHints(),
L.resolveDefault(uci.load('client')),
L.resolveDefault(uci.load('dhcp'))
]);
},
handleSetAlias: function(lease, alias, ev) {
ev.currentTarget.classList.add('spinning');
ev.currentTarget.disabled = true;
ev.currentTarget.blur();
var sections = lease.macaddr.toUpperCase().replace(/:/g, '');
if (!uci.get('client', sections, 'alias'))
uci.add('client', 'client', sections);
var say = 'Enter a new alias for client(%s)'.format(lease.macaddr.toUpperCase());
var new_alias = prompt(say, alias);
uci.set('client', sections, 'alias', new_alias || alias);
return uci.save()
.then(L.bind(L.ui.changes.init, L.ui.changes))
.then(L.bind(L.ui.changes.displayChanges, L.ui.changes));
},
handleCreateStaticLease: function(lease, ev) {
ev.currentTarget.classList.add('spinning');
ev.currentTarget.disabled = true;
ev.currentTarget.blur();
var cfg = uci.add('dhcp', 'host');
uci.set('dhcp', cfg, 'name', lease.hostname);
uci.set('dhcp', cfg, 'ip', lease.ipaddr);
uci.set('dhcp', cfg, 'mac', lease.macaddr.toUpperCase());
return uci.save()
.then(L.bind(L.ui.changes.init, L.ui.changes))
.then(L.bind(L.ui.changes.displayChanges, L.ui.changes));
},
handleCreateStaticLease6: function(lease, ev) {
ev.currentTarget.classList.add('spinning');
ev.currentTarget.disabled = true;
ev.currentTarget.blur();
var cfg = uci.add('dhcp', 'host'),
ip6arr = lease.ip6addrs[0] ? validation.parseIPv6(lease.ip6addrs[0]) : null;
uci.set('dhcp', cfg, 'name', lease.hostname);
uci.set('dhcp', cfg, 'duid', lease.duid.toUpperCase());
uci.set('dhcp', cfg, 'mac', lease.macaddr);
if (ip6arr)
uci.set('dhcp', cfg, 'hostid', (ip6arr[6] * 0xFFFF + ip6arr[7]).toString(16));
return uci.save()
.then(L.bind(L.ui.changes.init, L.ui.changes))
.then(L.bind(L.ui.changes.displayChanges, L.ui.changes));
},
renderLeases: function(data) {
var leases = Array.isArray(data[0].dhcp_leases) ? data[0].dhcp_leases : [],
leases6 = Array.isArray(data[0].dhcp6_leases) ? data[0].dhcp6_leases : [],
machints = data[1].getMACHints(false),
hosts = uci.sections('dhcp', 'host'),
isReadonlyView = !L.hasViewPermission();
for (var i = 0; i < hosts.length; i++) {
var host = hosts[i];
if (host.mac) {
var macs = L.toArray(host.mac);
for (var j = 0; j < macs.length; j++) {
var mac = macs[j].toUpperCase();
this.isMACStatic[mac] = true;
}
}
if (host.duid) {
var duid = host.duid.toUpperCase();
this.isDUIDStatic[duid] = true;
}
};
var table = E('table', { 'class': 'table lases' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('Hostname')),
E('th', { 'class': 'th' }, _('Customized Hostname')),
E('th', { 'class': 'th' }, _('IPv4 address')),
E('th', { 'class': 'th' }, _('MAC address')),
E('th', { 'class': 'th' }, _('Lease time remaining')),
E('th', { 'class': 'th cbi-section-actions' }, _('Static Alias')),
isReadonlyView ? E([]) : E('th', { 'class': 'th cbi-section-actions' }, _('Static Lease'))
])
]);
cbi_update_table(table, leases.map(L.bind(function(lease) {
var exp, rows;
if (lease.expires === false)
exp = E('em', _('unlimited'));
else if (lease.expires <= 0)
exp = E('em', _('expired'));
else
exp = '%t'.format(lease.expires);
var hint = lease.macaddr ? machints.filter(function(h) { return h[0] == lease.macaddr })[0] : null,
host = null;
if (hint && lease.hostname && lease.hostname != hint[1])
host = '%s (%s)'.format(lease.hostname, hint[1]);
else if (lease.hostname)
host = lease.hostname;
var alias = null;
if (lease.macaddr)
var mac = lease.macaddr.toUpperCase().replace(/:/g, '');
alias = uci.get('client', mac, 'alias');
if (!alias)
alias = 'Network Device';
rows = [
host || '-',
alias,
lease.ipaddr,
lease.macaddr,
exp
];
rows.push(E('button', {
'class': 'cbi-button cbi-button-apply',
'click': L.bind(this.handleSetAlias, this, lease, alias)
}, [ _('Set Alias') ]));
if (!isReadonlyView && lease.macaddr != null) {
var mac = lease.macaddr.toUpperCase();
rows.push(E('button', {
'class': 'cbi-button cbi-button-apply',
'click': L.bind(this.handleCreateStaticLease, this, lease),
'disabled': this.isMACStatic[mac]
}, [ _('Set Static') ]));
}
return rows;
}, this)), E('em', _('There are no active leases')));
var table6 = E('table', { 'class': 'table leases6' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('Host')),
E('th', { 'class': 'th' }, _('IPv6 address')),
E('th', { 'class': 'th' }, _('DUID')),
E('th', { 'class': 'th' }, _('Lease time remaining')),
isReadonlyView ? E([]) : E('th', { 'class': 'th cbi-section-actions' }, _('Static Lease'))
])
]);
cbi_update_table(table6, leases6.map(L.bind(function(lease) {
var exp, rows;
if (lease.expires === false)
exp = E('em', _('unlimited'));
else if (lease.expires <= 0)
exp = E('em', _('expired'));
else
exp = '%t'.format(lease.expires);
var hint = lease.macaddr ? machints.filter(function(h) { return h[0] == lease.macaddr })[0] : null,
host = null;
if (hint && lease.hostname && lease.hostname != hint[1] && lease.ip6addr != hint[1])
host = '%s (%s)'.format(lease.hostname, hint[1]);
else if (lease.hostname)
host = lease.hostname;
else if (hint)
host = hint[1];
rows = [
host || '-',
lease.ip6addrs ? lease.ip6addrs.join(' ') : lease.ip6addr,
lease.duid,
exp
];
if (!isReadonlyView && lease.duid != null) {
var duid = lease.duid.toUpperCase();
rows.push(E('button', {
'class': 'cbi-button cbi-button-apply',
'click': L.bind(this.handleCreateStaticLease6, this, lease),
'disabled': this.isDUIDStatic[duid]
}, [ _('Set Static') ]));
}
return rows;
}, this)), E('em', _('There are no active leases')));
return E([
E('h3', _('Active DHCP Leases')),
table,
E('h3', _('Active DHCPv6 Leases')),
table6
]);
},
render: function(data) {
if (L.hasSystemFeature('dnsmasq') || L.hasSystemFeature('odhcpd'))
return this.renderLeases(data);
return E([]);
}
});
直接替换文件系统中的/www/luci-static/resources/view/status/include/40_dhcp.js
并创建配置文件:
touch /etc/config/client
并删除luci
的缓存:
rm -rf /tmp/luci-indexcache*
重新打开浏览器,即得所需效果。
注意:有时候浏览器本身有缓存,可以换个浏览器打开试试;或者使用无痕模式浏览。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix