Index: lib/Makefile =================================================================== --- lib/Makefile +++ lib/Makefile @@ -78,6 +78,7 @@ libproc \ libprocstat \ libregex \ + libroute \ librpcsvc \ librss \ librt \ Index: lib/libroute/Makefile =================================================================== --- /dev/null +++ lib/libroute/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +PACKAGE= lib${LIB} +LIB= route +INTERNALLIB= true + +SHLIBDIR?= /lib +SHLIB_MAJOR= 1 +SRCS= libroute.c + +#MAN= libroute.3 + +CFLAGS+= -I${.CURDIR} +NO_WCAST_ALIGN= yes + +.include Index: lib/libroute/libroute.h =================================================================== --- /dev/null +++ lib/libroute/libroute.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Ahsan Barkati + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct rt_msg_t { + struct rt_msghdr m_rtm; + char m_space[512]; +} rt_msg_t; + +typedef struct rt_handle_t rt_handle; + +rt_handle* libroute_open(int); +void libroute_close(rt_handle*); +int libroute_modify(rt_handle*, struct rt_msg_t*, struct sockaddr*, struct sockaddr*, int, int); +int libroute_add(rt_handle*, struct sockaddr*, struct sockaddr*); +int libroute_change(rt_handle*, struct sockaddr*, struct sockaddr*); +int libroute_del(rt_handle*, struct sockaddr*); +int libroute_get(rt_handle*, struct sockaddr*); +int libroute_setfib(rt_handle *, int); +int libroute_errno(rt_handle *); +struct sockaddr* str_to_sockaddr(rt_handle *h, char *); +struct sockaddr* str_to_sockaddr6(rt_handle *h, char *); + Index: lib/libroute/libroute.c =================================================================== --- /dev/null +++ lib/libroute/libroute.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2020 Ahsan Barkati + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include "libroute.h" + +static void fill_rtmsg(rt_handle*, struct rt_msg_t*, int, int); +static void fillso(rt_handle *, int, struct sockaddr*); + +struct rt_handle_t { + int fib; + int s; + struct sockaddr_storage so[RTAX_MAX]; + int rtm_addrs; + int errcode; +}; + +rt_handle * +libroute_open(int fib) +{ + rt_handle *h; + h = calloc(1, sizeof(*h)); + if (h == NULL) { + h->errcode = errno; + return NULL; + } + h->s = socket(PF_ROUTE, SOCK_RAW, 0); + if (h->s < 0){ + h->errcode = errno; + } + if (libroute_setfib(h, fib)){ + h->errcode = errno; + } + if (h->errcode) { + free(h); + return (NULL); + } + return (h); +} + +void libroute_close(rt_handle *h) +{ + free(h); +} + + +int +libroute_errno(rt_handle *h) +{ + return (h->errcode); +} + + +int +libroute_setfib(rt_handle *h, int fib) +{ + h->fib = fib; + if (setsockopt(h->s, SOL_SOCKET, SO_SETFIB, (void *)&(h->fib), + sizeof(h->fib)) < 0) { + h->errcode = errno; + return (-1); + } + return (0); +} + +struct sockaddr* +str_to_sockaddr(rt_handle *h, char *str) +{ + struct sockaddr* sa; + struct sockaddr_in *sin; + sa = calloc(1, sizeof(*sa)); + if (sa == NULL) { + h->errcode = errno; + return NULL; + } + + sa->sa_family = AF_INET; + sa->sa_len = sizeof(struct sockaddr_in); + sin = (struct sockaddr_in *)(void *)sa; + if (inet_aton(str, &sin->sin_addr) == 0) { + free(sa); + return NULL; + } + return (sa); +} + +struct sockaddr* +str_to_sockaddr6(rt_handle *h, char *str) +{ + struct sockaddr* sa; + struct addrinfo hints, *res; + + sa = calloc(1, sizeof(*sa)); + if (sa == NULL) { + h->errcode = errno; + return NULL; + } + sa->sa_family = AF_INET6; + sa->sa_len = sizeof(struct sockaddr_in6); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = sa->sa_family; + hints.ai_socktype = SOCK_DGRAM; + if (getaddrinfo(str, NULL, &hints, &res)) { + free(sa); + return NULL; + } + memcpy(sa, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + return (sa); +} + +static void +fillso(rt_handle *h, int idx, struct sockaddr* sa_in) +{ + struct sockaddr *sa; + h->rtm_addrs |= (1 << idx); + sa = (struct sockaddr *)&(h->so[idx]); + memcpy(sa, sa_in, sa_in->sa_len); + return; +} + +int +libroute_modify(rt_handle *h, struct rt_msg_t *rtmsg, struct sockaddr* sa_dest, + struct sockaddr* sa_gateway, int operation, int flags) +{ + int rlen, l; + fillso(h, RTAX_DST, sa_dest); + + if (sa_gateway != NULL) { + fillso(h, RTAX_GATEWAY, sa_gateway); + } + + if (operation == RTM_GET) { + if (h->so[RTAX_IFP].ss_family == 0) { + h->so[RTAX_IFP].ss_family = AF_LINK; + h->so[RTAX_IFP].ss_len = sizeof(struct sockaddr_dl); + h->rtm_addrs |= RTA_IFP; + } + } + + fill_rtmsg(h, rtmsg, operation, flags); + l = (rtmsg->m_rtm).rtm_msglen; + + if (( rlen = write(h->s, (char *)rtmsg, l)) < 0) { + h->errcode = errno; + return (-1); + } + + if (operation == RTM_GET) { + if (( l = read(h->s, (char *)rtmsg, sizeof(*rtmsg))) < 0 ) { + h->errcode = errno; + return (-1); + } + } + + return (0); +} + +int +libroute_add(rt_handle *h, struct sockaddr* dest, struct sockaddr* gateway){ + struct rt_msg_t rtmsg; + int flags; + + memset(&rtmsg, 0, sizeof(struct rt_msg_t)); + flags = RTF_STATIC; + flags |= RTF_UP; + flags |= RTF_HOST; + flags |= RTF_GATEWAY; + + return (libroute_modify(h, &rtmsg, dest, gateway, RTM_ADD, flags)); +} + +int +libroute_change(rt_handle *h, struct sockaddr* dest, struct sockaddr* gateway){ + struct rt_msg_t rtmsg; + int flags; + + memset(&rtmsg, 0, sizeof(struct rt_msg_t)); + flags = RTF_STATIC; + flags |= RTF_UP; + flags |= RTF_HOST; + flags |= RTF_GATEWAY; + + return (libroute_modify(h, &rtmsg, dest, gateway, RTM_CHANGE, flags)); +} + +int +libroute_del(rt_handle *h, struct sockaddr* dest){ + struct rt_msg_t rtmsg; + int flags; + + memset(&rtmsg, 0, sizeof(struct rt_msg_t)); + flags = RTF_STATIC; + flags |= RTF_UP; + flags |= RTF_HOST; + flags |= RTF_GATEWAY; + return (libroute_modify(h, &rtmsg, dest, NULL, RTM_DELETE, flags)); +} + +int +libroute_get(rt_handle *h, struct sockaddr* dest){ + struct rt_msg_t rtmsg; + int flags; + + memset(&rtmsg, 0, sizeof(struct rt_msg_t)); + flags = RTF_STATIC; + flags |= RTF_UP; + flags |= RTF_HOST; + return (libroute_modify(h, &rtmsg, dest, NULL, RTM_GET, flags)); +} + +static void +fill_rtmsg(rt_handle *h, struct rt_msg_t *rtmsg_t, int operation, int flags) +{ + rt_msg_t* rtmsg = rtmsg_t; + char *cp = rtmsg->m_space; + int l, rtm_seq = 0; + struct sockaddr_storage *so = h->so; + static struct rt_metrics rt_metrics; + static u_long rtm_inits; + + memset(rtmsg, 0, sizeof(struct rt_msg_t)); + +#define NEXTADDR(w, u) \ + if ((h->rtm_addrs) & (w)) { \ + l = SA_SIZE(&(u)); \ + memmove(cp, (char *)&(u), l); \ + cp += l; \ + } + +#define rtm rtmsg->m_rtm + rtm.rtm_type = operation; + rtm.rtm_flags = flags; + rtm.rtm_version = RTM_VERSION; + rtm.rtm_seq = ++rtm_seq; + rtm.rtm_addrs = h->rtm_addrs; + rtm.rtm_rmx = rt_metrics; + rtm.rtm_inits = rtm_inits; + + NEXTADDR(RTA_DST, so[RTAX_DST]); + NEXTADDR(RTA_GATEWAY, so[RTAX_GATEWAY]); + NEXTADDR(RTA_NETMASK, so[RTAX_NETMASK]); + NEXTADDR(RTA_GENMASK, so[RTAX_GENMASK]); + NEXTADDR(RTA_IFP, so[RTAX_IFP]); + NEXTADDR(RTA_IFA, so[RTAX_IFA]); + rtm.rtm_msglen = l = cp - (char *)rtmsg; +#undef rtm + return; +} \ No newline at end of file Index: rescue/rescue/Makefile =================================================================== --- rescue/rescue/Makefile +++ rescue/rescue/Makefile @@ -227,6 +227,9 @@ CRUNCH_LIBS+= ${OBJTOP}/lib/libifconfig/libifconfig.a CRUNCH_BUILDOPTS+= CRUNCH_CFLAGS+=-I${OBJTOP}/lib/libifconfig +CRUNCH_LIBS+= ${OBJTOP}/lib/libroute/libroute.a +CRUNCH_BUILDOPTS+= CRUNCH_CFLAGS+=-I${OBJTOP}/lib/libroute + .if ${MK_ISCSI} != "no" CRUNCH_PROGS_usr.bin+= iscsictl CRUNCH_PROGS_usr.sbin+= iscsid Index: sbin/route/Makefile =================================================================== --- sbin/route/Makefile +++ sbin/route/Makefile @@ -10,6 +10,9 @@ WARNS?= 3 CLEANFILES+=keywords.h +CFLAGS+= -I${SRCTOP}/lib/libroute +LIBADD+= route + CFLAGS+= -DNS .if ${MK_INET_SUPPORT} != "no" CFLAGS+= -DINET Index: sbin/route/route.c =================================================================== --- sbin/route/route.c +++ sbin/route/route.c @@ -73,6 +73,7 @@ #include #include #include +#include struct fibl { TAILQ_ENTRY(fibl) fl_next; @@ -103,15 +104,9 @@ static int numfibs; static char domain[MAXHOSTNAMELEN + 1]; static bool domain_initialized; -static int rtm_seq; static char rt_line[NI_MAXHOST]; static char net_line[MAXHOSTNAMELEN + 1]; -static struct { - struct rt_msghdr m_rtm; - char m_space[512]; -} m_rtmsg; - static TAILQ_HEAD(fibl_head_t, fibl) fibl_head; static void printb(int, const char *); @@ -130,14 +125,12 @@ static void monitor(int, char*[]); static const char *netname(struct sockaddr *); static void newroute(int, char **); -static int newroute_fib(int, char *, int); static void pmsg_addrs(char *, int, size_t); static void pmsg_common(struct rt_msghdr *, size_t); static int prefixlen(const char *); static void print_getmsg(struct rt_msghdr *, int, int); static void print_rtmsg(struct rt_msghdr *, size_t); static const char *routename(struct sockaddr *); -static int rtmsg(int, int, int); static void set_metric(char *, int); static int set_sofib(int); static void sockaddr(char *, struct sockaddr *, size_t); @@ -790,6 +783,9 @@ static void newroute(int argc, char **argv) { + rt_handle *h; + struct rt_msg_t rtmsg_local; + int operation; struct sigaction sa; struct hostent *hp; struct fibl *fl; @@ -1009,13 +1005,37 @@ if (error) errx(EX_OSERR, "fiboptlist_csv failed."); } + + + if (cmd[0] == 'a') + operation = RTM_ADD; + else if (cmd[0] == 'c') + operation = RTM_CHANGE; + else if (cmd[0] == 'g' || cmd[0] == 's') + operation = RTM_GET; + else + operation = RTM_DELETE; + error = 0; + h = libroute_open(defaultfib); + if(h == NULL){ + errx(EX_OSERR, "Failed to open libroute handle"); + } TAILQ_FOREACH(fl, &fibl_head, fl_next) { - fl->fl_error = newroute_fib(fl->fl_num, cmd, flags); + libroute_setfib(h, fl->fl_num); + fl->fl_error = libroute_modify(h, &rtmsg_local, + (struct sockaddr *)&so[RTAX_DST], + (struct sockaddr *)&so[RTAX_GATEWAY], operation, flags); if (fl->fl_error) fl->fl_errno = errno; error += fl->fl_error; + + if(operation == RTM_GET && fl->fl_error == 0){ + print_getmsg(&rtmsg_local.m_rtm, rtmsg_local.m_rtm.rtm_msglen, + fl->fl_num); + } } + libroute_close(h); if (*cmd == 'g' || *cmd == 's') exit(error); @@ -1096,21 +1116,6 @@ exit(error); } -static int -newroute_fib(int fib, char *cmd, int flags) -{ - int error; - - error = set_sofib(fib); - if (error) { - warn("fib number %d is ignored", fib); - return (error); - } - - error = rtmsg(*cmd, flags, fib); - return (error); -} - #ifdef INET static void inet_makenetandmask(u_long net, struct sockaddr_in *sin, @@ -1494,97 +1499,6 @@ } } -static int -rtmsg(int cmd, int flags, int fib) -{ - int rlen; - char *cp = m_rtmsg.m_space; - int l; - -#define NEXTADDR(w, u) \ - if (rtm_addrs & (w)) { \ - l = SA_SIZE(&(u)); \ - memmove(cp, (char *)&(u), l); \ - cp += l; \ - if (verbose) \ - sodump((struct sockaddr *)&(u), #w); \ - } - - errno = 0; - memset(&m_rtmsg, 0, sizeof(m_rtmsg)); - if (cmd == 'a') - cmd = RTM_ADD; - else if (cmd == 'c') - cmd = RTM_CHANGE; - else if (cmd == 'g' || cmd == 's') { - cmd = RTM_GET; - if (so[RTAX_IFP].ss_family == 0) { - so[RTAX_IFP].ss_family = AF_LINK; - so[RTAX_IFP].ss_len = sizeof(struct sockaddr_dl); - rtm_addrs |= RTA_IFP; - } - } else { - cmd = RTM_DELETE; - flags |= RTF_PINNED; - } -#define rtm m_rtmsg.m_rtm - rtm.rtm_type = cmd; - rtm.rtm_flags = flags; - rtm.rtm_version = RTM_VERSION; - rtm.rtm_seq = ++rtm_seq; - rtm.rtm_addrs = rtm_addrs; - rtm.rtm_rmx = rt_metrics; - rtm.rtm_inits = rtm_inits; - - NEXTADDR(RTA_DST, so[RTAX_DST]); - NEXTADDR(RTA_GATEWAY, so[RTAX_GATEWAY]); - NEXTADDR(RTA_NETMASK, so[RTAX_NETMASK]); - NEXTADDR(RTA_GENMASK, so[RTAX_GENMASK]); - NEXTADDR(RTA_IFP, so[RTAX_IFP]); - NEXTADDR(RTA_IFA, so[RTAX_IFA]); - rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; - if (verbose) - print_rtmsg(&rtm, l); - if (debugonly) - return (0); - if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { - switch (errno) { - case EPERM: - err(1, "writing to routing socket"); - break; - case ESRCH: - warnx("route has not been found"); - break; - case EEXIST: - /* Handled by newroute() */ - break; - default: - warn("writing to routing socket"); - } - return (-1); - } - if (cmd == RTM_GET) { - stop_read = 0; - alarm(READ_TIMEOUT); - do { - l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); - } while (l > 0 && stop_read == 0 && - (rtm.rtm_type != RTM_GET || rtm.rtm_seq != rtm_seq || - rtm.rtm_pid != pid)); - if (stop_read != 0) { - warnx("read from routing socket timed out"); - return (-1); - } else - alarm(0); - if (l < 0) - warn("read from routing socket"); - else - print_getmsg(&rtm, l, fib); - } -#undef rtm - return (0); -} - static const char *const msgtypes[] = { "", "RTM_ADD: Add Route", Index: share/mk/src.libnames.mk =================================================================== --- share/mk/src.libnames.mk +++ share/mk/src.libnames.mk @@ -58,6 +58,7 @@ parse \ pe \ pmcstat \ + route \ sl \ sm \ smdb \ @@ -577,6 +578,9 @@ LIBC_NOSSP_PICDIR= ${_LIB_OBJTOP}/lib/libc LIBC_NOSSP_PIC?= ${LIBC_NOSSP_PICDIR}/libc_nossp_pic.a +LIBROUTEDIR= ${_LIB_OBJTOP}/lib/libroute +LIBROUTE?= ${LIBROUTEDIR}/libroute${PIE_SUFFIX}.a + # Define a directory for each library. This is useful for adding -L in when # not using a --sysroot or for meta mode bootstrapping when there is no # Makefile.depend. These are sorted by directory.