hope this time i get the part ‘poke claudio@’ right
a. fix a bug. b. get rid of some junk in ‘mask_rnhead’. c. forbid unprivileged user to insert ‘genmask' into ‘mask_rnhead' bug is in this line memcmp((caddr_t *)info.rti_info[RTAX_GENMASK] + 1, (caddr_t *)t->rn_key + 1, ((struct sockaddr *)t->rn_key)->sa_len) to make this right, at least, it should look like this memcmp((caddr_t *)info.rti_info[RTAX_GENMASK] + 1, (caddr_t *)t->rn_key + 1, ((struct sockaddr *)t->rn_key)->sa_len - 1) after doing this, the whole checking seems completely unnecessary, is expected result from ‘rn_addmask’. Index: net/rtsock.c =================================================================== RCS file: /cvs/src/sys/net/rtsock.c,v retrieving revision 1.136 diff -u -p -r1.136 rtsock.c --- net/rtsock.c 21 Jan 2014 10:08:02 -0000 1.136 +++ net/rtsock.c 21 Jan 2014 21:27:32 -0000 @@ -564,20 +564,25 @@ route_output(struct mbuf *m, ...) error = EINVAL; goto flush; } - if (info.rti_info[RTAX_GENMASK] != NULL) { - struct radix_node *t; - t = rn_addmask(info.rti_info[RTAX_GENMASK], 0, 1); - if (t && info.rti_info[RTAX_GENMASK]->sa_len >= - ((struct sockaddr *)t->rn_key)->sa_len && - memcmp((caddr_t *)info.rti_info[RTAX_GENMASK] + 1, - (caddr_t *)t->rn_key + 1, - ((struct sockaddr *)t->rn_key)->sa_len) - 1) - info.rti_info[RTAX_GENMASK] = - (struct sockaddr *)(t->rn_key); - else { + if (info.rti_info[RTAX_GENMASK] != NULL && rtm->rtm_type != RTM_GET) { + rnh = rt_gettable(info.rti_info[RTAX_DST]->sa_family, tableid); + if (rnh == NULL) { + error = EINVAL; + goto flush; + } + rn = rn_addmask(info.rti_info[RTAX_GENMASK], 0, + rnh->rnh_treetop->rn_off); + if (rn == NULL) { error = ENOBUFS; goto flush; } + if (!((struct sockaddr *)rn->rn_key)->sa_len) { + error = EINVAL; + goto flush; + } + info.rti_info[RTAX_GENMASK] = (struct sockaddr *)rn->rn_key; + } else { + info.rti_info[RTAX_GENMASK] = NULL; } #ifdef MPLS info.rti_mpls = rtm->rtm_mpls;