-static netlink_deliver_fn *netlink_init(struct netlink *st,
- void *dst, struct cloc loc,
- dict_t *dict, string_t description,
- netlink_deliver_fn *to_host)
-{
- st->dst=dst;
- st->cl.description=description;
- st->cl.type=CL_NETLINK;
- st->cl.apply=NULL;
- st->cl.interface=&st->ops;
- st->ops.st=st;
- st->ops.regnets=netlink_regnets;
- st->ops.deliver=netlink_from_tunnel;
- st->ops.set_delivery=netlink_set_delivery;
- st->max_start_pad=0;
- st->max_end_pad=0;
- st->clients=NULL;
- st->deliver_to_host=to_host;
-
- st->name=dict_read_string(dict,"name",False,"netlink",loc);
- if (!st->name) st->name=description;
- dict_read_subnet_list(dict, "networks", True, "netlink", loc,
- &st->networks);
- st->local_address=string_to_ipaddr(
- dict_find_item(dict,"local-address", True, "netlink", loc),"netlink");
- st->secnet_address=string_to_ipaddr(
- dict_find_item(dict,"secnet-address", True, "netlink", loc),"netlink");
- if (!subnet_match(&st->networks,st->local_address)) {
- cfgfatal(loc,"netlink","local-address must be in local networks\n");
- }
- st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
- buffer_new(&st->icmp,ICMP_BUFSIZE);
-
- return netlink_from_host;
-}
-
-/* Connection to the kernel through userv-ipif */
-
-struct userv {
- struct netlink nl;
- int txfd; /* We transmit to userv */
- int rxfd; /* We receive from userv */
- string_t userv_path;
- string_t service_user;
- string_t service_name;
- uint32_t txbuflen;
- struct buffer_if *buff; /* We unstuff received packets into here
- and send them to the site code. */
- bool_t pending_esc;
- netlink_deliver_fn *netlink_to_tunnel;
-};
-
-static int userv_beforepoll(void *sst, struct pollfd *fds, int *nfds_io,
- int *timeout_io, const struct timeval *tv_now,
- uint64_t *now)
-{
- struct userv *st=sst;
- *nfds_io=2;
- fds[0].fd=st->txfd;
- fds[0].events=POLLERR; /* Might want to pick up POLLOUT sometime */
- fds[1].fd=st->rxfd;
- fds[1].events=POLLIN|POLLERR|POLLHUP;
- return 0;
-}
-
-static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds,
- const struct timeval *tv_now, uint64_t *now)
-{
- struct userv *st=sst;
- uint8_t rxbuf[DEFAULT_BUFSIZE];
- int l,i;
-
- if (fds[1].revents&POLLERR) {
- printf("userv_afterpoll: hup!\n");
- }
- if (fds[1].revents&POLLIN) {
- l=read(st->rxfd,rxbuf,DEFAULT_BUFSIZE);
- if (l<0) {
- fatal_perror("userv_afterpoll: read(rxfd)");
- }
- if (l==0) {
- fatal("userv_afterpoll: read(rxfd)=0; userv gone away?\n");
- }
- /* XXX really crude unstuff code */
- /* XXX check for buffer overflow */
- BUF_ASSERT_USED(st->buff);
- for (i=0; i<l; i++) {
- if (st->pending_esc) {
- st->pending_esc=False;
- switch(rxbuf[i]) {
- case SLIP_ESCEND:
- *(uint8_t *)buf_append(st->buff,1)=SLIP_END;
- break;
- case SLIP_ESCESC:
- *(uint8_t *)buf_append(st->buff,1)=SLIP_ESC;
- break;
- default:
- fatal("userv_afterpoll: bad SLIP escape character\n");
- }
- } else {
- switch (rxbuf[i]) {
- case SLIP_END:
- if (st->buff->size>0) {
- st->netlink_to_tunnel(&st->nl,NULL,
- st->buff);
- BUF_ALLOC(st->buff,"userv_afterpoll");
- }
- buffer_init(st->buff,st->nl.max_start_pad);
- break;
- case SLIP_ESC:
- st->pending_esc=True;
- break;
- default:
- *(uint8_t *)buf_append(st->buff,1)=rxbuf[i];
- break;
- }
- }
- }
- }
-}
-
-/* Send buf to the kernel. Free buf before returning. */
-static void userv_deliver_to_kernel(void *sst, void *cid,
- struct buffer_if *buf)
-{
- struct userv *st=sst;
- uint8_t txbuf[DEFAULT_BUFSIZE];
- uint8_t *i;
- uint32_t j;
-
- BUF_ASSERT_USED(buf);
-
- /* Spit the packet at userv-ipif: SLIP start marker, then
- bytestuff the packet, then SLIP end marker */
- /* XXX crunchy bytestuff code */
- j=0;
- txbuf[j++]=SLIP_END;
- for (i=buf->start; i<(buf->start+buf->size); i++) {
- switch (*i) {
- case SLIP_END:
- txbuf[j++]=SLIP_ESC;
- txbuf[j++]=SLIP_ESCEND;
- break;
- case SLIP_ESC:
- txbuf[j++]=SLIP_ESC;
- txbuf[j++]=SLIP_ESCESC;
- break;
- default:
- txbuf[j++]=*i;
- break;
- }
- }
- txbuf[j++]=SLIP_END;
- if (write(st->txfd,txbuf,j)<0) {
- fatal_perror("userv_deliver_to_kernel: write()");
- }
- BUF_FREE(buf);
-}
-
-static void userv_phase_hook(void *sst, uint32_t newphase)