Skip to content

Commit 9a6ea18

Browse files
committed
ip: Add ability to set address protocol when adding addresses
Signed-off-by: Jacques de Laval <[email protected]>
1 parent 29da83f commit 9a6ea18

6 files changed

Lines changed: 117 additions & 0 deletions

File tree

etc/iproute2/ifa_protos

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#
2+
# Reserved protocols.
3+
#
4+
0 unspec
5+
1 static
6+
2 dhcp
7+
3 bootp

include/rt_names.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ const char *rtnl_rtrealm_n2a(int id, char *buf, int len);
1111
const char *rtnl_dsfield_n2a(int id, char *buf, int len);
1212
const char *rtnl_dsfield_get_name(int id);
1313
const char *rtnl_group_n2a(int id, char *buf, int len);
14+
const char *rtnl_ifaprot_n2a(int id, char *buf, int len);
1415

1516
int rtnl_rtprot_a2n(__u32 *id, const char *arg);
1617
int rtnl_rtscope_a2n(__u32 *id, const char *arg);
1718
int rtnl_rttable_a2n(__u32 *id, const char *arg);
1819
int rtnl_rtrealm_a2n(__u32 *id, const char *arg);
1920
int rtnl_dsfield_a2n(__u32 *id, const char *arg);
2021
int rtnl_group_a2n(int *id, const char *arg);
22+
int rtnl_ifaprot_a2n(__u32 *id, const char *arg);
2123

2224
const char *inet_proto_n2a(int proto, char *buf, int len);
2325
int inet_proto_a2n(const char *buf);

include/uapi/linux/if_addr.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ enum {
3535
IFA_FLAGS,
3636
IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */
3737
IFA_TARGET_NETNSID,
38+
IFA_PROTO,
3839
__IFA_MAX,
3940
};
4041

@@ -67,4 +68,11 @@ struct ifa_cacheinfo {
6768
#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
6869
#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
6970

71+
/* ifa_protocol */
72+
73+
#define IFAPROT_UNSPEC 0
74+
#define IFAPROT_STATIC 1
75+
#define IFAPROT_DHCP 2
76+
#define IFAPROT_BOOTP 3
77+
7078
#endif

ip/ip_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct link_filter {
1616
inet_prefix pfx;
1717
int scope, scopemask;
1818
int flags, flagmask;
19+
int proto, protomask;
1920
int up;
2021
char *label;
2122
int flushed;

ip/ipaddress.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static void usage(void)
6767
"IFADDR := PREFIX | ADDR peer PREFIX\n"
6868
" [ broadcast ADDR ] [ anycast ADDR ]\n"
6969
" [ label IFNAME ] [ scope SCOPE-ID ] [ metric METRIC ]\n"
70+
" [ proto IFAPROTO ]\n"
7071
"SCOPE-ID := [ host | link | global | NUMBER ]\n"
7172
"FLAG-LIST := [ FLAG-LIST ] FLAG\n"
7273
"FLAG := [ permanent | dynamic | secondary | primary |\n"
@@ -1508,6 +1509,9 @@ int print_addrinfo(struct nlmsghdr *n, void *arg)
15081509
return 0;
15091510
if ((filter.flags ^ ifa_flags) & filter.flagmask)
15101511
return 0;
1512+
if (rta_tb[IFA_PROTO])
1513+
if ((filter.proto ^ rta_getattr_u32(rta_tb[IFA_PROTO])) & filter.protomask)
1514+
return 0;
15111515

15121516
if (filter.family && filter.family != ifa->ifa_family)
15131517
return 0;
@@ -1618,6 +1622,16 @@ int print_addrinfo(struct nlmsghdr *n, void *arg)
16181622

16191623
print_ifa_flags(fp, ifa, ifa_flags);
16201624

1625+
if (rta_tb[IFA_PROTO]) {
1626+
__u8 prot = rta_getattr_u8(rta_tb[IFA_PROTO]);
1627+
1628+
if (prot != IFAPROT_UNSPEC)
1629+
print_string(PRINT_ANY,
1630+
"protocol",
1631+
"proto %s ",
1632+
rtnl_ifaprot_n2a(prot, b1, sizeof(b1)));
1633+
}
1634+
16211635
if (rta_tb[IFA_LABEL])
16221636
print_string(PRINT_ANY,
16231637
"label",
@@ -1872,6 +1886,10 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
18721886
if ((filter.flags ^ ifa_flags) & filter.flagmask)
18731887
continue;
18741888

1889+
if (tb[IFA_PROTO])
1890+
if ((filter.proto ^ rta_getattr_u32(tb[IFA_PROTO])) & filter.protomask)
1891+
continue;
1892+
18751893
if (ifa_label_match_rta(ifa->ifa_index, tb[IFA_LABEL]))
18761894
continue;
18771895

@@ -2137,6 +2155,18 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
21372155
} else {
21382156
filter.kind = *argv;
21392157
}
2158+
} else if (strcmp(*argv, "proto") == 0) {
2159+
unsigned int proto = 0;
2160+
2161+
NEXT_ARG();
2162+
filter.protomask = -1;
2163+
if (rtnl_ifaprot_a2n(&proto, *argv)) {
2164+
if (strcmp(*argv, "all") != 0)
2165+
invarg("invalid \"proto\"\n", *argv);
2166+
proto = 0;
2167+
filter.protomask = 0;
2168+
}
2169+
filter.proto = proto;
21402170
} else {
21412171
if (strcmp(*argv, "dev") == 0)
21422172
NEXT_ARG();
@@ -2434,6 +2464,13 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
24342464
} else if (strcmp(*argv, "dev") == 0) {
24352465
NEXT_ARG();
24362466
d = *argv;
2467+
} else if (strcmp(*argv, "proto") == 0) {
2468+
__u32 prot;
2469+
2470+
NEXT_ARG();
2471+
if (rtnl_ifaprot_a2n(&prot, *argv))
2472+
invarg("Invalid \"protocol\" value\n", *argv);
2473+
addattr8(&req.n, sizeof(req), IFA_PROTO, prot);
24372474
} else if (strcmp(*argv, "label") == 0) {
24382475
NEXT_ARG();
24392476
l = *argv;

lib/rt_names.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,3 +786,65 @@ int protodown_reason_a2n(__u32 *id, const char *arg)
786786
*id = res;
787787
return 0;
788788
}
789+
790+
static char *rtnl_ifaprot_tab[256] = {
791+
[IFAPROT_UNSPEC] = "unspec",
792+
[IFAPROT_STATIC] = "static",
793+
[IFAPROT_DHCP] = "dhcp",
794+
[IFAPROT_BOOTP] = "bootp",
795+
};
796+
797+
static int rtnl_ifaprot_init;
798+
799+
static void rtnl_ifaprot_initialize(void)
800+
{
801+
rtnl_ifaprot_init = 1;
802+
rtnl_tab_initialize(CONFDIR "/ifa_protos",
803+
rtnl_ifaprot_tab, 256);
804+
}
805+
806+
const char *rtnl_ifaprot_n2a(int id, char *buf, int len) {
807+
if (id < 0 || id >= 256) {
808+
snprintf(buf, len, "%d", id);
809+
return buf;
810+
}
811+
if (!rtnl_ifaprot_tab[id]) {
812+
if (!rtnl_ifaprot_init)
813+
rtnl_ifaprot_initialize();
814+
}
815+
if (rtnl_ifaprot_tab[id])
816+
return rtnl_ifaprot_tab[id];
817+
snprintf(buf, len, "0x%02x", id);
818+
return buf;
819+
}
820+
821+
int rtnl_ifaprot_a2n(__u32 *id, const char *arg) {
822+
static char *cache;
823+
static unsigned long res;
824+
char *end;
825+
int i;
826+
827+
if (cache && strcmp(cache, arg) == 0) {
828+
*id = res;
829+
return 0;
830+
}
831+
832+
if (!rtnl_ifaprot_init)
833+
rtnl_ifaprot_initialize();
834+
835+
for (i = 0; i < 256; i++) {
836+
if (rtnl_ifaprot_tab[i] &&
837+
strcmp(rtnl_ifaprot_tab[i], arg) == 0) {
838+
cache = rtnl_ifaprot_tab[i];
839+
res = i;
840+
*id = res;
841+
return 0;
842+
}
843+
}
844+
845+
res = strtoul(arg, &end, 0);
846+
if (!end || end == arg || *end || res > 255)
847+
return -1;
848+
*id = res;
849+
return 0;
850+
}

0 commit comments

Comments
 (0)