VALUE rb_rt_initialize(int argc, VALUE *argv, VALUE klass) { rt_ctx *ctx; VALUE binmode = Qnil; int _bmode = 0; rb_scan_args(argc, argv, "01", &binmode); if ((binmode != Qnil) && (binmode != Qfalse)) { Check_Type(binmode, T_TRUE); _bmode=1; } if(!(ctx = rt_new())) rb_sys_fail(0); ctx->binary = _bmode; return Data_Wrap_Struct(klass, rb_rt_mark, rt_free, ctx); }
/* Our rt netlink filter */ int rt_filter(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct rt_entry *rtarg; struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[RTA_MAX+1]; struct rt_entry *entry; rtarg = (struct rt_entry *)arg; /* Just lookup the Main routing table */ if (r->rtm_table != RT_TABLE_MAIN) return 0; /* init len value */ len -= NLMSG_LENGTH(sizeof(*r)); if (len <0) { printf("BUG: wrong nlmsg len %d\n", len); return -1; } /* init the parse attribute space */ memset(tb, 0, sizeof(tb)); parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); /* * we return from filter when route is * cloned from another route, learn by an * ICMP redirect or set by kernel. * Return too when rt type != gateway or direct route. */ if (r->rtm_flags & RTM_F_CLONED) return 0; if (r->rtm_protocol == RTPROT_REDIRECT) return 0; if (r->rtm_protocol == RTPROT_KERNEL) return 0; if (r->rtm_type != RTN_UNICAST) return 0; if (tb[RTA_OIF]) { /* alloc new memory entry */ entry = rt_new(); /* copy the rtmsg infos */ memcpy(entry->rtm, r, sizeof(struct rtmsg)); /* * can use RTA_PAYLOAD(tb[RTA_SRC]) * but ipv4 addr are 4 bytes coded */ entry->oif = *(int *) RTA_DATA(tb[RTA_OIF]); if (tb[RTA_SRC]) memcpy(&entry->src, RTA_DATA(tb[RTA_SRC]), 4); if (tb[RTA_PREFSRC]) memcpy(&entry->psrc, RTA_DATA(tb[RTA_PREFSRC]), 4); if (tb[RTA_DST]) memcpy(&entry->dest, RTA_DATA(tb[RTA_DST]), 4); if (tb[RTA_GATEWAY]) memcpy(&entry->gate, RTA_DATA(tb[RTA_GATEWAY]), 4); if (tb[RTA_FLOW]) memcpy(&entry->flow, RTA_DATA(tb[RTA_FLOW]), 4); if (tb[RTA_IIF]) entry->iif = *(int *) RTA_DATA(tb[RTA_IIF]); if (tb[RTA_PRIORITY]) entry->prio = *(int *) RTA_DATA(tb[RTA_PRIORITY]); if (tb[RTA_METRICS]) entry->metrics = *(int *) RTA_DATA(tb[RTA_METRICS]); /* save this entry */ rtarg = rt_append(rtarg, entry); } return 0; }