X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=blobdiff_plain;f=slip.c;h=a296e420597ee9e1ae81ef1ea0b16492b25ee91c;hp=d0a77c0b7a118ee7c63fa25c6216d105f2adffd7;hb=263cda0978685f36a149deac8a32c3d382101dd3;hpb=469fd1d95b2528212a46b155cb115c078de4228f diff --git a/slip.c b/slip.c index d0a77c0..a296e42 100644 --- a/slip.c +++ b/slip.c @@ -33,11 +33,11 @@ static void slip_stuff(struct slip *st, struct buffer_if *buf, int fd) { uint8_t txbuf[DEFAULT_BUFSIZE]; uint8_t *i; - uint32_t j=0; + int32_t j=0; BUF_ASSERT_USED(buf); - /* XXX crunchy bytestuff code */ + /* There's probably a much more efficient way of implementing this */ txbuf[j++]=SLIP_END; for (i=buf->start; i<(buf->start+buf->size); i++) { switch (*i) { @@ -71,8 +71,6 @@ static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l) { uint32_t i; - /* XXX really crude unstuff code */ - /* XXX check for buffer overflow */ BUF_ASSERT_USED(st->buff); for (i=0; ipending_esc) { @@ -85,7 +83,7 @@ static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l) *(uint8_t *)buf_append(st->buff,1)=SLIP_ESC; break; default: - fatal("userv_afterpoll: bad SLIP escape character\n"); + fatal("userv_afterpoll: bad SLIP escape character"); } } else { switch (buf[i]) { @@ -108,13 +106,13 @@ static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l) } static void slip_init(struct slip *st, struct cloc loc, dict_t *dict, - string_t name, netlink_deliver_fn *to_host) + cstring_t name, netlink_deliver_fn *to_host) { st->netlink_to_tunnel= netlink_init(&st->nl,st,loc,dict, "netlink-userv-ipif",NULL,to_host); st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"name",loc); - st->local_address=string_to_ipaddr( + st->local_address=string_item_to_ipaddr( dict_find_item(dict,"local-address", True, name, loc),"netlink"); BUF_ALLOC(st->buff,"slip_init"); st->pending_esc=False; @@ -126,33 +124,31 @@ struct userv { struct slip slip; int txfd; /* We transmit to userv */ int rxfd; /* We receive from userv */ - string_t userv_path; - string_t service_user; - string_t service_name; + cstring_t userv_path; + cstring_t service_user; + cstring_t service_name; pid_t pid; bool_t expecting_userv_exit; }; static int userv_beforepoll(void *sst, struct pollfd *fds, int *nfds_io, - int *timeout_io, const struct timeval *tv_now, - uint64_t *now) + int *timeout_io) { struct userv *st=sst; if (st->rxfd!=-1) { *nfds_io=2; fds[0].fd=st->txfd; - fds[0].events=POLLERR; /* Might want to pick up POLLOUT sometime */ + fds[0].events=0; /* Might want to pick up POLLOUT sometime */ fds[1].fd=st->rxfd; - fds[1].events=POLLIN|POLLERR|POLLHUP; + fds[1].events=POLLIN; } else { *nfds_io=0; } return 0; } -static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds, - const struct timeval *tv_now, uint64_t *now) +static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds) { struct userv *st=sst; uint8_t rxbuf[DEFAULT_BUFSIZE]; @@ -170,7 +166,7 @@ static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds, fatal_perror("%s: userv_afterpoll: read(rxfd)", st->slip.nl.name); } else if (l==0) { - fatal("%s: userv_afterpoll: read(rxfd)=0; userv gone away?\n", + fatal("%s: userv_afterpoll: read(rxfd)=0; userv gone away?", st->slip.nl.name); } else slip_unstuff(&st->slip,rxbuf,l); } @@ -195,13 +191,13 @@ static void userv_userv_callback(void *sst, pid_t pid, int status) } if (!st->expecting_userv_exit) { if (WIFEXITED(status)) { - fatal("%s: userv exited unexpectedly with status %d\n", + fatal("%s: userv exited unexpectedly with status %d", st->slip.nl.name,WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { - fatal("%s: userv exited unexpectedly: uncaught signal %d\n", + fatal("%s: userv exited unexpectedly: uncaught signal %d", st->slip.nl.name,WTERMSIG(status)); } else { - fatal("%s: userv stopped unexpectedly\n"); + fatal("%s: userv stopped unexpectedly"); } } Message(M_WARNING,"%s: userv subprocess died with status %d\n", @@ -210,8 +206,8 @@ static void userv_userv_callback(void *sst, pid_t pid, int status) } struct userv_entry_rec { - string_t path; - char **argv; + cstring_t path; + const char **argv; int in; int out; /* XXX perhaps we should collect and log stderr? */ @@ -226,7 +222,9 @@ static void userv_entry(void *sst) /* XXX close all other fds */ setsid(); - execvp(st->path,st->argv); + /* XXX We really should strdup() all of argv[] but because we'll just + exit anyway if execvp() fails it doesn't seem worth bothering. */ + execvp(st->path,(char *const*)st->argv); perror("userv-entry: execvp()"); exit(1); } @@ -239,12 +237,14 @@ static void userv_invoke_userv(struct userv *st) string_t addrs; string_t nets; string_t s; - struct netlink_route *r; - int i; + struct netlink_client *r; + struct ipset *allnets; + struct subnet_list *snets; + int i, nread; uint8_t confirm; if (st->pid) { - fatal("userv_invoke_userv: already running\n"); + fatal("userv_invoke_userv: already running"); } /* This is where we actually invoke userv - all the networks we'll @@ -255,19 +255,28 @@ static void userv_invoke_userv(struct userv *st) ipaddr_to_string(st->slip.local_address), ipaddr_to_string(st->slip.nl.secnet_address),st->slip.nl.mtu); - nets=safe_malloc(1024,"userv_invoke_userv:nets"); - *nets=0; - r=st->slip.nl.routes; - for (i=0; islip.nl.n_routes; i++) { - if (r[i].up) { - r[i].kup=True; - s=subnet_to_string(&r[i].net); - strcat(nets,s); - strcat(nets,","); - free(s); + allnets=ipset_new(); + for (r=st->slip.nl.clients; r; r=r->next) { + if (r->up) { + struct ipset *nan; + r->kup=True; + nan=ipset_union(allnets,r->networks); + ipset_free(allnets); + allnets=nan; } } + snets=ipset_to_subnet_list(allnets); + ipset_free(allnets); + nets=safe_malloc(20*snets->entries,"userv_invoke_userv:nets"); + *nets=0; + for (i=0; ientries; i++) { + s=subnet_to_string(snets->list[i]); + strcat(nets,s); + strcat(nets,","); + free(s); + } nets[strlen(nets)-1]=0; + subnet_list_free(snets); Message(M_INFO,"%s: about to invoke: %s %s %s %s %s\n",st->slip.nl.name, st->userv_path,st->service_user,st->service_name,addrs,nets); @@ -314,23 +323,25 @@ static void userv_invoke_userv(struct userv *st) Message(M_INFO,"%s: userv-ipif pid is %d\n",st->slip.nl.name,st->pid); /* Read a single character from the pipe to confirm userv-ipif is running. If we get a SIGCHLD at this point then we'll get EINTR. */ - if (read(st->rxfd,&confirm,1)!=1) { + if ((nread=read(st->rxfd,&confirm,1))!=1) { if (errno==EINTR) { Message(M_WARNING,"%s: read of confirmation byte was " "interrupted\n",st->slip.nl.name); } else { - fatal_perror("%s: read() of confirmation byte",st->slip.nl.name); + if (nread<0) { + fatal_perror("%s: error reading confirmation byte", + st->slip.nl.name); + } else { + fatal("%s: unexpected EOF instead of confirmation byte" + " - userv ipif failed?", st->slip.nl.name); + } } } else { if (confirm!=SLIP_END) { - fatal("%s: bad confirmation byte %d from userv-ipif\n", + fatal("%s: bad confirmation byte %d from userv-ipif", st->slip.nl.name,confirm); } } - /* Mark rxfd non-blocking */ - if (fcntl(st->rxfd, F_SETFL, fcntl(st->rxfd, F_GETFL)|O_NONBLOCK)==-1) { - fatal_perror("%s: fcntl(O_NONBLOCK)",st->slip.nl.name); - } } static void userv_kill_userv(struct userv *st) @@ -394,13 +405,7 @@ static list_t *userv_apply(closure_t *self, struct cloc loc, dict_t *context, return new_closure(&st->slip.nl.cl); } -init_module slip_module; void slip_module(dict_t *dict) { add_closure(dict,"userv-ipif",userv_apply); -#if 0 - /* TODO */ - add_closure(dict,"pty-slip",ptyslip_apply); - add_closure(dict,"slipd",slipd_apply); -#endif /* 0 */ }