/* GLOBAL VARS */
-int irdp_sock;
+int irdp_sock = -1;
char b1[16], b2[16], b3[16], b4[16]; /* For inet_2a */
extern struct zebra_t zebrad;
extern struct thread *t_irdp_raw;
-extern struct interface *get_iflist_ifp(int idx);
int in_cksum (void *ptr, int nbytes);
void process_solicit (struct interface *ifp);
-void parse_irdp_packet(char *p,
+static void
+parse_irdp_packet(char *p,
int len,
struct interface *ifp)
{
struct ip *ip = (struct ip *)p ;
struct icmphdr *icmp;
struct in_addr src;
- int ip_hlen, ip_len;
+ int ip_hlen, iplen, datalen;
struct zebra_if *zi;
struct irdp_interface *irdp;
zi = ifp->info;
- if(!zi) return;
+ if (!zi)
+ return;
irdp = &zi->irdp;
- if(!irdp) return;
+ if (!irdp)
+ return;
- ip_hlen = ip->ip_hl*4;
- ip_len = ntohs(ip->ip_len);
- len = len - ip_hlen;
+ ip_hlen = ip->ip_hl << 2;
+
+ sockopt_iphdrincl_swab_systoh (ip);
+
+ iplen = ip->ip_len;
+ datalen = len - ip_hlen;
src = ip->ip_src;
- if(ip_len < ICMP_MINLEN) {
- zlog_err ("IRDP: RX ICMP packet too short from %s\n",
- inet_ntoa (src));
- return;
- }
+ if (len != iplen)
+ {
+ zlog_err ("IRDP: RX length doesnt match IP length");
+ return;
+ }
+ if (iplen < ICMP_MINLEN)
+ {
+ zlog_err ("IRDP: RX ICMP packet too short from %s\n",
+ inet_ntoa (src));
+ return;
+ }
+
+ /* XXX: RAW doesnt receive link-layer, surely? ??? */
/* Check so we don't checksum packets longer than oure RX_BUF - (ethlen +
len of IP-header) 14+20 */
-
- if(ip_len > IRDP_RX_BUF-34) {
- zlog_err ("IRDP: RX ICMP packet too long from %s\n",
- inet_ntoa (src));
- return;
- }
-
-
- if (in_cksum (ip, ip_len)) {
- zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
- inet_ntoa (src));
- return;
- }
+ if (iplen > IRDP_RX_BUF-34)
+ {
+ zlog_err ("IRDP: RX ICMP packet too long from %s\n",
+ inet_ntoa (src));
+ return;
+ }
icmp = (struct icmphdr *) (p+ip_hlen);
-
+ /* check icmp checksum */
+ if (in_cksum (icmp, datalen) != icmp->checksum)
+ {
+ zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
+ inet_ntoa (src));
+ return;
+ }
+
/* Handle just only IRDP */
-
- if( icmp->type == ICMP_ROUTERADVERT);
- else if( icmp->type == ICMP_ROUTERSOLICIT);
- else return;
-
-
- if (icmp->code != 0) {
- zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code, silently ignored",
- icmp->type,
- inet_ntoa (src));
+ if (!(icmp->type == ICMP_ROUTERADVERT
+ || icmp->type == ICMP_ROUTERSOLICIT))
return;
- }
-
- if(ip->ip_dst.s_addr == INADDR_BROADCAST &&
- irdp->flags & IF_BROADCAST);
-
- else if ( ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP &&
- ! (irdp->flags & IF_BROADCAST));
-
- else { /* ERROR */
-
- zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n",
- inet_ntoa (src),
- ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP?
- "multicast" : inet_ntoa(ip->ip_dst),
- ifp->name,
- irdp->flags & IF_BROADCAST?
- "broadcast" : "multicast");
+
+ if (icmp->code != 0)
+ {
+ zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code,"
+ " silently ignored",
+ icmp->type, inet_ntoa (src));
+ return;
+ }
- zlog_warn ("IRDP: Please correct settings\n");
- return;
- }
+ if (! ((ntohl (ip->ip_dst.s_addr) == INADDR_BROADCAST)
+ && (irdp->flags & IF_BROADCAST))
+ ||
+ (ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP
+ && !(irdp->flags & IF_BROADCAST)))
+ {
+ zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n",
+ inet_ntoa (src),
+ ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP ?
+ "multicast" : inet_ntoa (ip->ip_dst),
+ ifp->name,
+ irdp->flags & IF_BROADCAST ? "broadcast" : "multicast");
+
+ zlog_warn ("IRDP: Please correct settings\n");
+ return;
+ }
switch (icmp->type)
{
case ICMP_ROUTERSOLICIT:
if(irdp->flags & IF_DEBUG_MESSAGES)
- zlog_warn ("IRDP: RX Solicit on %s from %s\n",
- ifp->name,
- inet_ntoa (src));
+ zlog_debug ("IRDP: RX Solicit on %s from %s\n",
+ ifp->name,
+ inet_ntoa (src));
process_solicit(ifp);
break;
}
}
\f
-int irdp_recvmsg (int sock,
- u_char *buf,
- int size,
- int *ifindex)
+static int
+irdp_recvmsg (int sock, u_char *buf, int size, int *ifindex)
{
struct msghdr msg;
struct iovec iov;
- struct cmsghdr *ptr;
char adata[CMSG_SPACE( SOPT_SIZE_CMSG_PKTINFO_IPV4() )];
int ret;
ret = recvmsg (sock, &msg, 0);
if (ret < 0) {
- zlog_warn("IRDP: recvmsg: read error %s", strerror(errno));
+ zlog_warn("IRDP: recvmsg: read error %s", safe_strerror(errno));
return ret;
}
return ret;
}
- ifindex = getsockopt_ifindex (AF_INET, &msg);
+ *ifindex = getsockopt_ifindex (AF_INET, &msg);
return ret;
}
int irdp_sock = THREAD_FD (r);
t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, irdp_sock);
- ret = irdp_recvmsg (irdp_sock, buf, IRDP_RX_BUF, &ifindex);
+ ret = irdp_recvmsg (irdp_sock, (u_char *) buf, IRDP_RX_BUF, &ifindex);
if (ret < 0) zlog_warn ("IRDP: RX Error length = %d", ret);
- ifp = get_iflist_ifp(ifindex);
+ ifp = if_lookup_by_index(ifindex);
if(! ifp ) return ret;
zi= ifp->info;
if(! (irdp->flags & IF_ACTIVE)) {
if(irdp->flags & IF_DEBUG_MISC)
- zlog_warn("IRDP: RX ICMP for disabled interface %s\n",
- ifp->name);
+ zlog_debug("IRDP: RX ICMP for disabled interface %s\n", ifp->name);
return 0;
}
if(irdp->flags & IF_DEBUG_PACKET) {
int i;
- zlog_warn("IRDP: RX (idx %d) ", ifindex);
- for(i=0; i < ret; i++) zlog_warn( "IRDP: RX %x ", buf[i]&0xFF);
+ zlog_debug("IRDP: RX (idx %d) ", ifindex);
+ for(i=0; i < ret; i++) zlog_debug( "IRDP: RX %x ", buf[i]&0xFF);
}
parse_irdp_packet(buf, ret, ifp);
+
return ret;
}
\f
-void send_packet(struct interface *ifp,
+void
+send_packet(struct interface *ifp,
struct stream *s,
u_int32_t dst,
struct prefix *p,
u_long src;
int on;
- if (! (ifp->flags & IFF_UP)) return;
+ if (!(ifp->flags & IFF_UP))
+ return;
- if(!p) src = ntohl(p->u.prefix4.s_addr);
- else src = 0; /* Is filled in */
+ if (!p)
+ src = ntohl(p->u.prefix4.s_addr);
+ else
+ src = 0; /* Is filled in */
ip = (struct ip *) buf;
ip->ip_hl = sizeof(struct ip) >> 2;
ip->ip_ttl = ttl;
ip->ip_src.s_addr = src;
ip->ip_dst.s_addr = dst;
- icmp = (struct icmphdr *) (buf + 20);
+ icmp = (struct icmphdr *) (buf + sizeof (struct ip));
/* Merge IP header with icmp packet */
-
- stream_get(icmp, s, s->putp);
+ assert (stream_get_endp(s) < (sizeof (buf) - sizeof (struct ip)));
+ stream_get(icmp, s, stream_get_endp(s));
/* icmp->checksum is already calculated */
- ip->ip_len = sizeof(struct ip) + s->putp;
- stream_free(s);
+ ip->ip_len = sizeof(struct ip) + stream_get_endp(s);
on = 1;
if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL,
(char *) &on, sizeof(on)) < 0)
- zlog_warn("sendto %s", strerror (errno));
+ zlog_warn("sendto %s", safe_strerror (errno));
if(dst == INADDR_BROADCAST ) {
on = 1;
if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST,
(char *) &on, sizeof(on)) < 0)
- zlog_warn("sendto %s", strerror (errno));
+ zlog_warn("sendto %s", safe_strerror (errno));
}
if(dst != INADDR_BROADCAST) {
on = 0;
if( setsockopt(irdp_sock,IPPROTO_IP, IP_MULTICAST_LOOP,
(char *)&on,sizeof(on)) < 0)
- zlog_warn("sendto %s", strerror (errno));
+ zlog_warn("sendto %s", safe_strerror (errno));
}
bzero(&sockdst,sizeof(sockdst));
msg->msg_control = cmsg;
msg->msg_controllen = cmsg->cmsg_len;
+ sockopt_iphdrincl_swab_htosys (ip);
+
if (sendmsg(irdp_sock, msg, 0) < 0) {
- zlog_warn("sendto %s", strerror (errno));
+ zlog_warn("sendto %s", safe_strerror (errno));
}
/* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
}