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 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 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; }
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; }
int genl_resolve_family(struct rtnl_handle *grth, const char *family) { GENL_REQUEST(req, 1024, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, NLM_F_REQUEST); struct nlmsghdr *answer; int fnum; addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1); if (rtnl_talk(grth, &req.n, &answer) < 0) { fprintf(stderr, "Error talking to the kernel\n"); return -2; } fnum = genl_parse_getfamily(answer); free(answer); return fnum; }
static int get_tunnel(struct l2tp_data *p) { GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION, L2TP_CMD_TUNNEL_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) addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id); if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0) return -2; if (rtnl_dump_filter(&genl_rth, tunnel_nlmsg, p) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } return 0; }