void ipoe_nl_add_net(uint32_t addr, int mask) { struct nlmsghdr *nlh; struct genlmsghdr *ghdr; struct { struct nlmsghdr n; char buf[1024]; } req; if (rth.fd == -1) return; nlh = &req.n; nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_type = ipoe_genl_id; ghdr = NLMSG_DATA(&req.n); ghdr->cmd = IPOE_CMD_ADD_NET; mask = mask ? ~0 << (32 - mask) : 0; addattr32(nlh, 1024, IPOE_ATTR_ADDR, addr); addattr32(nlh, 1024, IPOE_ATTR_MASK, mask); if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) log_error("ipoe: nl_add_net: error talking to kernel\n"); }
static int create_tunnel(struct l2tp_parm *p) { uint32_t local_attr = L2TP_ATTR_IP_SADDR; uint32_t peer_attr = L2TP_ATTR_IP_DADDR; GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION, L2TP_CMD_TUNNEL_CREATE, NLM_F_REQUEST | NLM_F_ACK); addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id); addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id); addattr8(&req.n, 1024, L2TP_ATTR_PROTO_VERSION, 3); addattr16(&req.n, 1024, L2TP_ATTR_ENCAP_TYPE, p->encap); if (p->local_ip.family == AF_INET6) local_attr = L2TP_ATTR_IP6_SADDR; addattr_l(&req.n, 1024, local_attr, &p->local_ip.data, p->local_ip.bytelen); if (p->peer_ip.family == AF_INET6) peer_attr = L2TP_ATTR_IP6_DADDR; addattr_l(&req.n, 1024, peer_attr, &p->peer_ip.data, p->peer_ip.bytelen); if (p->encap == L2TP_ENCAPTYPE_UDP) { addattr16(&req.n, 1024, L2TP_ATTR_UDP_SPORT, p->local_udp_port); addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port); } if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) return -2; return 0; }
static int set_netnsid_from_name(const char *name, int nsid) { struct { struct nlmsghdr n; struct rtgenmsg g; char buf[1024]; } req; int fd, err = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_NEWNSID; req.g.rtgen_family = AF_UNSPEC; fd = netns_get_fd(name); if (fd < 0) return fd; addattr32(&req.n, 1024, NETNSA_FD, fd); addattr32(&req.n, 1024, NETNSA_NSID, nsid); if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) err = -2; close(fd); return err; }
static int create_session(struct l2tp_parm *p) { GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION, L2TP_CMD_SESSION_CREATE, NLM_F_REQUEST | NLM_F_ACK); addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id); addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id); addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id); addattr32(&req.n, 1024, L2TP_ATTR_PEER_SESSION_ID, p->peer_session_id); addattr16(&req.n, 1024, L2TP_ATTR_PW_TYPE, p->pw_type); addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_TYPE, p->l2spec_type); addattr8(&req.n, 1024, L2TP_ATTR_L2SPEC_LEN, p->l2spec_len); if (p->mtu) addattr16(&req.n, 1024, L2TP_ATTR_MTU, p->mtu); if (p->recv_seq) addattr(&req.n, 1024, L2TP_ATTR_RECV_SEQ); if (p->send_seq) addattr(&req.n, 1024, L2TP_ATTR_SEND_SEQ); if (p->lns_mode) addattr(&req.n, 1024, L2TP_ATTR_LNS_MODE); if (p->data_seq) addattr8(&req.n, 1024, L2TP_ATTR_DATA_SEQ, p->data_seq); if (p->reorder_timeout) addattr64(&req.n, 1024, L2TP_ATTR_RECV_TIMEOUT, p->reorder_timeout); if (p->offset) addattr16(&req.n, 1024, L2TP_ATTR_OFFSET, p->offset); if (p->cookie_len) addattr_l(&req.n, 1024, L2TP_ATTR_COOKIE, p->cookie, p->cookie_len); if (p->peer_cookie_len) addattr_l(&req.n, 1024, L2TP_ATTR_PEER_COOKIE, p->peer_cookie, p->peer_cookie_len); if (p->ifname && p->ifname[0]) addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname); if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) return -2; return 0; }
static int do_modify_nl(enum cmd c, enum macsec_nl_commands cmd, int ifindex, struct rxsc_desc *rxsc, struct sa_desc *sa) { struct rtattr *attr_sa; MACSEC_GENL_REQ(req, MACSEC_BUFLEN, cmd, NLM_F_REQUEST); addattr32(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_IFINDEX, ifindex); if (rxsc) { struct rtattr *attr_rxsc; attr_rxsc = addattr_nest(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_RXSC_CONFIG); addattr64(&req.n, MACSEC_BUFLEN, MACSEC_RXSC_ATTR_SCI, rxsc->sci); if (c != CMD_DEL && rxsc->active != 0xff) addattr8(&req.n, MACSEC_BUFLEN, MACSEC_RXSC_ATTR_ACTIVE, rxsc->active); addattr_nest_end(&req.n, attr_rxsc); } if (sa->an == 0xff) goto talk; attr_sa = addattr_nest(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_SA_CONFIG); addattr8(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_AN, sa->an); if (c != CMD_DEL) { if (sa->pn) addattr32(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_PN, sa->pn); if (sa->key_len) { addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEYID, sa->key_id, MACSEC_KEYID_LEN); addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEY, sa->key, sa->key_len); } if (sa->active != 0xff) { addattr8(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_ACTIVE, sa->active); } } addattr_nest_end(&req.n, attr_sa); talk: if (rtnl_talk(&genl_rth, &req.n, NULL) < 0) return -2; return 0; }
static int delete_session(struct l2tp_parm *p) { GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION, L2TP_CMD_SESSION_DELETE, NLM_F_REQUEST | NLM_F_ACK); addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id); addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id); if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) return -2; return 0; }
int rt_restore_entry(struct rt_entry *r) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; req.n.nlmsg_type = RTM_NEWROUTE; memcpy(&req.r, r->rtm, sizeof(struct rtmsg)); if (r->src) addattr_l(&req.n, sizeof(req), RTA_SRC, &r->src, 4); if (r->psrc) addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &r->psrc, 4); if (r->dest) addattr_l(&req.n, sizeof(req), RTA_DST, &r->dest, 4); if (r->gate) addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &r->gate, 4); if (r->flow) addattr_l(&req.n, sizeof(req), RTA_FLOW, &r->flow, 4); if (r->oif) addattr32(&req.n, sizeof(req), RTA_OIF, r->oif); if (r->iif) addattr32(&req.n, sizeof(req), RTA_IIF, r->iif); if (r->prio) addattr32(&req.n, sizeof(req), RTA_PRIORITY, r->prio); if (r->metrics) addattr32(&req.n, sizeof(req), RTA_METRICS, r->metrics); if (rtnl_open(&rth, 0) < 0) { printf("Can not initialize netlink interface...\n"); return -1; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) { printf("Can not talk with netlink interface...\n"); return -1; } return 0; }
int ipoe_nl_modify(int ifindex, uint32_t peer_addr, uint32_t addr, const char *ifname, uint8_t *hwaddr) { struct rtnl_handle rth; struct nlmsghdr *nlh; struct genlmsghdr *ghdr; int ret = 0; struct { struct nlmsghdr n; char buf[1024]; } req; union { uint8_t hwaddr[6]; uint64_t u64; } u; if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) { log_ppp_error("ipoe: cannot open generic netlink socket\n"); return -1; } nlh = &req.n; nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_type = ipoe_genl_id; ghdr = NLMSG_DATA(&req.n); ghdr->cmd = IPOE_CMD_MODIFY; addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex); addattr32(nlh, 1024, IPOE_ATTR_PEER_ADDR, peer_addr); addattr32(nlh, 1024, IPOE_ATTR_ADDR, addr); if (hwaddr) { memcpy(u.hwaddr, hwaddr, 6); addattr_l(nlh, 1024, IPOE_ATTR_HWADDR, &u.u64, 8); } if (ifname) addattr_l(nlh, 1024, IPOE_ATTR_IFNAME, ifname, strlen(ifname) + 1); if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) { log_ppp_error("ipoe: nl_create: error talking to kernel\n"); ret = -1; } rtnl_close(&rth); return ret; }
void ipoe_nl_add_interface(int ifindex) { struct nlmsghdr *nlh; struct genlmsghdr *ghdr; struct { struct nlmsghdr n; char buf[1024]; } req; if (rth.fd == -1) return; nlh = &req.n; nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_type = ipoe_genl_id; ghdr = NLMSG_DATA(&req.n); ghdr->cmd = IPOE_CMD_ADD_IF; addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex); if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) log_error("ipoe: nl_add_iface: error talking to kernel\n"); }
int iplink_get(unsigned int flags, char *name, __u32 filt_mask) { int len; struct iplink_req req; char answer[16384]; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = RTM_GETLINK; req.i.ifi_family = preferred_family; if (name) { len = strlen(name) + 1; if (len == 1) invarg("\"\" is not a valid device identifier\n", "name"); if (len > IFNAMSIZ) invarg("\"name\" too long\n", name); addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len); } addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask); if (rtnl_talk(&rth, &req.n, 0, 0, (struct nlmsghdr *)answer) < 0) return -2; print_linkinfo(NULL, (struct nlmsghdr *)answer, stdout); return 0; }
static int ipnetns_have_nsid(void) { struct { struct nlmsghdr n; struct rtgenmsg g; char buf[1024]; } req; int fd; if (have_rtnl_getnsid < 0) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETNSID; req.g.rtgen_family = AF_UNSPEC; fd = open("/proc/self/ns/net", O_RDONLY); if (fd < 0) { perror("open(\"/proc/self/ns/net\")"); exit(1); } addattr32(&req.n, 1024, NETNSA_FD, fd); if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) { perror("request send failed"); exit(1); } rtnl_listen(&rth, ipnetns_accept_msg, NULL); close(fd); } return have_rtnl_getnsid; }
int ipoe_nl_del_vlan_mon(int ifindex) { struct nlmsghdr *nlh; struct genlmsghdr *ghdr; struct { struct nlmsghdr n; char buf[1024]; } req; if (rth.fd == -1) return -1; nlh = &req.n; nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_type = ipoe_genl_id; ghdr = NLMSG_DATA(&req.n); ghdr->cmd = IPOE_CMD_DEL_VLAN_MON; addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex); if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) { log_error("ipoe: nl_del_vlan_mon: error talking to kernel\n"); return -1; } return 0; }
void ipoe_nl_delete(int ifindex) { struct rtnl_handle rth; struct nlmsghdr *nlh; struct genlmsghdr *ghdr; struct { struct nlmsghdr n; char buf[1024]; } req; if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) { log_ppp_error("ipoe: cannot open generic netlink socket\n"); return; } nlh = &req.n; nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_type = ipoe_genl_id; ghdr = NLMSG_DATA(&req.n); ghdr->cmd = IPOE_CMD_DELETE; addattr32(nlh, 128, IPOE_ATTR_IFINDEX, ifindex); if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) log_ppp_error("ipoe: nl_delete: error talking to kernel\n"); rtnl_close(&rth); }
void ipoe_nl_delete_nets(void) { struct nlmsghdr *nlh; struct genlmsghdr *ghdr; struct { struct nlmsghdr n; char buf[1024]; } req; if (rth.fd == -1) return; nlh = &req.n; nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_type = ipoe_genl_id; ghdr = NLMSG_DATA(&req.n); ghdr->cmd = IPOE_CMD_DEL_NET; addattr32(nlh, 1024, IPOE_ATTR_ADDR, 0); if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) log_error("ipoe: nl_del_net: error talking to kernel\n"); }
static int macvtap_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { while (argc > 0) { if (matches(*argv, "mode") == 0) { __u32 mode = 0; NEXT_ARG(); if (strcmp(*argv, "private") == 0) mode = MACVLAN_MODE_PRIVATE; else if (strcmp(*argv, "vepa") == 0) mode = MACVLAN_MODE_VEPA; else if (strcmp(*argv, "bridge") == 0) mode = MACVLAN_MODE_BRIDGE; else if (strcmp(*argv, "passthru") == 0) mode = MACVLAN_MODE_PASSTHRU; else return mode_arg(*argv); addattr32(n, 1024, IFLA_MACVLAN_MODE, mode); } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "macvtap: unknown command \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } return 0; }
static int route_mod(int cmd, int oif, uint8_t table, uint8_t proto, unsigned flags, uint32_t priority, const struct in6_addr *src, int src_plen, const struct in6_addr *dst, int dst_plen, const struct in6_addr *gateway) { uint8_t buf[512]; struct nlmsghdr *n; struct rtmsg *rtm; if (cmd == RTM_NEWROUTE && oif == 0) return -1; memset(buf, 0, sizeof(buf)); n = (struct nlmsghdr *)buf; n->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); n->nlmsg_flags = NLM_F_REQUEST; if (cmd == RTM_NEWROUTE) { n->nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; } n->nlmsg_type = cmd; rtm = NLMSG_DATA(n); rtm->rtm_family = AF_INET6; rtm->rtm_dst_len = dst_plen; rtm->rtm_src_len = src_plen; rtm->rtm_table = table; rtm->rtm_protocol = proto; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_flags = flags; addattr_l(n, sizeof(buf), RTA_DST, dst, sizeof(*dst)); if (src) addattr_l(n, sizeof(buf), RTA_SRC, src, sizeof(*src)); addattr32(n, sizeof(buf), RTA_OIF, oif); if (gateway) addattr_l(n, sizeof(buf), RTA_GATEWAY, gateway, sizeof(*gateway)); if (priority) addattr32(n, sizeof(buf), RTA_PRIORITY, priority); return rtnl_route_do(n, NULL); }
static int veth_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *hdr) { char *dev = NULL; char *name = NULL; char *link = NULL; char *type = NULL; int index = 0; int err, len; struct rtattr * data; int group; struct ifinfomsg *ifm, *peer_ifm; unsigned int ifi_flags, ifi_change; if (strcmp(argv[0], "peer") != 0) { usage(); return -1; } ifm = NLMSG_DATA(hdr); ifi_flags = ifm->ifi_flags; ifi_change = ifm->ifi_change; ifm->ifi_flags = 0; ifm->ifi_change = 0; data = NLMSG_TAIL(hdr); addattr_l(hdr, 1024, VETH_INFO_PEER, NULL, 0); hdr->nlmsg_len += sizeof(struct ifinfomsg); err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr, &name, &type, &link, &dev, &group, &index); if (err < 0) return err; if (name) { len = strlen(name) + 1; if (len > IFNAMSIZ) invarg("\"name\" too long\n", *argv); addattr_l(hdr, 1024, IFLA_IFNAME, name, len); } peer_ifm = RTA_DATA(data); peer_ifm->ifi_index = index; peer_ifm->ifi_flags = ifm->ifi_flags; peer_ifm->ifi_change = ifm->ifi_change; ifm->ifi_flags = ifi_flags; ifm->ifi_change = ifi_change; if (group != -1) addattr32(hdr, 1024, IFLA_GROUP, group); data->rta_len = (void *)NLMSG_TAIL(hdr) - (void *)data; return argc - 1 - err; }
/* Routing table change via netlink interface. */ int netlink_route (int cmd, int family, void *dest, int length, void *gate, int index, int zebra_flags, int table) { int ret; int bytelen; struct sockaddr_nl snl; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; memset (&req, 0, sizeof req); bytelen = (family == AF_INET ? 4 : 16); req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.r.rtm_family = family; req.r.rtm_table = table; req.r.rtm_dst_len = length; if (cmd == RTM_NEWROUTE) { req.r.rtm_protocol = RTPROT_ZEBRA; req.r.rtm_scope = RT_SCOPE_UNIVERSE; if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) req.r.rtm_type = RTN_BLACKHOLE; else req.r.rtm_type = RTN_UNICAST; } if (gate) addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen); if (dest) addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen); if (index > 0) addattr32 (&req.n, sizeof req, RTA_OIF, index); /* Destination netlink address. */ memset (&snl, 0, sizeof snl); snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ ret = netlink_talk (&req.n, &netlink); if (ret < 0) return -1; return 0; }
static int ipneigh_dump_filter(struct nlmsghdr *nlh, int reqlen) { struct ndmsg *ndm = NLMSG_DATA(nlh); int err; ndm->ndm_flags = filter.ndm_flags; if (filter.index) { err = addattr32(nlh, reqlen, NDA_IFINDEX, filter.index); if (err) return err; } if (filter.master) { err = addattr32(nlh, reqlen, NDA_MASTER, filter.master); if (err) return err; } return 0; }
static int delete_tunnel(struct l2tp_parm *p) { GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION, L2TP_CMD_TUNNEL_DELETE, NLM_F_REQUEST | NLM_F_ACK); addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id); if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) return -2; return 0; }
static int get_session(struct l2tp_data *p) { GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION, L2TP_CMD_SESSION_GET, NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST); req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq; if (p->config.tunnel_id && p->config.session_id) { addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->config.tunnel_id); addattr32(&req.n, 128, L2TP_ATTR_SESSION_ID, p->config.session_id); } if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0) return -2; if (rtnl_dump_filter(&genl_rth, session_nlmsg, p) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }
static int qfq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct rtattr *tail; __u32 tmp; tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "weight") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 10)) { explain1("weight"); return -1; } addattr32(n, 4096, TCA_QFQ_WEIGHT, tmp); } else if (matches(*argv, "maxpkt") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 10)) { explain1("maxpkt"); return -1; } addattr32(n, 4096, TCA_QFQ_LMAX, tmp); } else if (strcmp(*argv, "help") == 0) { explain_class(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain_class(); return -1; } argc--; argv++; } tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; return 0; }
int ipoe_nl_add_vlan_mon_vid(int ifindex, int vid) { struct rtnl_handle rth; struct nlmsghdr *nlh; struct genlmsghdr *ghdr; struct { struct nlmsghdr n; char buf[1024]; } req; int r = 0; if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC)) { log_error("ipoe: cannot open generic netlink socket\n"); return -1; } nlh = &req.n; nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_type = ipoe_genl_id; ghdr = NLMSG_DATA(&req.n); ghdr->cmd = IPOE_CMD_ADD_VLAN_MON_VID; addattr32(nlh, 1024, IPOE_ATTR_IFINDEX, ifindex); addattr32(nlh, 1024, IPOE_ATTR_ADDR, vid); if (rtnl_talk(&rth, nlh, 0, 0, nlh, NULL, NULL, 0) < 0 ) { log_error("ipoe: nl_add_vlan_mon_vid: error talking to kernel\n"); r = -1; } rtnl_close(&rth); return r; }
static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u32 mode = 0; __u16 flags = 0; while (argc > 0) { if (matches(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "private") == 0) mode = MACVLAN_MODE_PRIVATE; else if (strcmp(*argv, "vepa") == 0) mode = MACVLAN_MODE_VEPA; else if (strcmp(*argv, "bridge") == 0) mode = MACVLAN_MODE_BRIDGE; else if (strcmp(*argv, "passthru") == 0) mode = MACVLAN_MODE_PASSTHRU; else return mode_arg(*argv); } else if (matches(*argv, "nopromisc") == 0) { flags |= MACVLAN_FLAG_NOPROMISC; } else if (matches(*argv, "help") == 0) { explain(lu); return -1; } else { pfx_err(lu, "unknown option \"%s\"?", *argv); explain(lu); return -1; } argc--, argv++; } if (mode) addattr32(n, 1024, IFLA_MACVLAN_MODE, mode); if (flags) { if (flags & MACVLAN_FLAG_NOPROMISC && mode != MACVLAN_MODE_PASSTHRU) { pfx_err(lu, "nopromisc flag only valid in passthru mode"); explain(lu); return -1; } addattr16(n, 1024, IFLA_MACVLAN_FLAGS, flags); } return 0; }
static int netlink_link_setmode(vrrp_rt *vrrp) { int status = 1; struct { struct nlmsghdr n; struct ifinfomsg ifi; char buf[256]; } req; struct rtattr *linkinfo; struct rtattr *data; memset(&req, 0, sizeof (req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_NEWLINK; req.ifi.ifi_family = AF_INET; req.ifi.ifi_index = IF_INDEX(vrrp->xmit_ifp); linkinfo = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)ll_kind, strlen(ll_kind)); data = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); /* * In private mode, macvlan will receive frames with same MAC addr * as configured on the interface. */ #ifndef MACVLAN_MODE_VRRP #define MACVLAN_MODE_VRRP 16 #endif addattr32(&req.n, sizeof(req), IFLA_MACVLAN_MODE, MACVLAN_MODE_VRRP); data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; if (netlink_talk(&nl_cmd, &req.n) < 0) status = -1; return status; }
static int get_netnsid_from_name(const char *name) { struct { struct nlmsghdr n; struct rtgenmsg g; char buf[1024]; } req, answer; struct rtattr *tb[NETNSA_MAX + 1]; struct rtgenmsg *rthdr; int len, fd; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETNSID; req.g.rtgen_family = AF_UNSPEC; fd = netns_get_fd(name); if (fd < 0) return fd; addattr32(&req.n, 1024, NETNSA_FD, fd); if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) { close(fd); return -2; } close(fd); /* Validate message and parse attributes */ if (answer.n.nlmsg_type == NLMSG_ERROR) return -1; rthdr = NLMSG_DATA(&answer.n); len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr)); if (len < 0) return -1; parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len); if (tb[NETNSA_NSID]) return rta_getattr_u32(tb[NETNSA_NSID]); return -1; }
/* Add/Delete IP rule to/from a specific IP/network */ int netlink_rule(ip_rule_t *iprule, int cmd) { int status = 1; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; memset(&req, 0, sizeof (req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; req.n.nlmsg_type = cmd ? RTM_NEWRULE : RTM_DELRULE; req.r.rtm_family = IP_FAMILY(iprule->addr); if (iprule->table < 256) req.r.rtm_table = iprule->table ? iprule->table : RT_TABLE_MAIN; else { req.r.rtm_table = RT_TABLE_UNSPEC; addattr32(&req.n, sizeof(req), FRA_TABLE, iprule->table); } req.r.rtm_type = RTN_UNSPEC; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_flags = 0; if (cmd) { req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_type = RTN_UNICAST; } /* Set rule entry */ if (iprule->dir == VRRP_RULE_FROM) { req.r.rtm_src_len = iprule->mask; add_addr2req(&req.n, sizeof(req), FRA_SRC, iprule->addr); } else if (iprule->dir == VRRP_RULE_TO) { req.r.rtm_dst_len = iprule->mask; add_addr2req(&req.n, sizeof(req), FRA_DST, iprule->addr); } if (netlink_talk(&nl_cmd, &req.n) < 0) status = -1; return status; }
void TunManager::addRemoveTable(int ifIdx, RouterID rid, bool add) { // We just store default routes (one for IPv4 and one for IPv6) in each route // table. struct { struct nlmsghdr n; struct rtmsg r; char buf[256]; } req; const folly::IPAddress addrs[] = { IPAddress{"0.0.0.0"}, // v4 default IPAddress{"::0"}, // v6 default }; for (const auto& addr : addrs) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; if (add) { req.n.nlmsg_type = RTM_NEWROUTE; req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_REPLACE; } else { req.n.nlmsg_type = RTM_DELROUTE; } req.r.rtm_family = addr.family(); req.r.rtm_table = getTableId(rid); req.r.rtm_scope = RT_SCOPE_NOWHERE; req.r.rtm_protocol = RTPROT_FBOSS; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_type = RTN_UNICAST; req.r.rtm_dst_len = 0; // default route, /0 addattr_l(&req.n, sizeof(req), RTA_DST, addr.bytes(), addr.byteCount()); addattr32(&req.n, sizeof(req), RTA_OIF, ifIdx); auto ret = rtnl_talk(&rth_, &req.n, 0, 0, nullptr); sysCheckError(ret, "Failed to ", add ? "add" : "remove", " default route ", addr, " @ index ", ifIdx, " in table ", getTableId(rid), " for router ", rid); LOG(INFO) << (add ? "Added" : "Removed") << " default route " << addr << " @ index " << ifIdx << " in table " << getTableId(rid) << " for router " << rid; } }
/* Request for specific interface or address information from the kernel */ static int netlink_request_intf_addr(struct zebra_ns *zns, int family, int type, uint32_t filter_mask) { struct { struct nlmsghdr n; struct ifinfomsg ifm; char buf[256]; } req; /* Form the request, specifying filter (rtattr) if needed. */ memset(&req, 0, sizeof(req)); req.n.nlmsg_type = type; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.ifm.ifi_family = family; /* Include filter, if specified. */ if (filter_mask) addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask); return netlink_request(&zns->netlink_cmd, &req.n); }
static int modify_neigh(struct xia_xid *dst, unsigned char *lladdr, int lladdr_len, unsigned oif, int to_add) { struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); if (to_add) { /* XXX Does one really needs all these flags? */ req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; req.n.nlmsg_type = RTM_NEWROUTE; req.r.rtm_scope = RT_SCOPE_LINK; } else { req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_DELROUTE; req.r.rtm_scope = RT_SCOPE_NOWHERE; } req.r.rtm_family = AF_XIA; req.r.rtm_table = XRTABLE_MAIN_INDEX; req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_type = RTN_UNICAST; req.r.rtm_dst_len = sizeof(*dst); addattr_l(&req.n, sizeof(req), RTA_DST, dst, sizeof(*dst)); addattr_l(&req.n, sizeof(req), RTA_LLADDR, lladdr, lladdr_len); addattr32(&req.n, sizeof(req), RTA_OIF, oif); if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) exit(2); return 0; }