X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=blobdiff_plain;f=slip.c;h=d8b32d8dbda79b5ad8ad4432be2adb4d3a166a10;hp=5eb8dbdb1239e72698eb52d0f53d108af2e2f607;hb=ec2ae5fa0ae79baedb567ad18e09e17305aa89d1;hpb=3abd18e85781e00e2b7fc641f29c99e130238abf diff --git a/slip.c b/slip.c index 5eb8dbd..d8b32d8 100644 --- a/slip.c +++ b/slip.c @@ -27,7 +27,6 @@ struct slip { bool_t ignoring_packet; /* If this packet was corrupt or overlong, we ignore everything up to the next END */ netlink_deliver_fn *netlink_to_tunnel; - uint32_t local_address; }; /* Generic SLIP mangling code */ @@ -79,6 +78,9 @@ static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l) int outputchr; enum { OUTPUT_END = 256, OUTPUT_NOTHING = 257 }; + if (!st->buff->size) + buffer_init(st->buff,calculate_max_start_pad()); + if (st->pending_esc) { st->pending_esc=False; switch(buf[i]) { @@ -115,7 +117,7 @@ static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l) if (st->ignoring_packet) { if (outputchr == OUTPUT_END) { st->ignoring_packet=False; - buffer_init(st->buff,calculate_max_start_pad()); + st->buff->size=0; } } else { if (outputchr == OUTPUT_END) { @@ -123,9 +125,9 @@ static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l) st->netlink_to_tunnel(&st->nl,st->buff); BUF_ALLOC(st->buff,"userv_afterpoll"); } - buffer_init(st->buff,calculate_max_start_pad()); + st->buff->size=0; } else if (outputchr != OUTPUT_NOTHING) { - if (st->buff->size < st->buff->len) { + if (buf_remaining_space(st->buff)) { buf_append_uint8(st->buff,outputchr); } else { Message(M_WARNING, "userv_afterpoll: dropping overlong" @@ -144,8 +146,6 @@ static void slip_init(struct slip *st, struct cloc loc, dict_t *dict, 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_item_to_ipaddr( - dict_find_item(dict,"local-address", True, name, loc),"netlink"); BUF_ALLOC(st->buff,"slip_init"); st->pending_esc=False; st->ignoring_packet=False; @@ -210,6 +210,14 @@ static void userv_deliver_to_kernel(void *sst, struct buffer_if *buf) { struct userv *st=sst; + if (buf->size > st->slip.nl.mtu) { + Message(M_ERR,"%s: packet of size %"PRIu32" exceeds mtu %"PRIu32":" + " cannot be injected into kernel, dropped\n", + st->slip.nl.name, buf->size, st->slip.nl.mtu); + BUF_FREE(buf); + return; + } + slip_stuff(&st->slip,buf,st->txfd); } @@ -254,7 +262,6 @@ static void userv_entry(void *sst) dup2(st->in,0); dup2(st->out,1); - /* XXX close all other fds */ setsid(); /* XXX We really should strdup() all of argv[] but because we'll just exit anyway if execvp() fails it doesn't seem worth bothering. */ @@ -265,10 +272,9 @@ static void userv_entry(void *sst) static void userv_invoke_userv(struct userv *st) { - struct userv_entry_rec *er; + struct userv_entry_rec er[1]; int c_stdin[2]; int c_stdout[2]; - string_t addrs; string_t nets; string_t s; struct netlink_client *r; @@ -284,9 +290,9 @@ static void userv_invoke_userv(struct userv *st) /* This is where we actually invoke userv - all the networks we'll be using should already have been registered. */ - addrs=safe_malloc(512,"userv_invoke_userv:addrs"); - snprintf(addrs,512,"%s,%s,%d,slip", - ipaddr_to_string(st->slip.local_address), + char addrs[512]; + snprintf(addrs,sizeof(addrs),"%s,%s,%d,slip", + ipaddr_to_string(st->slip.nl.local_address), ipaddr_to_string(st->slip.nl.secnet_address),st->slip.nl.mtu); allnets=ipset_new(); @@ -307,7 +313,6 @@ static void userv_invoke_userv(struct userv *st) s=subnet_to_string(snets->list[i]); strcat(nets,s); strcat(nets,","); - free(s); } nets[strlen(nets)-1]=0; subnet_list_free(snets); @@ -318,17 +323,11 @@ static void userv_invoke_userv(struct userv *st) st->slip.pending_esc=False; /* Invoke userv */ - if (pipe(c_stdin)!=0) { - fatal_perror("userv_invoke_userv: pipe(c_stdin)"); - } - if (pipe(c_stdout)!=0) { - fatal_perror("userv_invoke_userv: pipe(c_stdout)"); - } + pipe_cloexec(c_stdin); + pipe_cloexec(c_stdout); st->txfd=c_stdin[1]; st->rxfd=c_stdout[0]; - er=safe_malloc(sizeof(*r),"userv_invoke_userv: er"); - er->in=c_stdin[0]; er->out=c_stdout[1]; /* The arguments are: @@ -337,7 +336,8 @@ static void userv_invoke_userv(struct userv *st) service-name local-addr,secnet-addr,mtu,protocol route1,route2,... */ - er->argv=safe_malloc(sizeof(*er->argv)*6,"userv_invoke_userv:argv"); + const char *er_argv[6]; + er->argv=er_argv; er->argv[0]=st->userv_path; er->argv[1]=st->service_user; er->argv[2]=st->service_name; @@ -350,9 +350,6 @@ static void userv_invoke_userv(struct userv *st) er, st, st->slip.nl.name); close(er->in); close(er->out); - free(er->argv); - free(er); - free(addrs); free(nets); 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