Rename netlink infrastructure to rtnetlink

We will introduce genetlink infrastructure just after this.
This commit is contained in:
Samuel Thibault 2023-04-18 00:07:40 +02:00
parent fdf19f5467
commit 60329986b2
3 changed files with 102 additions and 65 deletions

161
l2tpns.c
View file

@ -63,7 +63,7 @@ uint32_t call_serial_number = 0;
// Globals // Globals
configt *config = NULL; // all configuration configt *config = NULL; // all configuration
int nlfd = -1; // netlink socket int rtnlfd = -1; // route netlink socket
int tunfd = -1; // tun interface file handle. (network device) int tunfd = -1; // tun interface file handle. (network device)
int udpfd[MAX_UDPFD + 1] = INIT_TABUDPFD; // array UDP file handle + 1 for lac udp int udpfd[MAX_UDPFD + 1] = INIT_TABUDPFD; // array UDP file handle + 1 for lac udp
int udplacfd = -1; // UDP LAC file handle int udplacfd = -1; // UDP LAC file handle
@ -78,8 +78,8 @@ int epollfd = -1; // event polling
time_t basetime = 0; // base clock time_t basetime = 0; // base clock
char hostname[MAXHOSTNAME] = ""; // us. char hostname[MAXHOSTNAME] = ""; // us.
static int tunidx; // ifr_ifindex of tun device static int tunidx; // ifr_ifindex of tun device
int nlseqnum = 0; // netlink sequence number int rtnlseqnum = 0; // route netlink sequence number
int min_initok_nlseqnum = 0; // minimun seq number for messages after init is ok int min_initok_rtnlseqnum = 0; // minimun seq number for messages after init is ok
static int syslog_log = 0; // are we logging to syslog static int syslog_log = 0; // are we logging to syslog
FILE *log_stream = 0; // file handle for direct logging (i.e. direct into file, not via syslog). FILE *log_stream = 0; // file handle for direct logging (i.e. direct into file, not via syslog).
uint32_t last_id = 0; // Unique ID for radius accounting uint32_t last_id = 0; // Unique ID for radius accounting
@ -240,8 +240,9 @@ struct Tstats *_statistics = NULL;
struct Tringbuffer *ringbuffer = NULL; struct Tringbuffer *ringbuffer = NULL;
#endif #endif
static ssize_t netlink_send(struct nlmsghdr *nh); static ssize_t rtnetlink_send(struct nlmsghdr *nh);
static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen); static int netlink_handle_ack(struct nlmsghdr *nh, int min_initok_nlseqnum, char *tun_nl_phase_msg[]);
static void rtnetlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
static void cache_ipmap(in_addr_t ip, sessionidt s); static void cache_ipmap(in_addr_t ip, sessionidt s);
static void uncache_ipmap(in_addr_t ip); static void uncache_ipmap(in_addr_t ip);
static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s); static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s);
@ -497,20 +498,20 @@ static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, in
req.rt.rtm_scope = RT_SCOPE_LINK; req.rt.rtm_scope = RT_SCOPE_LINK;
req.rt.rtm_type = RTN_UNICAST; req.rt.rtm_type = RTN_UNICAST;
netlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int)); rtnetlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int));
n_ip = htonl(ip); n_ip = htonl(ip);
netlink_addattr(&req.nh, RTA_DST, &n_ip, sizeof(n_ip)); rtnetlink_addattr(&req.nh, RTA_DST, &n_ip, sizeof(n_ip));
if (gw) if (gw)
{ {
n_ip = htonl(gw); n_ip = htonl(gw);
netlink_addattr(&req.nh, RTA_GATEWAY, &n_ip, sizeof(n_ip)); rtnetlink_addattr(&req.nh, RTA_GATEWAY, &n_ip, sizeof(n_ip));
} }
LOG(1, s, session[s].tunnel, "Route %s %s/%d%s%s\n", add ? "add" : "del", LOG(1, s, session[s].tunnel, "Route %s %s/%d%s%s\n", add ? "add" : "del",
fmtaddr(htonl(ip), 0), prefixlen, fmtaddr(htonl(ip), 0), prefixlen,
gw ? " via" : "", gw ? fmtaddr(htonl(gw), 2) : ""); gw ? " via" : "", gw ? fmtaddr(htonl(gw), 2) : "");
if (netlink_send(&req.nh) < 0) if (rtnetlink_send(&req.nh) < 0)
LOG(0, 0, 0, "routeset() error in sending netlink message: %s\n", strerror(errno)); LOG(0, 0, 0, "routeset() error in sending netlink message: %s\n", strerror(errno));
#ifdef BGP #ifdef BGP
@ -576,17 +577,17 @@ void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add)
req.rt.rtm_scope = RT_SCOPE_LINK; req.rt.rtm_scope = RT_SCOPE_LINK;
req.rt.rtm_type = RTN_UNICAST; req.rt.rtm_type = RTN_UNICAST;
netlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int)); rtnetlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int));
netlink_addattr(&req.nh, RTA_DST, &ip, sizeof(ip)); rtnetlink_addattr(&req.nh, RTA_DST, &ip, sizeof(ip));
metric = 1; metric = 1;
netlink_addattr(&req.nh, RTA_METRICS, &metric, sizeof(metric)); rtnetlink_addattr(&req.nh, RTA_METRICS, &metric, sizeof(metric));
LOG(1, s, session[s].tunnel, "Route %s %s/%d\n", LOG(1, s, session[s].tunnel, "Route %s %s/%d\n",
add ? "add" : "del", add ? "add" : "del",
inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN), inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN),
prefixlen); prefixlen);
if (netlink_send(&req.nh) < 0) if (rtnetlink_send(&req.nh) < 0)
LOG(0, 0, 0, "route6set() error in sending netlink message: %s\n", strerror(errno)); LOG(0, 0, 0, "route6set() error in sending netlink message: %s\n", strerror(errno));
#ifdef BGP #ifdef BGP
@ -613,10 +614,10 @@ static void initnetlink(void)
{ {
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); rtnlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nlfd < 0) if (rtnlfd < 0)
{ {
LOG(0, 0, 0, "Can't create netlink socket: %s\n", strerror(errno)); LOG(0, 0, 0, "Can't create route netlink socket: %s\n", strerror(errno));
exit(1); exit(1);
} }
@ -624,21 +625,23 @@ static void initnetlink(void)
nladdr.nl_family = AF_NETLINK; nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid(); nladdr.nl_pid = getpid();
if (bind(nlfd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) if (bind(rtnlfd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0)
{ {
LOG(0, 0, 0, "Can't bind netlink socket: %s\n", strerror(errno)); LOG(0, 0, 0, "Can't bind route netlink socket: %s\n", strerror(errno));
exit(1); exit(1);
} }
} }
static ssize_t netlink_send(struct nlmsghdr *nh) //
// Send message to a netlink socket
static ssize_t netlink_send(int fd, int *seqnum, struct nlmsghdr *nh)
{ {
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
struct iovec iov; struct iovec iov;
struct msghdr msg; struct msghdr msg;
nh->nlmsg_pid = getpid(); nh->nlmsg_pid = getpid();
nh->nlmsg_seq = ++nlseqnum; nh->nlmsg_seq = ++*seqnum;
// set kernel address // set kernel address
memset(&nladdr, 0, sizeof(nladdr)); memset(&nladdr, 0, sizeof(nladdr));
@ -647,10 +650,19 @@ static ssize_t netlink_send(struct nlmsghdr *nh)
iov = (struct iovec){ (void *)nh, nh->nlmsg_len }; iov = (struct iovec){ (void *)nh, nh->nlmsg_len };
msg = (struct msghdr){ (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; msg = (struct msghdr){ (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 };
return sendmsg(nlfd, &msg, 0); return sendmsg(fd, &msg, 0);
} }
static ssize_t netlink_recv(void *buf, ssize_t len) //
// Send message to the route netlink socket
static ssize_t rtnetlink_send(struct nlmsghdr *nh)
{
return netlink_send(rtnlfd, &rtnlseqnum, nh);
}
//
// Receive a message from a netlink socket
static ssize_t netlink_recv(int fd, void *buf, ssize_t len)
{ {
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
struct iovec iov; struct iovec iov;
@ -663,11 +675,52 @@ static ssize_t netlink_recv(void *buf, ssize_t len)
iov = (struct iovec){ buf, len }; iov = (struct iovec){ buf, len };
msg = (struct msghdr){ (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; msg = (struct msghdr){ (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 };
return recvmsg(nlfd, &msg, 0); return recvmsg(fd, &msg, 0);
} }
//
// Receive a message from the route netlink socket
static ssize_t rtnetlink_recv(void *buf, ssize_t len)
{
return netlink_recv(rtnlfd, buf, len);
}
//
// Look ack netlink message for errors
static int netlink_handle_ack(struct nlmsghdr *nh, int min_initok_nlseqnum, char *tun_nl_phase_msg[])
{
if (nh->nlmsg_type == NLMSG_ERROR)
{
struct nlmsgerr *errmsg = NLMSG_DATA(nh);
if (errmsg->error)
{
if (errmsg->msg.nlmsg_seq < min_initok_nlseqnum)
{
LOG(0, 0, 0, "Got a fatal netlink error (while %s): %s\n", tun_nl_phase_msg[nh->nlmsg_seq], strerror(-errmsg->error));
exit(1);
}
else
{
LOG(0, 0, 0, "For netlink request %d, got a netlink error: %s\n", errmsg->msg.nlmsg_type, strerror(-errmsg->error));
errno = -errmsg->error;
return -1;
}
}
// else it's an ack
return 0;
}
else
{
LOG(1, 0, 0, "Got an unknown netlink message: type %d seq %d flags %d\n", nh->nlmsg_type, nh->nlmsg_seq, nh->nlmsg_flags);
errno = EIO;
return -1;
}
}
//
// Add an attribute to a message for a route netlink socket
/* adapted from iproute2 */ /* adapted from iproute2 */
static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) static void rtnetlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen)
{ {
int len = RTA_LENGTH(alen); int len = RTA_LENGTH(alen);
struct rtattr *rta; struct rtattr *rta;
@ -680,7 +733,7 @@ static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int
} }
// messages corresponding to different phases seq number // messages corresponding to different phases seq number
static char *tun_nl_phase_msg[] = { static char *tun_rtnl_phase_msg[] = {
"initialized", "initialized",
"getting tun interface index", "getting tun interface index",
"setting tun interface parameters", "setting tun interface parameters",
@ -753,12 +806,12 @@ static void inittun(void)
/* Bump up the qlen to deal with bursts from the network */ /* Bump up the qlen to deal with bursts from the network */
txqlen = 1000; txqlen = 1000;
netlink_addattr(&req.nh, IFLA_TXQLEN, &txqlen, sizeof(txqlen)); rtnetlink_addattr(&req.nh, IFLA_TXQLEN, &txqlen, sizeof(txqlen));
/* set MTU to modem MRU */ /* set MTU to modem MRU */
mtu = MRU; mtu = MRU;
netlink_addattr(&req.nh, IFLA_MTU, &mtu, sizeof(mtu)); rtnetlink_addattr(&req.nh, IFLA_MTU, &mtu, sizeof(mtu));
if (netlink_send(&req.nh) < 0) if (rtnetlink_send(&req.nh) < 0)
goto senderror; goto senderror;
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
@ -778,8 +831,8 @@ static void inittun(void)
for (i = 0; i < config->nbmultiaddress ; i++) for (i = 0; i < config->nbmultiaddress ; i++)
{ {
ip = config->iftun_n_address[i]; ip = config->iftun_n_address[i];
netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); rtnetlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip));
if (netlink_send(&req.nh) < 0) if (rtnetlink_send(&req.nh) < 0)
goto senderror; goto senderror;
} }
} }
@ -789,9 +842,9 @@ static void inittun(void)
ip = config->iftun_address; ip = config->iftun_address;
else else
ip = 0x01010101; // 1.1.1.1 ip = 0x01010101; // 1.1.1.1
netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); rtnetlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip));
if (netlink_send(&req.nh) < 0) if (rtnetlink_send(&req.nh) < 0)
goto senderror; goto senderror;
} }
@ -817,9 +870,9 @@ static void inittun(void)
ip6.s6_addr[0] = 0xFE; ip6.s6_addr[0] = 0xFE;
ip6.s6_addr[1] = 0x80; ip6.s6_addr[1] = 0x80;
ip6.s6_addr[15] = 1; ip6.s6_addr[15] = 1;
netlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6)); rtnetlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6));
if (netlink_send(&req.nh) < 0) if (rtnetlink_send(&req.nh) < 0)
goto senderror; goto senderror;
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
@ -836,9 +889,9 @@ static void inittun(void)
// Global address is prefix::1 // Global address is prefix::1
ip6 = config->ipv6_prefix; ip6 = config->ipv6_prefix;
ip6.s6_addr[15] = 1; ip6.s6_addr[15] = 1;
netlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6)); rtnetlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6));
if (netlink_send(&req.nh) < 0) if (rtnetlink_send(&req.nh) < 0)
goto senderror; goto senderror;
} }
@ -847,15 +900,15 @@ static void inittun(void)
req.nh.nlmsg_type = NLMSG_DONE; req.nh.nlmsg_type = NLMSG_DONE;
req.nh.nlmsg_len = NLMSG_LENGTH(0); req.nh.nlmsg_len = NLMSG_LENGTH(0);
if (netlink_send(&req.nh) < 0) if (rtnetlink_send(&req.nh) < 0)
goto senderror; goto senderror;
// if we get an error for seqnum < min_initok_nlseqnum, // if we get an error for seqnum < min_initok_nlseqnum,
// we must exit as initialization went wrong // we must exit as initialization went wrong
if (config->ipv6_prefix.s6_addr[0]) if (config->ipv6_prefix.s6_addr[0])
min_initok_nlseqnum = 5 + 1; // idx + if + addr + 2*addr6 min_initok_rtnlseqnum = 5 + 1; // idx + if + addr + 2*addr6
else else
min_initok_nlseqnum = 3 + 1; // idx + if + addr min_initok_rtnlseqnum = 3 + 1; // idx + if + addr
} }
return; return;
@ -4135,8 +4188,8 @@ static void mainloop(void)
exit(1); exit(1);
} }
LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, nlfd=%d , udplacfd=%d, pppoefd=%d, pppoesessfd=%d\n", LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, rtnlfd=%d , udplacfd=%d, pppoefd=%d, pppoesessfd=%d\n",
clifd, cluster_sockfd, tunfd, udpfd[0], controlfd, daefd, nlfd, udplacfd, pppoediscfd, pppoesessfd); clifd, cluster_sockfd, tunfd, udpfd[0], controlfd, daefd, rtnlfd, udplacfd, pppoediscfd, pppoesessfd);
/* setup our fds to poll for input */ /* setup our fds to poll for input */
{ {
@ -4169,9 +4222,9 @@ static void mainloop(void)
e.data.ptr = &d[i++]; e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, daefd, &e); epoll_ctl(epollfd, EPOLL_CTL_ADD, daefd, &e);
d[i].type = FD_TYPE_NETLINK; d[i].type = FD_TYPE_RTNETLINK;
e.data.ptr = &d[i++]; e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, nlfd, &e); epoll_ctl(epollfd, EPOLL_CTL_ADD, rtnlfd, &e);
d[i].type = FD_TYPE_PPPOEDISC; d[i].type = FD_TYPE_PPPOEDISC;
e.data.ptr = &d[i++]; e.data.ptr = &d[i++];
@ -4334,27 +4387,11 @@ static void mainloop(void)
break; break;
#endif /* BGP */ #endif /* BGP */
case FD_TYPE_NETLINK: case FD_TYPE_RTNETLINK:
{ {
struct nlmsghdr *nh = (struct nlmsghdr *)p; struct nlmsghdr *nh = (struct nlmsghdr *)p;
s = netlink_recv(p, size_bufp); s = rtnetlink_recv(p, size_bufp);
if (nh->nlmsg_type == NLMSG_ERROR) netlink_handle_ack(nh, min_initok_rtnlseqnum, tun_rtnl_phase_msg);
{
struct nlmsgerr *errmsg = NLMSG_DATA(nh);
if (errmsg->error)
{
if (errmsg->msg.nlmsg_seq < min_initok_nlseqnum)
{
LOG(0, 0, 0, "Got a fatal netlink error (while %s): %s\n", tun_nl_phase_msg[nh->nlmsg_seq], strerror(-errmsg->error));
exit(1);
}
else
LOG(0, 0, 0, "Got a netlink error: %s\n", strerror(-errmsg->error));
}
// else it's a ack
}
else
LOG(1, 0, 0, "Got a unknown netlink message: type %d seq %d flags %d\n", nh->nlmsg_type, nh->nlmsg_seq, nh->nlmsg_flags);
n--; n--;
break; break;
} }

View file

@ -1037,7 +1037,7 @@ extern uint32_t last_id;
extern struct Tstats *_statistics; extern struct Tstats *_statistics;
extern in_addr_t my_address; extern in_addr_t my_address;
extern int clifd; extern int clifd;
extern int nlfd; extern int rtnlfd;
extern int epollfd; extern int epollfd;
extern FILE *log_stream; extern FILE *log_stream;
@ -1051,7 +1051,7 @@ struct event_data {
FD_TYPE_DAE, FD_TYPE_DAE,
FD_TYPE_RADIUS, FD_TYPE_RADIUS,
FD_TYPE_BGP, FD_TYPE_BGP,
FD_TYPE_NETLINK, FD_TYPE_RTNETLINK,
FD_TYPE_PPPOEDISC, FD_TYPE_PPPOEDISC,
FD_TYPE_PPPOESESS FD_TYPE_PPPOESESS
} type; } type;

2
util.c
View file

@ -120,7 +120,7 @@ pid_t fork_and_close()
close(bgp_peers[i].sock); close(bgp_peers[i].sock);
#endif /* BGP */ #endif /* BGP */
if (nlfd != -1) close(nlfd); if (rtnlfd != -1) close(rtnlfd);
if (pppoediscfd != -1) close(pppoediscfd); if (pppoediscfd != -1) close(pppoediscfd);
if (pppoesessfd != -1) close(pppoesessfd); if (pppoesessfd != -1) close(pppoesessfd);