Add tool: route.

This commit ports FreeBSD `route` to F-Stack, can be used to set the route
table.
This commit is contained in:
logwang 2017-06-14 15:25:35 +08:00
parent 488adaba23
commit 144c6bcd95
22 changed files with 4028 additions and 20 deletions

View File

@ -16,7 +16,7 @@ LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread
TARGET="helloworld"
all:
cc -O -gdwarf-2 -I../lib -o ${TARGET} main.c ${LIBS}
cc -O -gdwarf-2 -g -I../lib -o ${TARGET} main.c ${LIBS}
.PHONY: clean
clean:

View File

@ -129,7 +129,8 @@ FF_SRCS+= \
ff_subr_prf.c \
ff_vfs_ops.c \
ff_veth.c \
ff_epoll.c
ff_epoll.c \
ff_route.c
FF_HOST_SRCS+= \
ff_host_interface.c \

View File

@ -33,6 +33,7 @@ extern "C" {
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include "ff_event.h"
#include "ff_errno.h"
@ -102,6 +103,34 @@ int ff_kqueue(void);
int ff_kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout);
/* route api begin */
enum FF_ROUTE_CTL {
FF_ROUTE_ADD,
FF_ROUTE_DEL,
FF_ROUTE_CHANGE,
};
enum FF_ROUTE_FLAG {
FF_RTF_HOST,
FF_RTF_GATEWAY,
};
/*
* On success, 0 is returned.
* On error, -1 is returned, and errno is set appropriately.
*/
int ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag,
struct linux_sockaddr *dst, struct linux_sockaddr *gw,
struct linux_sockaddr *netmask);
/*
* This is used in handling ff_msg.
* The data is a pointer to struct rt_msghdr.
*/
int ff_rtioctl(int fib, void *data, unsigned *plen, unsigned maxlen);
/* route api end */
#ifdef __cplusplus
}
#endif

View File

@ -41,3 +41,5 @@ ff_mbuf_get
ff_mbuf_free
ff_mbuf_copydata
ff_mbuf_tx_offload
ff_route_ctl
ff_rtioctl

View File

@ -721,7 +721,7 @@ init_port_start(void)
}
if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
return 0;
continue;
}
/* Currently, proc id 1:1 map to queue id per port. */
@ -852,18 +852,19 @@ ff_veth_input(const struct ff_dpdk_if_context *ctx, struct rte_mbuf *pkt)
return;
}
pkt = pkt->next;
struct rte_mbuf *pn = pkt->next;
void *prev = hdr;
while(pkt != NULL) {
while(pn != NULL) {
data = rte_pktmbuf_mtod(pkt, void*);
len = rte_pktmbuf_data_len(pkt);
void *mb = ff_mbuf_get(prev, data, len);
if (mb == NULL) {
ff_mbuf_free(hdr);
rte_pktmbuf_free(pkt);
return;
}
pkt = pkt->next;
pn = pn->next;
prev = mb;
}
@ -1004,6 +1005,15 @@ done:
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
}
static inline void
handle_route_msg(struct ff_msg *msg, uint16_t proc_id)
{
msg->result = ff_rtioctl(msg->route.fib, msg->route.data,
&msg->route.len, msg->route.maxlen);
rte_ring_enqueue(msg_ring[proc_id].ring[1], msg);
}
static inline void
handle_default_msg(struct ff_msg *msg, uint16_t proc_id)
{
@ -1021,6 +1031,9 @@ handle_msg(struct ff_msg *msg, uint16_t proc_id)
case FF_IOCTL:
handle_ioctl_msg(msg, proc_id);
break;
case FF_ROUTE:
handle_route_msg(msg, proc_id);
break;
default:
handle_default_msg(msg, proc_id);
break;

View File

@ -38,6 +38,7 @@ enum FF_MSG_TYPE {
FF_UNKNOWN = 0,
FF_SYSCTL,
FF_IOCTL,
FF_ROUTE,
};
struct ff_sysctl_args {
@ -54,6 +55,13 @@ struct ff_ioctl_args {
void *data;
};
struct ff_route_args {
int fib;
unsigned len;
unsigned maxlen;
void *data;
};
#define MAX_MSG_BUF_SIZE 10240
/* structure of ipc msg */
@ -69,6 +77,7 @@ struct ff_msg {
union {
struct ff_sysctl_args sysctl;
struct ff_ioctl_args ioctl;
struct ff_route_args route;
};
} __attribute__((packed)) __rte_cache_aligned;

733
lib/ff_route.c Normal file
View File

@ -0,0 +1,733 @@
/*
* Copyright (c) 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
* Copyright (C) 2017 THL A29 Limited, a Tencent company.
* All rights reserved.
*
* 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* 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.
*
* Copied part from FreeBSD rtsock.c.
*
*/
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/domain.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <net/route_var.h>
#include <netinet/if_ether.h>
#include "ff_api.h"
#include "ff_host_interface.h"
#ifndef _SOCKADDR_UNION_DEFINED
#define _SOCKADDR_UNION_DEFINED
/*
* The union of all possible address formats we handle.
*/
union sockaddr_union {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
};
#endif /* _SOCKADDR_UNION_DEFINED */
static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
struct walkarg {
int w_tmemsize;
int w_op, w_arg;
caddr_t w_tmem;
struct sysctl_req *w_req;
};
static int
rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp,
struct rtentry *rt, union sockaddr_union *saun, struct ucred *cred)
{
/* First, see if the returned address is part of the jail. */
if (prison_if(cred, rt->rt_ifa->ifa_addr) == 0) {
info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
return (0);
}
switch (info->rti_info[RTAX_DST]->sa_family) {
#ifdef INET
case AF_INET:
{
struct in_addr ia;
struct ifaddr *ifa;
int found;
found = 0;
/*
* Try to find an address on the given outgoing interface
* that belongs to the jail.
*/
IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa;
sa = ifa->ifa_addr;
if (sa->sa_family != AF_INET)
continue;
ia = ((struct sockaddr_in *)sa)->sin_addr;
if (prison_check_ip4(cred, &ia) == 0) {
found = 1;
break;
}
}
IF_ADDR_RUNLOCK(ifp);
if (!found) {
/*
* As a last resort return the 'default' jail address.
*/
ia = ((struct sockaddr_in *)rt->rt_ifa->ifa_addr)->
sin_addr;
if (prison_get_ip4(cred, &ia) != 0)
return (ESRCH);
}
bzero(&saun->sin, sizeof(struct sockaddr_in));
saun->sin.sin_len = sizeof(struct sockaddr_in);
saun->sin.sin_family = AF_INET;
saun->sin.sin_addr.s_addr = ia.s_addr;
info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin;
break;
}
#endif
#ifdef INET6
case AF_INET6:
{
struct in6_addr ia6;
struct ifaddr *ifa;
int found;
found = 0;
/*
* Try to find an address on the given outgoing interface
* that belongs to the jail.
*/
IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa;
sa = ifa->ifa_addr;
if (sa->sa_family != AF_INET6)
continue;
bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
&ia6, sizeof(struct in6_addr));
if (prison_check_ip6(cred, &ia6) == 0) {
found = 1;
break;
}
}
IF_ADDR_RUNLOCK(ifp);
if (!found) {
/*
* As a last resort return the 'default' jail address.
*/
ia6 = ((struct sockaddr_in6 *)rt->rt_ifa->ifa_addr)->
sin6_addr;
if (prison_get_ip6(cred, &ia6) != 0)
return (ESRCH);
}
bzero(&saun->sin6, sizeof(struct sockaddr_in6));
saun->sin6.sin6_len = sizeof(struct sockaddr_in6);
saun->sin6.sin6_family = AF_INET6;
bcopy(&ia6, &saun->sin6.sin6_addr, sizeof(struct in6_addr));
if (sa6_recoverscope(&saun->sin6) != 0)
return (ESRCH);
info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin6;
break;
}
#endif
default:
return (ESRCH);
}
return (0);
}
/*
* Extract the addresses of the passed sockaddrs.
* Do a little sanity checking so as to avoid bad memory references.
* This data is derived straight from userland.
*/
static int
rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
{
struct sockaddr *sa;
int i;
for (i = 0; i < RTAX_MAX && cp < cplim; i++) {
if ((rtinfo->rti_addrs & (1 << i)) == 0)
continue;
sa = (struct sockaddr *)cp;
/*
* It won't fit.
*/
if (cp + sa->sa_len > cplim)
return (EINVAL);
/*
* there are no more.. quit now
* If there are more bits, they are in error.
* I've seen this. route(1) can evidently generate these.
* This causes kernel to core dump.
* for compatibility, If we see this, point to a safe address.
*/
if (sa->sa_len == 0) {
rtinfo->rti_info[i] = &sa_zero;
return (0); /* should be EINVAL but for compat */
}
/* accept it */
#ifdef INET6
if (sa->sa_family == AF_INET6)
sa6_embedscope((struct sockaddr_in6 *)sa,
V_ip6_use_defzone);
#endif
rtinfo->rti_info[i] = sa;
cp += SA_SIZE(sa);
}
return (0);
}
/*
* Writes information related to @rtinfo object to preallocated buffer.
* Stores needed size in @plen. If @w is NULL, calculates size without
* writing.
* Used for sysctl dumps and rtsock answers (RTM_DEL/RTM_GET) generation.
*
* Returns 0 on success.
*
*/
static int
rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int *plen)
{
int i;
int len, buflen = 0, dlen;
caddr_t cp = NULL;
struct rt_msghdr *rtm = NULL;
#ifdef INET6
struct sockaddr_storage ss;
struct sockaddr_in6 *sin6;
#endif
switch (type) {
case RTM_DELADDR:
case RTM_NEWADDR:
if (w != NULL && w->w_op == NET_RT_IFLISTL) {
#ifdef COMPAT_FREEBSD32
if (w->w_req->flags & SCTL_MASK32)
len = sizeof(struct ifa_msghdrl32);
else
#endif
len = sizeof(struct ifa_msghdrl);
} else
len = sizeof(struct ifa_msghdr);
break;
case RTM_IFINFO:
#ifdef COMPAT_FREEBSD32
if (w != NULL && w->w_req->flags & SCTL_MASK32) {
if (w->w_op == NET_RT_IFLISTL)
len = sizeof(struct if_msghdrl32);
else
len = sizeof(struct if_msghdr32);
break;
}
#endif
if (w != NULL && w->w_op == NET_RT_IFLISTL)
len = sizeof(struct if_msghdrl);
else
len = sizeof(struct if_msghdr);
break;
case RTM_NEWMADDR:
len = sizeof(struct ifma_msghdr);
break;
default:
len = sizeof(struct rt_msghdr);
}
if (w != NULL) {
rtm = (struct rt_msghdr *)w->w_tmem;
buflen = w->w_tmemsize - len;
cp = (caddr_t)w->w_tmem + len;
}
rtinfo->rti_addrs = 0;
for (i = 0; i < RTAX_MAX; i++) {
struct sockaddr *sa;
if ((sa = rtinfo->rti_info[i]) == NULL)
continue;
rtinfo->rti_addrs |= (1 << i);
dlen = SA_SIZE(sa);
if (cp != NULL && buflen >= dlen) {
#ifdef INET6
if (V_deembed_scopeid && sa->sa_family == AF_INET6) {
sin6 = (struct sockaddr_in6 *)&ss;
bcopy(sa, sin6, sizeof(*sin6));
if (sa6_recoverscope(sin6) == 0)
sa = (struct sockaddr *)sin6;
}
#endif
bcopy((caddr_t)sa, cp, (unsigned)dlen);
cp += dlen;
buflen -= dlen;
} else if (cp != NULL) {
/*
* Buffer too small. Count needed size
* and return with error.
*/
cp = NULL;
}
len += dlen;
}
if (cp != NULL) {
dlen = ALIGN(len) - len;
if (buflen < dlen)
cp = NULL;
else
buflen -= dlen;
}
len = ALIGN(len);
if (cp != NULL) {
/* fill header iff buffer is large enough */
rtm->rtm_version = RTM_VERSION;
rtm->rtm_type = type;
rtm->rtm_msglen = len;
}
*plen = len;
if (w != NULL && cp == NULL)
return (ENOBUFS);
return (0);
}
/*
* Fill in @dmask with valid netmask leaving original @smask
* intact. Mostly used with radix netmasks.
*/
static struct sockaddr *
rtsock_fix_netmask(struct sockaddr *dst, struct sockaddr *smask,
struct sockaddr_storage *dmask)
{
if (dst == NULL || smask == NULL)
return (NULL);
memset(dmask, 0, dst->sa_len);
memcpy(dmask, smask, smask->sa_len);
dmask->ss_len = dst->sa_len;
dmask->ss_family = dst->sa_family;
return ((struct sockaddr *)dmask);
}
static void
rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out)
{
bzero(out, sizeof(*out));
out->rmx_mtu = rt->rt_mtu;
out->rmx_weight = rt->rt_weight;
out->rmx_pksent = counter_u64_fetch(rt->rt_pksent);
/* Kernel -> userland timebase conversion. */
out->rmx_expire = rt->rt_expire ?
rt->rt_expire - time_uptime + time_second : 0;
}
int
ff_rtioctl(int fibnum, void *data, unsigned *plen, unsigned maxlen)
{
struct rt_msghdr *rtm = NULL;
struct rtentry *rt = NULL;
struct rib_head *rnh;
struct rt_addrinfo info;
union sockaddr_union saun;
sa_family_t saf = AF_UNSPEC;
struct sockaddr_storage ss;
struct walkarg w;
int error = 0, alloc_len = 0, len;
struct ifnet *ifp = NULL;
#ifdef INET6
struct sockaddr_in6 *sin6;
int i, rti_need_deembed = 0;
#endif
#define senderr(e) { error = e; goto flush;}
len = *plen;
/*
* Most of current messages are in range 200-240 bytes,
* minimize possible re-allocation on reply using larger size
* buffer aligned on 1k boundaty.
*/
alloc_len = roundup2(len, 1024);
if ((rtm = malloc(alloc_len, M_TEMP, M_NOWAIT)) == NULL)
senderr(ENOBUFS);
bcopy(data, (caddr_t)rtm, len);
if (len < sizeof(*rtm) || len != rtm->rtm_msglen)
senderr(EINVAL);
bzero(&info, sizeof(info));
bzero(&w, sizeof(w));
if (rtm->rtm_version != RTM_VERSION)
senderr(EPROTONOSUPPORT);
/*
* Starting from here, it is possible
* to alter original message and insert
* caller PID and error value.
*/
rtm->rtm_pid = curproc->p_pid;
info.rti_addrs = rtm->rtm_addrs;
info.rti_mflags = rtm->rtm_inits;
info.rti_rmx = &rtm->rtm_rmx;
/*
* rt_xaddrs() performs s6_addr[2] := sin6_scope_id for AF_INET6
* link-local address because rtrequest requires addresses with
* embedded scope id.
*/
if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info))
senderr(EINVAL);
info.rti_flags = rtm->rtm_flags;
if (info.rti_info[RTAX_DST] == NULL ||
info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
(info.rti_info[RTAX_GATEWAY] != NULL &&
info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
senderr(EINVAL);
saf = info.rti_info[RTAX_DST]->sa_family;
/*
* The given gateway address may be an interface address.
* For example, issuing a "route change" command on a route
* entry that was created from a tunnel, and the gateway
* address given is the local end point. In this case the
* RTF_GATEWAY flag must be cleared or the destination will
* not be reachable even though there is no error message.
*/
if (info.rti_info[RTAX_GATEWAY] != NULL &&
info.rti_info[RTAX_GATEWAY]->sa_family != AF_LINK) {
struct rt_addrinfo ginfo;
struct sockaddr *gdst;
bzero(&ginfo, sizeof(ginfo));
bzero(&ss, sizeof(ss));
ss.ss_len = sizeof(ss);
ginfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&ss;
gdst = info.rti_info[RTAX_GATEWAY];
/*
* A host route through the loopback interface is
* installed for each interface adddress. In pre 8.0
* releases the interface address of a PPP link type
* is not reachable locally. This behavior is fixed as
* part of the new L2/L3 redesign and rewrite work. The
* signature of this interface address route is the
* AF_LINK sa_family type of the rt_gateway, and the
* rt_ifp has the IFF_LOOPBACK flag set.
*/
if (rib_lookup_info(fibnum, gdst, NHR_REF, 0, &ginfo) == 0) {
if (ss.ss_family == AF_LINK &&
ginfo.rti_ifp->if_flags & IFF_LOOPBACK) {
info.rti_flags &= ~RTF_GATEWAY;
info.rti_flags |= RTF_GWFLAG_COMPAT;
}
rib_free_info(&ginfo);
}
}
switch (rtm->rtm_type) {
struct rtentry *saved_nrt;
case RTM_ADD:
case RTM_CHANGE:
if (info.rti_info[RTAX_GATEWAY] == NULL)
senderr(EINVAL);
saved_nrt = NULL;
/* support for new ARP code */
if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK &&
(rtm->rtm_flags & RTF_LLDATA) != 0) {
error = lla_rt_output(rtm, &info);
#ifdef INET6
if (error == 0)
rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
#endif
break;
}
error = rtrequest1_fib(rtm->rtm_type, &info, &saved_nrt,
fibnum);
if (error == 0 && saved_nrt != NULL) {
#ifdef INET6
rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
#endif
RT_LOCK(saved_nrt);
rtm->rtm_index = saved_nrt->rt_ifp->if_index;
RT_REMREF(saved_nrt);
RT_UNLOCK(saved_nrt);
}
break;
case RTM_DELETE:
saved_nrt = NULL;
/* support for new ARP code */
if (info.rti_info[RTAX_GATEWAY] &&
(info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) &&
(rtm->rtm_flags & RTF_LLDATA) != 0) {
error = lla_rt_output(rtm, &info);
#ifdef INET6
if (error == 0)
rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
#endif
break;
}
error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt, fibnum);
if (error == 0) {
RT_LOCK(saved_nrt);
rt = saved_nrt;
goto report;
}
#ifdef INET6
/* rt_msg2() will not be used when RTM_DELETE fails. */
rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
#endif
break;
case RTM_GET:
rnh = rt_tables_get_rnh(fibnum, saf);
if (rnh == NULL)
senderr(EAFNOSUPPORT);
RIB_RLOCK(rnh);
if (info.rti_info[RTAX_NETMASK] == NULL &&
rtm->rtm_type == RTM_GET) {
/*
* Provide logest prefix match for
* address lookup (no mask).
* 'route -n get addr'
*/
rt = (struct rtentry *) rnh->rnh_matchaddr(
info.rti_info[RTAX_DST], &rnh->head);
} else
rt = (struct rtentry *) rnh->rnh_lookup(
info.rti_info[RTAX_DST],
info.rti_info[RTAX_NETMASK], &rnh->head);
if (rt == NULL) {
RIB_RUNLOCK(rnh);
senderr(ESRCH);
}
#ifdef RADIX_MPATH
/*
* for RTM_CHANGE/LOCK, if we got multipath routes,
* we require users to specify a matching RTAX_GATEWAY.
*
* for RTM_GET, gate is optional even with multipath.
* if gate == NULL the first match is returned.
* (no need to call rt_mpath_matchgate if gate == NULL)
*/
if (rt_mpath_capable(rnh) &&
(rtm->rtm_type != RTM_GET || info.rti_info[RTAX_GATEWAY])) {
rt = rt_mpath_matchgate(rt, info.rti_info[RTAX_GATEWAY]);
if (!rt) {
RIB_RUNLOCK(rnh);
senderr(ESRCH);
}
}
#endif
/*
* If performing proxied L2 entry insertion, and
* the actual PPP host entry is found, perform
* another search to retrieve the prefix route of
* the local end point of the PPP link.
*/
if (rtm->rtm_flags & RTF_ANNOUNCE) {
struct sockaddr laddr;
if (rt->rt_ifp != NULL &&
rt->rt_ifp->if_type == IFT_PROPVIRTUAL) {
struct ifaddr *ifa;
ifa = ifa_ifwithnet(info.rti_info[RTAX_DST], 1,
RT_ALL_FIBS);
if (ifa != NULL)
rt_maskedcopy(ifa->ifa_addr,
&laddr,
ifa->ifa_netmask);
} else
rt_maskedcopy(rt->rt_ifa->ifa_addr,
&laddr,
rt->rt_ifa->ifa_netmask);
/*
* refactor rt and no lock operation necessary
*/
rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr,
&rnh->head);
if (rt == NULL) {
RIB_RUNLOCK(rnh);
senderr(ESRCH);
}
}
RT_LOCK(rt);
RT_ADDREF(rt);
RIB_RUNLOCK(rnh);
report:
RT_LOCK_ASSERT(rt);
if ((rt->rt_flags & RTF_HOST) == 0
? jailed_without_vnet(curthread->td_ucred)
: prison_if(curthread->td_ucred,
rt_key(rt)) != 0) {
RT_UNLOCK(rt);
senderr(ESRCH);
}
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt),
rt_mask(rt), &ss);
info.rti_info[RTAX_GENMASK] = 0;
if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
ifp = rt->rt_ifp;
if (ifp) {
info.rti_info[RTAX_IFP] =
ifp->if_addr->ifa_addr;
error = rtm_get_jailed(&info, ifp, rt,
&saun, curthread->td_ucred);
if (error != 0) {
RT_UNLOCK(rt);
senderr(error);
}
if (ifp->if_flags & IFF_POINTOPOINT)
info.rti_info[RTAX_BRD] =
rt->rt_ifa->ifa_dstaddr;
rtm->rtm_index = ifp->if_index;
} else {
info.rti_info[RTAX_IFP] = NULL;
info.rti_info[RTAX_IFA] = NULL;
}
} else if ((ifp = rt->rt_ifp) != NULL) {
rtm->rtm_index = ifp->if_index;
}
/* Check if we need to realloc storage */
rtsock_msg_buffer(rtm->rtm_type, &info, NULL, &len);
if (len > maxlen) {
RT_UNLOCK(rt);
senderr(ENOBUFS);
}
if (len > alloc_len) {
struct rt_msghdr *new_rtm;
new_rtm = malloc(len, M_TEMP, M_NOWAIT);
if (new_rtm == NULL) {
RT_UNLOCK(rt);
senderr(ENOBUFS);
}
bcopy(rtm, new_rtm, rtm->rtm_msglen);
free(rtm, M_TEMP);
rtm = new_rtm;
alloc_len = len;
}
w.w_tmem = (caddr_t)rtm;
w.w_tmemsize = alloc_len;
rtsock_msg_buffer(rtm->rtm_type, &info, &w, &len);
if (rt->rt_flags & RTF_GWFLAG_COMPAT)
rtm->rtm_flags = RTF_GATEWAY |
(rt->rt_flags & ~RTF_GWFLAG_COMPAT);
else
rtm->rtm_flags = rt->rt_flags;
rt_getmetrics(rt, &rtm->rtm_rmx);
rtm->rtm_addrs = info.rti_addrs;
RT_UNLOCK(rt);
break;
default:
senderr(EOPNOTSUPP);
}
flush:
if (rt != NULL)
RTFREE(rt);
if (rtm != NULL) {
#ifdef INET6
if (rti_need_deembed) {
/* sin6_scope_id is recovered before sending rtm. */
sin6 = (struct sockaddr_in6 *)&ss;
for (i = 0; i < RTAX_MAX; i++) {
if (info.rti_info[i] == NULL)
continue;
if (info.rti_info[i]->sa_family != AF_INET6)
continue;
bcopy(info.rti_info[i], sin6, sizeof(*sin6));
if (sa6_recoverscope(sin6) == 0)
bcopy(sin6, info.rti_info[i],
sizeof(*sin6));
}
}
#endif
if (error != 0)
rtm->rtm_errno = error;
else
rtm->rtm_flags |= RTF_DONE;
bcopy((caddr_t)rtm, data, rtm->rtm_msglen);
*plen = rtm->rtm_msglen;
free(rtm, M_TEMP);
}
return (error);
}

View File

@ -50,6 +50,7 @@
#include <sys/filio.h>
#include <sys/sysproto.h>
#include <sys/fcntl.h>
#include <net/route.h>
#include <machine/stdarg.h>
@ -258,7 +259,7 @@ so_opt_convert(int optname)
case LINUX_SO_PROTOCOL:
return SO_PROTOCOL;
default:
return (-1);
return optname;
}
}
@ -285,7 +286,7 @@ ip_opt_convert(int optname)
case LINUX_IP_DROP_MEMBERSHIP:
return IP_DROP_MEMBERSHIP;
default:
return (-1);
return optname;
}
}
@ -306,7 +307,7 @@ tcp_opt_convert(int optname)
case LINUX_TCP_MD5SIG:
return TCP_MD5SIG;
default:
return (-1);
return optname;
}
}
@ -321,7 +322,7 @@ linux2freebsd_opt(int level, int optname)
case IPPROTO_TCP:
return tcp_opt_convert(optname);
default:
return (-1);
return optname;
}
}
@ -1002,3 +1003,76 @@ kern_fail:
ff_os_errno(rc);
return (-1);
}
int
ff_route_ctl(enum FF_ROUTE_CTL req, enum FF_ROUTE_FLAG flag,
struct linux_sockaddr *dst, struct linux_sockaddr *gw,
struct linux_sockaddr *netmask)
{
struct sockaddr sa_gw, sa_dst, sa_nm;
struct sockaddr *psa_gw, *psa_dst, *psa_nm;
int rtreq, rtflag;
int rc;
switch (req) {
case FF_ROUTE_ADD:
rtreq = RTM_ADD;
break;
case FF_ROUTE_DEL:
rtreq = RTM_DELETE;
break;
case FF_ROUTE_CHANGE:
rtreq = RTM_CHANGE;
break;
default:
rc = EINVAL;
goto kern_fail;
}
switch (flag) {
case FF_RTF_HOST:
rtflag = RTF_HOST;
break;
case FF_RTF_GATEWAY:
rtflag = RTF_GATEWAY;
break;
default:
rc = EINVAL;
goto kern_fail;
};
if (gw != NULL) {
psa_gw = &sa_gw;
linux2freebsd_sockaddr(gw, sizeof(*gw), psa_gw);
} else {
psa_gw = NULL;
}
if (dst != NULL) {
psa_dst = &sa_dst;
linux2freebsd_sockaddr(dst, sizeof(*dst), psa_dst);
} else {
psa_dst = NULL;
}
if (netmask != NULL) {
psa_nm = &sa_nm;
linux2freebsd_sockaddr(netmask, sizeof(*netmask), psa_nm);
} else {
psa_nm = NULL;
}
rc = rtrequest_fib(rtreq, psa_dst, psa_gw, psa_nm, rtflag,
NULL, RT_DEFAULT_FIB);
if (rc != 0)
goto kern_fail;
return (rc);
kern_fail:
ff_os_errno(rc);
return (-1);
}

View File

@ -1,4 +1,4 @@
SUBDIRS=compat sysctl ifconfig
SUBDIRS=compat sysctl ifconfig route
all:
for d in $(SUBDIRS); do ( cd $$d; $(MAKE) all ) ; done

View File

@ -39,6 +39,52 @@ jail
```
For more details, see [Manual page](https://www.freebsd.org/cgi/man.cgi?ifconfig).
# route
Usage:
```
route -p <f-stack proc_id> [-46dnqtv] command [[modifiers] args]
```
Examples:
```
Add a default route:
./route -p 0 add -net 0.0.0.0/0 192.168.1.1
A shorter version of adding a default route can also be written as:
./route -p 0 add default 192.168.1.1
Add a static route to the 172.16.10.0/24 network via the 172.16.1.1 gate-
way:
./route -p 0 add -net 172.16.10.0/24 172.16.1.1
Change the gateway of an already established static route in the routing
table:
./route -p 0 change -net 172.16.10.0/24 172.16.1.2
Display the route for a destination network:
./route -p 0 show 172.16.10.0
Delete a static route from the routing table:
./route -p 0 delete -net 172.16.10.0/24 172.16.1.2
Remove all routes from the routing table:
./route -p 0 flush
FreeBSD uses `netstat -rn ` to list the route table which we havn't ported,
you can execute the following command instead, `-d` means debug mode, `-v`
means verbose.
./route -p 0 -d -v flush
```
Note that, if you want to modify the route table, you must use `-p` to execute the same command for each f-stack process.
For more details, see [Manual page](https://www.freebsd.org/cgi/man.cgi?route).
# how to implement a custom tool for communicating with F-Stack process
Add a new FF_MSG_TYPE in ff_msg.h:

View File

@ -29,6 +29,22 @@
#include <stddef.h>
#ifndef __dead2
#define __dead2 __attribute__((__noreturn__))
#endif
#ifndef __dead
#define __dead __dead2
#endif
#ifndef nitems
#define nitems(x) (sizeof((x)) / sizeof((x)[0]))
#endif
#ifndef __FBSDID
#define __FBSDID(s) /* nothing */
#endif
void *reallocf(void *ptr, size_t size);
int feature_present(const char *feature);

View File

@ -61,7 +61,7 @@ ff_ipc_init(void)
char *dpdk_argv[] = {
"ff-ipc", "-c1", "-n4",
"--proc-type=secondary",
/* RTE_LOG_ERR */
/* RTE_LOG_WARNING */
"--log-level=5",
};

150
tools/compat/getopt.c Normal file
View File

@ -0,0 +1,150 @@
/* $NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* 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.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
#ifndef FSTACK
__FBSDID("$FreeBSD$");
#include "namespace.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef FSTACK
#include "un-namespace.h"
#include "libc_private.h"
#endif
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(int nargc, char * const nargv[], const char *ostr)
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (optreset || *place == 0) { /* update scanning pointer */
optreset = 0;
place = nargv[optind];
if (optind >= nargc || *place++ != '-') {
/* Argument is absent or is not an option */
place = EMSG;
return (-1);
}
optopt = *place++;
if (optopt == '-' && *place == 0) {
/* "--" => end of options */
++optind;
place = EMSG;
return (-1);
}
if (optopt == 0) {
/* Solitary '-', treat as a '-' option
if the program (eg su) is looking for it. */
place = EMSG;
if (strchr(ostr, '-') == NULL)
return (-1);
optopt = '-';
}
} else
optopt = *place++;
/* See if option letter is one the caller wanted... */
if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
if (*place == 0)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
#ifndef FSTACK
"%s: illegal option -- %c\n", _getprogname(),
#else
"illegal option -- %c\n",
#endif
optopt);
return (BADCH);
}
/* Does this option need an argument? */
if (oli[1] != ':') {
/* don't need argument */
optarg = NULL;
if (*place == 0)
++optind;
} else {
/* Option-argument is either the rest of this argument or the
entire next argument. */
if (*place)
optarg = place;
else if (oli[2] == ':')
/*
* GNU Extension, for optional arguments if the rest of
* the argument is empty, we return NULL
*/
optarg = NULL;
else if (nargc > ++optind)
optarg = nargv[optind];
else {
/* option-argument absent */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
#ifndef FSTACK
"%s: option requires an argument -- %c\n",
_getprogname(), optopt);
#else
"option requires an argument -- %c\n", optopt);
#endif
return (BADCH);
}
place = EMSG;
++optind;
}
return (optopt); /* return option letter */
}

View File

@ -125,6 +125,12 @@ int inet_pton(int, const char * __restrict, void * __restrict);
int inet_aton(const char *, struct in_addr *);
in_addr_t inet_lnaof(struct in_addr);
struct in_addr inet_makeaddr(in_addr_t, in_addr_t);
char * inet_neta(in_addr_t, char *, size_t);
in_addr_t inet_netof(struct in_addr);
in_addr_t inet_network(const char *);
#endif /* !_ARPA_INET_H_ */
/*! \file */

View File

@ -0,0 +1,116 @@
/*-
* Copyright (c) 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* 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.
*
* @(#)if_arp.h 8.1 (Berkeley) 6/10/93
* $FreeBSD$
*/
#ifndef _NET_IF_ARP_H_
#define _NET_IF_ARP_H_
/*
* Address Resolution Protocol.
*
* See RFC 826 for protocol description. ARP packets are variable
* in size; the arphdr structure defines the fixed-length portion.
* Protocol type values are the same as those for 10 Mb/s Ethernet.
* It is followed by the variable-sized fields ar_sha, arp_spa,
* arp_tha and arp_tpa in that order, according to the lengths
* specified. Field names used correspond to RFC 826.
*/
struct arphdr {
u_short ar_hrd; /* format of hardware address */
#define ARPHRD_ETHER 1 /* ethernet hardware format */
#define ARPHRD_IEEE802 6 /* token-ring hardware format */
#define ARPHRD_ARCNET 7 /* arcnet hardware format */
#define ARPHRD_FRELAY 15 /* frame relay hardware format */
#define ARPHRD_IEEE1394 24 /* firewire hardware format */
#define ARPHRD_INFINIBAND 32 /* infiniband hardware format */
u_short ar_pro; /* format of protocol address */
u_char ar_hln; /* length of hardware address */
u_char ar_pln; /* length of protocol address */
u_short ar_op; /* one of: */
#define ARPOP_REQUEST 1 /* request to resolve address */
#define ARPOP_REPLY 2 /* response to previous request */
#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */
#define ARPOP_REVREPLY 4 /* response giving protocol address */
#define ARPOP_INVREQUEST 8 /* request to identify peer */
#define ARPOP_INVREPLY 9 /* response identifying peer */
/*
* The remaining fields are variable in size,
* according to the sizes above.
*/
#ifdef COMMENT_ONLY
u_char ar_sha[]; /* sender hardware address */
u_char ar_spa[]; /* sender protocol address */
u_char ar_tha[]; /* target hardware address */
u_char ar_tpa[]; /* target protocol address */
#endif
};
#define ar_sha(ap) (((caddr_t)((ap)+1)) + 0)
#define ar_spa(ap) (((caddr_t)((ap)+1)) + (ap)->ar_hln)
#define ar_tha(ap) (((caddr_t)((ap)+1)) + (ap)->ar_hln + (ap)->ar_pln)
#define ar_tpa(ap) (((caddr_t)((ap)+1)) + 2*(ap)->ar_hln + (ap)->ar_pln)
#define arphdr_len2(ar_hln, ar_pln) \
(sizeof(struct arphdr) + 2*(ar_hln) + 2*(ar_pln))
#define arphdr_len(ap) (arphdr_len2((ap)->ar_hln, (ap)->ar_pln))
/*
* ARP ioctl request
*/
struct arpreq {
struct sockaddr arp_pa; /* protocol address */
struct sockaddr arp_ha; /* hardware address */
int arp_flags; /* flags */
};
/* arp_flags and at_flags field values */
#define ATF_INUSE 0x01 /* entry in use */
#define ATF_COM 0x02 /* completed entry (enaddr valid) */
#define ATF_PERM 0x04 /* permanent entry */
#define ATF_PUBL 0x08 /* publish entry (respond for other host) */
#define ATF_USETRAILERS 0x10 /* has requested trailers */
struct arpstat {
/* Normal things that happen: */
uint64_t txrequests; /* # of ARP requests sent by this host. */
uint64_t txreplies; /* # of ARP replies sent by this host. */
uint64_t rxrequests; /* # of ARP requests received by this host. */
uint64_t rxreplies; /* # of ARP replies received by this host. */
uint64_t received; /* # of ARP packets received by this host. */
uint64_t arp_spares[4]; /* For either the upper or lower half. */
/* Abnormal event and error counting: */
uint64_t dropped; /* # of packets dropped waiting for a reply. */
uint64_t timeouts; /* # of times with entries removed */
/* due to timeout. */
uint64_t dupips; /* # of duplicate IPs detected. */
};
#endif /* !_NET_IF_ARP_H_ */

View File

@ -0,0 +1,111 @@
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* 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.
*
* @(#)if_ether.h 8.3 (Berkeley) 5/2/95
* $FreeBSD$
*/
#ifndef _NETINET_IF_ETHER_H_
#define _NETINET_IF_ETHER_H_
#include <net/ethernet.h>
#include <net/if_arp.h>
/*
* Macro to map an IP multicast address to an Ethernet multicast address.
* The high-order 25 bits of the Ethernet address are statically assigned,
* and the low-order 23 bits are taken from the low end of the IP address.
*/
#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \
/* struct in_addr *ipaddr; */ \
/* u_char enaddr[ETHER_ADDR_LEN]; */ \
{ \
(enaddr)[0] = 0x01; \
(enaddr)[1] = 0x00; \
(enaddr)[2] = 0x5e; \
(enaddr)[3] = ((const u_char *)ipaddr)[1] & 0x7f; \
(enaddr)[4] = ((const u_char *)ipaddr)[2]; \
(enaddr)[5] = ((const u_char *)ipaddr)[3]; \
}
/*
* Macro to map an IP6 multicast address to an Ethernet multicast address.
* The high-order 16 bits of the Ethernet address are statically assigned,
* and the low-order 32 bits are taken from the low end of the IP6 address.
*/
#define ETHER_MAP_IPV6_MULTICAST(ip6addr, enaddr) \
/* struct in6_addr *ip6addr; */ \
/* u_char enaddr[ETHER_ADDR_LEN]; */ \
{ \
(enaddr)[0] = 0x33; \
(enaddr)[1] = 0x33; \
(enaddr)[2] = ((const u_char *)ip6addr)[12]; \
(enaddr)[3] = ((const u_char *)ip6addr)[13]; \
(enaddr)[4] = ((const u_char *)ip6addr)[14]; \
(enaddr)[5] = ((const u_char *)ip6addr)[15]; \
}
/*
* Ethernet Address Resolution Protocol.
*
* See RFC 826 for protocol description. Structure below is adapted
* to resolving internet addresses. Field names used correspond to
* RFC 826.
*/
struct ether_arp {
struct arphdr ea_hdr; /* fixed-size header */
u_char arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */
u_char arp_spa[4]; /* sender protocol address */
u_char arp_tha[ETHER_ADDR_LEN]; /* target hardware address */
u_char arp_tpa[4]; /* target protocol address */
};
#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ea_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
#define arp_pln ea_hdr.ar_pln
#define arp_op ea_hdr.ar_op
#ifndef BURN_BRIDGES /* Can be used by third party software. */
struct sockaddr_inarp {
u_char sin_len;
u_char sin_family;
u_short sin_port;
struct in_addr sin_addr;
struct in_addr sin_srcaddr;
u_short sin_tos;
u_short sin_other;
#define SIN_PROXY 1
};
#endif /* !BURN_BRIDGES */
/*
* IP and ethernet specific routing flags
*/
#define RTF_USETRAILERS RTF_PROTO1 /* use trailers */
#define RTF_ANNOUNCE RTF_PROTO2 /* announce new arp entry */
#endif

View File

@ -49,10 +49,6 @@ int fake_close(int fd);
#define socket(a, b, c) fake_socket((a), (b), (c))
#define close(a) fake_close((a))
#ifndef nitems
#define nitems(x) (sizeof((x)) / sizeof((x)[0]))
#endif
#endif
struct afswtch;

View File

@ -35,7 +35,9 @@ SRCS= ${PROG}.c
endif
endif
OBJS+= $(patsubst %.cc,%.o,$(patsubst %.c,%.o,${SRCS}))
HEADERS+= $(filter %.h,${SRCS})
OBJS+= $(patsubst %.c,%.o, $(filter %.c,${SRCS}))
OBJS+= $(patsubst %.cc,%.o, $(filter %.cc,${SRCS}))
ifeq ($(FF_DPDK),)
FF_DPDK=${TOPDIR}/dpdk/x86_64-native-linuxapp-gcc
@ -57,7 +59,9 @@ CXXFLAGS+= ${FF_PROG_CFLAGS}
LIBS+= ${FF_PROG_LIBS}
${PROG}: ${OBJS}
CLEANFILES+= ${PROG} ${OBJS}
${PROG}: ${HEADERS} ${OBJS}
ifdef PROG_CXX
${CXX} ${CXXFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
else
@ -65,6 +69,6 @@ else
endif
clean:
@rm -f ${PROG} ${OBJS}
@rm -f ${CLEANFILES}
all: ${PROG}

29
tools/route/Makefile Normal file
View File

@ -0,0 +1,29 @@
# @(#)Makefile 8.1 (Berkeley) 6/5/93
# $FreeBSD$
TOPDIR?=${CURDIR}/../..
include ${TOPDIR}/tools/opts.mk
PROG= route
MAN= route.8
SRCS= route.c keywords.h
WARNS?= 3
CLEANFILES+=keywords.h
CFLAGS+= -DNS
ifneq (${MK_INET_SUPPORT},"no")
CFLAGS+= -DINET
endif
ifneq (${MK_INET6_SUPPORT},"no")
CFLAGS+= -DINET6
endif
CFLAGS+= -I.
include ${TOPDIR}/tools/prog.mk
keywords.h: keywords
LC_ALL=C awk '!/^#|^$$/ { \
printf "#define\tK_%s\t%d\n\t{\"%s\", K_%s},\n", \
toupper($$1), ++L, $$1, toupper($$1); \
}' < ${CURDIR}/keywords > $@

57
tools/route/keywords Normal file
View File

@ -0,0 +1,57 @@
# @(#)keywords 8.2 (Berkeley) 3/19/94
# $FreeBSD$
4
6
add
blackhole
change
cloning
del
delete
dst
expire
fib
flush
gateway
genmask
get
host
hopcount
iface
interface
ifa
ifp
inet
inet6
iso
link
llinfo
lock
lockrest
mask
monitor
mtu
net
netmask
nostatic
nostick
osi
prefixlen
proto1
proto2
proxy
recvpipe
reject
rtt
rttvar
sa
sendpipe
show
ssthresh
static
sticky
weight
x25
xns
xresolve

506
tools/route/route.8 Normal file
View File

@ -0,0 +1,506 @@
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" 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.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" 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.
.\"
.\" @(#)route.8 8.3 (Berkeley) 3/19/94
.\" $FreeBSD$
.\"
.Dd November 11, 2014
.Dt ROUTE 8
.Os
.Sh NAME
.Nm route
.Nd manually manipulate the routing tables
.Sh SYNOPSIS
.Nm
.Op Fl dnqtv
.Ar command
.Oo
.Op Ar modifiers
.Ar args
.Oc
.Sh DESCRIPTION
The
.Nm
utility is used to manually manipulate the network
routing tables.
It normally is not needed, as a
system routing table management daemon, such as
.Xr routed 8 ,
should tend to this task.
.Pp
The
.Nm
utility supports a limited number of general options,
but a rich command language, enabling the user to specify
any arbitrary request that could be delivered via the
programmatic interface discussed in
.Xr route 4 .
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl 4
Specify
.Cm inet
address family as family hint for subcommands.
.It Fl 6
Specify
.Cm inet
address family as family hint for subcommands.
.It Fl d
Run in debug-only mode, i.e., do not actually modify the routing table.
.It Fl n
Bypass attempts to print host and network names symbolically
when reporting actions.
(The process of translating between symbolic
names and numerical equivalents can be quite time consuming, and
may require correct operation of the network; thus it may be expedient
to forget this, especially when attempting to repair networking operations).
.It Fl t
Run in test-only mode.
.Pa /dev/null
is used instead of a socket.
.It Fl v
(verbose) Print additional details.
.It Fl q
Suppress all output from the
.Cm add , change , delete ,
and
.Cm flush
commands.
.El
.Pp
The
.Nm
utility provides the following commands:
.Pp
.Bl -tag -width Fl -compact
.It Cm add
Add a route.
.It Cm flush
Remove all routes.
.It Cm delete
Delete a specific route.
.It Cm del
Another name for the
.Cm delete
command.
.It Cm change
Change aspects of a route (such as its gateway).
.It Cm get
Lookup and display the route for a destination.
.It Cm monitor
Continuously report any changes to the routing information base,
routing lookup misses, or suspected network partitionings.
.It Cm show
Another name for the
.Cm get
command.
.El
.Pp
The monitor command has the syntax:
.Pp
.Bd -ragged -offset indent -compact
.Nm
.Op Fl n
.Cm monitor Op Fl fib Ar number
.Ed
.Pp
The flush command has the syntax:
.Pp
.Bd -ragged -offset indent -compact
.Nm
.Oo Fl n Cm flush Oc Oo Ar family Oc Op Fl fib Ar number
.Ed
.Pp
If the
.Cm flush
command is specified,
.Nm
will ``flush'' the routing tables of all gateway entries.
When the address family may is specified by any of the
.Fl osi ,
.Fl xns ,
.Fl inet6 ,
or
.Fl inet
modifiers, only routes having destinations with addresses in the
delineated family will be deleted.
Additionally,
.Fl 4
or
.Fl 6
can be used as aliases for
.Fl inet
and
.Fl inet6
modifiers.
When a
.Fl fib
option is specified, the operation will be applied to
the specified FIB
.Pq routing table .
.Pp
The other commands have the following syntax:
.Pp
.Bd -ragged -offset indent -compact
.Nm
.Op Fl n
.Ar command
.Op Fl net No \&| Fl host
.Ar destination gateway
.Op Ar netmask
.Op Fl fib Ar number
.Ed
.Pp
where
.Ar destination
is the destination host or network,
.Ar gateway
is the next-hop intermediary via which packets should be routed.
Routes to a particular host may be distinguished from those to
a network by interpreting the Internet address specified as the
.Ar destination
argument.
The optional modifiers
.Fl net
and
.Fl host
force the destination to be interpreted as a network or a host, respectively.
Otherwise, if the
.Ar destination
has a
.Dq local address part
of
INADDR_ANY
.Pq Li 0.0.0.0 ,
or if the
.Ar destination
is the symbolic name of a network, then the route is
assumed to be to a network; otherwise, it is presumed to be a
route to a host.
Optionally, the
.Ar destination
could also be specified in the
.Ar net Ns / Ns Ar bits
format.
.Pp
For example,
.Li 128.32
is interpreted as
.Fl host Li 128.0.0.32 ;
.Li 128.32.130
is interpreted as
.Fl host Li 128.32.0.130 ;
.Fl net Li 128.32
is interpreted as
.Li 128.32.0.0;
.Fl net Li 128.32.130
is interpreted as
.Li 128.32.130.0;
and
.Li 192.168.64/20
is interpreted as
.Fl net Li 192.168.64 Fl netmask Li 255.255.240.0 .
.Pp
A
.Ar destination
of
.Ar default
is a synonym for the default route.
For
.Li IPv4
it is
.Fl net Fl inet Li 0.0.0.0 ,
and for
.Li IPv6
it is
.Fl net Fl inet6 Li :: .
.Pp
If the destination is directly reachable
via an interface requiring
no intermediary system to act as a gateway, the
.Fl interface
modifier should be specified;
the gateway given is the address of this host on the common network,
indicating the interface to be used for transmission.
Alternately, if the interface is point to point the name of the interface
itself may be given, in which case the route remains valid even
if the local or remote addresses change.
.Pp
The optional modifiers
.Fl xns ,
.Fl osi ,
and
.Fl link
specify that all subsequent addresses are in the
.Tn XNS
or
.Tn OSI
address families,
or are specified as link-level addresses,
and the names must be numeric specifications rather than
symbolic names.
.Pp
The optional
.Fl netmask
modifier is intended
to achieve the effect of an
.Tn OSI
.Tn ESIS
redirect with the netmask option,
or to manually add subnet routes with
netmasks different from that of the implied network interface
(as would otherwise be communicated using the OSPF or ISIS routing protocols).
One specifies an additional ensuing address parameter
(to be interpreted as a network mask).
The implicit network mask generated in the AF_INET case
can be overridden by making sure this option follows the destination parameter.
.Pp
For
.Dv AF_INET6 ,
the
.Fl prefixlen
qualifier
is available instead of the
.Fl mask
qualifier because non-continuous masks are not allowed in IPv6.
For example,
.Fl prefixlen Li 32
specifies network mask of
.Li ffff:ffff:0000:0000:0000:0000:0000:0000
to be used.
The default value of prefixlen is 64 to get along with
the aggregatable address.
But 0 is assumed if
.Cm default
is specified.
Note that the qualifier works only for
.Dv AF_INET6
address family.
.Pp
Routes have associated flags which influence operation of the protocols
when sending to destinations matched by the routes.
These flags may be set (or sometimes cleared)
by indicating the following corresponding modifiers:
.Bd -literal
-xresolve RTF_XRESOLVE - emit mesg on use (for external lookup)
-iface ~RTF_GATEWAY - destination is directly reachable
-static RTF_STATIC - manually added route
-nostatic ~RTF_STATIC - pretend route added by kernel or daemon
-reject RTF_REJECT - emit an ICMP unreachable when matched
-blackhole RTF_BLACKHOLE - silently discard pkts (during updates)
-proto1 RTF_PROTO1 - set protocol specific routing flag #1
-proto2 RTF_PROTO2 - set protocol specific routing flag #2
.Ed
.Pp
The optional modifiers
.Fl rtt ,
.Fl rttvar ,
.Fl sendpipe ,
.Fl recvpipe ,
.Fl mtu ,
.Fl hopcount ,
.Fl expire ,
and
.Fl ssthresh
provide initial values to quantities maintained in the routing entry
by transport level protocols, such as TCP or TP4.
These may be individually locked by preceding each such modifier to
be locked by
the
.Fl lock
meta-modifier, or one can
specify that all ensuing metrics may be locked by the
.Fl lockrest
meta-modifier.
.Pp
Note that
.Fl expire
accepts expiration time of the route as the number of seconds since the
Epoch
.Pq see Xr time 3 .
When the first character of the number is
.Dq +
or
.Dq - ,
it is interpreted as a value relative to the current time.
.Pp
The optional modifier
.Fl fib Ar number
specifies that the command will be applied to a non-default FIB.
The
.Ar number
must be smaller than the
.Va net.fibs
.Xr sysctl 8
MIB.
When this modifier is not specified,
or a negative number is specified,
the default FIB shown in the
.Va net.my_fibnum
.Xr sysctl 8
MIB will be used.
.Pp
The
.Ar number
allows multiple FIBs by a comma-separeted list and/or range
specification.
The
.Qq Fl fib Li 2,4,6
means the FIB number 2, 4, and 6.
The
.Qq Fl fib Li 1,3-5,6
means the 1, 3, 4, 5, and 6.
.Pp
In a
.Cm change
or
.Cm add
command where the destination and gateway are not sufficient to specify
the route (as in the
.Tn ISO
case where several interfaces may have the
same address), the
.Fl ifp
or
.Fl ifa
modifiers may be used to determine the interface or interface address.
.Pp
All symbolic names specified for a
.Ar destination
or
.Ar gateway
are looked up first as a host name using
.Xr gethostbyname 3 .
If this lookup fails,
.Xr getnetbyname 3
is then used to interpret the name as that of a network.
.Pp
The
.Nm
utility uses a routing socket and the new message types
.Dv RTM_ADD , RTM_DELETE , RTM_GET ,
and
.Dv RTM_CHANGE .
As such, only the super-user may modify
the routing tables.
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
Add a default route to the network routing table.
This will send all packets for destinations not available in the routing table
to the default gateway at 192.168.1.1:
.Pp
.Dl route add -net 0.0.0.0/0 192.168.1.1
.Pp
A shorter version of adding a default route can also be written as:
.Pp
.Dl route add default 192.168.1.1
.Pp
Add a static route to the 172.16.10.0/24 network via the 172.16.1.1 gateway:
.Pp
.Dl route add -net 172.16.10.0/24 172.16.1.1
.Pp
Change the gateway of an already established static route in the routing table:
.Pp
.Dl route change -net 172.16.10.0/24 172.16.1.2
.Pp
Display the route for a destination network:
.Pp
.Dl route show 172.16.10.0
.Pp
Delete a static route from the routing table:
.Pp
.Dl route delete -net 172.16.10.0/24 172.16.1.2
.Pp
Remove all routes from the routing table:
.Pp
.Dl route flush
.Sh DIAGNOSTICS
.Bl -diag
.It "add [host \&| network ] %s: gateway %s flags %x"
The specified route is being added to the tables.
The
values printed are from the routing table entry supplied
in the
.Xr ioctl 2
call.
If the gateway address used was not the primary address of the gateway
(the first one returned by
.Xr gethostbyname 3 ) ,
the gateway address is printed numerically as well as symbolically.
.It "delete [ host \&| network ] %s: gateway %s flags %x"
As above, but when deleting an entry.
.It "%s %s done"
When the
.Cm flush
command is specified, each routing table entry deleted
is indicated with a message of this form.
.It "Network is unreachable"
An attempt to add a route failed because the gateway listed was not
on a directly-connected network.
The next-hop gateway must be given.
.It "not in table"
A delete operation was attempted for an entry which
was not present in the tables.
.It "routing table overflow"
An add operation was attempted, but the system was
low on resources and was unable to allocate memory
to create the new entry.
.It "gateway uses the same route"
A
.Cm change
operation resulted in a route whose gateway uses the
same route as the one being changed.
The next-hop gateway should be reachable through a different route.
.El
.Sh SEE ALSO
.\".Xr esis 4 ,
.Xr netintro 4 ,
.Xr route 4 ,
.Xr arp 8 ,
.Xr routed 8
.\".Xr XNSrouted 8
.Sh HISTORY
The
.Nm
utility appeared in
.Bx 4.2 .
.Sh BUGS
The first paragraph may have slightly exaggerated
.Xr routed 8 Ns 's
abilities.
.Pp
Currently, routes with the
.Dv RTF_BLACKHOLE
flag set need to have the gateway set to an instance of the
.Xr lo 4
driver, using the
.Fl iface
option, for the flag to have any effect; unless IP fast forwarding
is enabled, in which case the meaning of the flag will always
be honored.

2110
tools/route/route.c Normal file

File diff suppressed because it is too large Load Diff