LCOV - code coverage report
Current view: top level - zebra - irdp_packet.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 148 0.0 %
Date: 2015-11-19 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  * Copyright (C) 2000  Robert Olsson.
       4             :  * Swedish University of Agricultural Sciences
       5             :  *
       6             :  * This file is part of GNU Zebra.
       7             :  *
       8             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       9             :  * under the terms of the GNU General Public License as published by the
      10             :  * Free Software Foundation; either version 2, or (at your option) any
      11             :  * later version.
      12             :  *
      13             :  * GNU Zebra is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License
      19             :  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
      20             :  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      21             :  * 02111-1307, USA.  
      22             :  */
      23             : 
      24             : /* 
      25             :  * This work includes work with the following copywrite:
      26             :  *
      27             :  * Copyright (C) 1997, 2000 Kunihiro Ishiguro
      28             :  *
      29             :  */
      30             : 
      31             : /* 
      32             :  * Thanks to Jens Låås at Swedish University of Agricultural Sciences
      33             :  * for reviewing and tests.
      34             :  */
      35             : 
      36             : 
      37             : #include <zebra.h>
      38             : 
      39             : 
      40             : #ifdef HAVE_IRDP
      41             : 
      42             : #include "if.h"
      43             : #include "vty.h"
      44             : #include "sockunion.h"
      45             : #include "prefix.h"
      46             : #include "command.h"
      47             : #include "memory.h"
      48             : #include "stream.h"
      49             : #include "ioctl.h"
      50             : #include "connected.h"
      51             : #include "log.h"
      52             : #include "zclient.h"
      53             : #include "thread.h"
      54             : #include "zebra/interface.h"
      55             : #include "zebra/rtadv.h"
      56             : #include "zebra/rib.h"
      57             : #include "zebra/zserv.h"
      58             : #include "zebra/redistribute.h"
      59             : #include "zebra/irdp.h"
      60             : #include <netinet/ip_icmp.h>
      61             : #include "if.h"
      62             : #include "checksum.h"
      63             : #include "sockunion.h"
      64             : #include "log.h"
      65             : #include "sockopt.h"
      66             : 
      67             : 
      68             : /* GLOBAL VARS */
      69             : 
      70             : int irdp_sock = -1;
      71             : 
      72             : extern struct zebra_t zebrad;
      73             : extern struct thread *t_irdp_raw;
      74             : 
      75             : static void
      76           0 : parse_irdp_packet(char *p, 
      77             :                   int len, 
      78             :                   struct interface *ifp)
      79             : {
      80           0 :   struct ip *ip = (struct ip *)p ;
      81             :   struct icmphdr *icmp;
      82             :   struct in_addr src;
      83             :   int ip_hlen, iplen, datalen;
      84             :   struct zebra_if *zi;
      85             :   struct irdp_interface *irdp;
      86             : 
      87           0 :   zi = ifp->info;
      88           0 :   if (!zi) 
      89           0 :     return;
      90             : 
      91           0 :   irdp = &zi->irdp;
      92           0 :   if (!irdp) 
      93           0 :     return;
      94             : 
      95           0 :   ip_hlen = ip->ip_hl << 2;
      96             :   
      97           0 :   sockopt_iphdrincl_swab_systoh (ip);
      98             :   
      99           0 :   iplen = ip->ip_len;
     100           0 :   datalen = len - ip_hlen;
     101           0 :   src = ip->ip_src;
     102             : 
     103           0 :   if (len != iplen)
     104             :     {
     105           0 :       zlog_err ("IRDP: RX length doesnt match IP length");
     106           0 :       return;
     107             :     }
     108             : 
     109           0 :   if (iplen < ICMP_MINLEN) 
     110             :     {
     111           0 :       zlog_err ("IRDP: RX ICMP packet too short from %s\n",
     112             :               inet_ntoa (src));
     113           0 :       return;
     114             :     }
     115             :     
     116             :   /* XXX: RAW doesnt receive link-layer, surely? ??? */
     117             :   /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen +
     118             :    len of IP-header) 14+20 */
     119           0 :   if (iplen > IRDP_RX_BUF-34) 
     120             :     {
     121           0 :       zlog_err ("IRDP: RX ICMP packet too long from %s\n",
     122             :                 inet_ntoa (src));
     123           0 :       return;
     124             :     }
     125             : 
     126           0 :   icmp = (struct icmphdr *) (p+ip_hlen);
     127             : 
     128             :   /* check icmp checksum */    
     129           0 :   if (in_cksum (icmp, datalen) != icmp->checksum) 
     130             :     {
     131           0 :       zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
     132             :                  inet_ntoa (src));
     133           0 :       return;
     134             :     }
     135             :   
     136             :   /* Handle just only IRDP */
     137           0 :   if (!(icmp->type == ICMP_ROUTERADVERT
     138           0 :         || icmp->type == ICMP_ROUTERSOLICIT))
     139           0 :     return;
     140             :   
     141           0 :   if (icmp->code != 0) 
     142             :     {
     143           0 :       zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code,"
     144             :                  " silently ignored",
     145           0 :                  icmp->type, inet_ntoa (src));
     146           0 :       return;
     147             :     }
     148             : 
     149           0 :   if (! ((ntohl (ip->ip_dst.s_addr) == INADDR_BROADCAST)
     150           0 :          && (irdp->flags & IF_BROADCAST))
     151           0 :         ||
     152           0 :         (ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP
     153           0 :          && !(irdp->flags & IF_BROADCAST)))
     154             :     {
     155           0 :       zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n",
     156             :                  inet_ntoa (src),
     157           0 :                  ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP ?
     158             :                  "multicast" : inet_ntoa (ip->ip_dst),
     159           0 :                  ifp->name,
     160           0 :                  irdp->flags & IF_BROADCAST ? "broadcast" : "multicast");
     161             : 
     162           0 :       zlog_warn ("IRDP: Please correct settings\n");
     163           0 :       return;
     164             :     }
     165             : 
     166           0 :   switch (icmp->type) 
     167             :     {
     168             :     case ICMP_ROUTERADVERT:
     169           0 :       break;
     170             : 
     171             :     case ICMP_ROUTERSOLICIT:
     172             : 
     173           0 :       if(irdp->flags & IF_DEBUG_MESSAGES) 
     174           0 :         zlog_debug ("IRDP: RX Solicit on %s from %s\n",
     175           0 :                     ifp->name,
     176             :                     inet_ntoa (src));
     177             : 
     178           0 :       process_solicit(ifp);
     179           0 :       break;
     180             : 
     181             :     default:
     182           0 :       zlog_warn ("IRDP: RX type %d from %s. Bad ICMP type, silently ignored",
     183           0 :                  icmp->type,
     184             :                  inet_ntoa (src));
     185             :     }
     186             : }
     187             : 
     188             : static int
     189           0 : irdp_recvmsg (int sock, u_char *buf, int size, int *ifindex)
     190             : {
     191             :   struct msghdr msg;
     192             :   struct iovec iov;
     193             :   char adata[CMSG_SPACE( SOPT_SIZE_CMSG_PKTINFO_IPV4() )];
     194             :   int ret;
     195             : 
     196           0 :   msg.msg_name = (void *)0;
     197           0 :   msg.msg_namelen = 0;
     198           0 :   msg.msg_iov = &iov;
     199           0 :   msg.msg_iovlen = 1;
     200           0 :   msg.msg_control = (void *) adata;
     201           0 :   msg.msg_controllen = sizeof adata;
     202             : 
     203           0 :   iov.iov_base = buf;
     204           0 :   iov.iov_len = size;
     205             : 
     206           0 :   ret = recvmsg (sock, &msg, 0);
     207           0 :   if (ret < 0) {
     208           0 :     zlog_warn("IRDP: recvmsg: read error %s", safe_strerror(errno));
     209           0 :     return ret;
     210             :   }
     211             : 
     212           0 :   if (msg.msg_flags & MSG_TRUNC) {
     213           0 :     zlog_warn("IRDP: recvmsg: truncated message");
     214           0 :     return ret;
     215             :   }
     216           0 :   if (msg.msg_flags & MSG_CTRUNC) {
     217           0 :     zlog_warn("IRDP: recvmsg: truncated control message");
     218           0 :     return ret;
     219             :   }
     220             : 
     221           0 :   *ifindex = getsockopt_ifindex (AF_INET, &msg);
     222             : 
     223           0 :   return ret;
     224             : }
     225             : 
     226           0 : int irdp_read_raw(struct thread *r)
     227             : {
     228             :   struct interface *ifp;
     229             :   struct zebra_if *zi;
     230             :   struct irdp_interface *irdp;
     231             :   char buf[IRDP_RX_BUF];
     232           0 :   int ret, ifindex = 0;
     233             :   
     234           0 :   int irdp_sock = THREAD_FD (r);
     235           0 :   t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, irdp_sock);
     236             :   
     237           0 :   ret = irdp_recvmsg (irdp_sock, (u_char *) buf, IRDP_RX_BUF,  &ifindex);
     238             :  
     239           0 :   if (ret < 0) zlog_warn ("IRDP: RX Error length = %d", ret);
     240             : 
     241           0 :   ifp = if_lookup_by_index(ifindex);
     242           0 :   if(! ifp ) return ret;
     243             : 
     244           0 :   zi= ifp->info;
     245           0 :   if(! zi ) return ret;
     246             : 
     247           0 :   irdp = &zi->irdp;
     248           0 :   if(! irdp ) return ret;
     249             : 
     250           0 :   if(! (irdp->flags & IF_ACTIVE)) {
     251             : 
     252           0 :     if(irdp->flags & IF_DEBUG_MISC) 
     253           0 :       zlog_debug("IRDP: RX ICMP for disabled interface %s\n", ifp->name);
     254           0 :     return 0;
     255             :   }
     256             : 
     257           0 :   if(irdp->flags & IF_DEBUG_PACKET) {
     258             :     int i;
     259           0 :     zlog_debug("IRDP: RX (idx %d) ", ifindex);
     260           0 :     for(i=0; i < ret; i++) zlog_debug( "IRDP: RX %x ", buf[i]&0xFF);
     261             :   }
     262             : 
     263           0 :   parse_irdp_packet(buf, ret, ifp);
     264             : 
     265           0 :   return ret;
     266             : }
     267             : 
     268             : void 
     269           0 : send_packet(struct interface *ifp, 
     270             :             struct stream *s,
     271             :             u_int32_t dst,
     272             :             struct prefix *p,
     273             :             u_int32_t ttl)
     274             : {
     275             :   static struct sockaddr_in sockdst = {AF_INET};
     276             :   struct ip *ip;
     277             :   struct icmphdr *icmp;
     278             :   struct msghdr *msg;
     279             :   struct cmsghdr *cmsg;
     280             :   struct iovec iovector;
     281             :   char msgbuf[256];
     282             :   char buf[256];
     283             :   struct in_pktinfo *pktinfo;
     284             :   u_long src;
     285             :   int on;
     286             :  
     287           0 :   if (!(ifp->flags & IFF_UP))
     288           0 :     return;
     289             : 
     290           0 :   if (p)
     291           0 :     src = ntohl(p->u.prefix4.s_addr);
     292             :   else 
     293           0 :     src = 0; /* Is filled in */
     294             :   
     295           0 :   ip = (struct ip *) buf;
     296           0 :   ip->ip_hl = sizeof(struct ip) >> 2;
     297           0 :   ip->ip_v = IPVERSION;
     298           0 :   ip->ip_tos = 0xC0;
     299           0 :   ip->ip_off = 0L;
     300           0 :   ip->ip_p = 1;       /* IP_ICMP */
     301           0 :   ip->ip_ttl = ttl;
     302           0 :   ip->ip_src.s_addr = src;
     303           0 :   ip->ip_dst.s_addr = dst;
     304           0 :   icmp = (struct icmphdr *) (buf + sizeof (struct ip));
     305             : 
     306             :   /* Merge IP header with icmp packet */
     307           0 :   assert (stream_get_endp(s) < (sizeof (buf) - sizeof (struct ip)));
     308           0 :   stream_get(icmp, s, stream_get_endp(s));
     309             : 
     310             :   /* icmp->checksum is already calculated */
     311           0 :   ip->ip_len  = sizeof(struct ip) + stream_get_endp(s);
     312             : 
     313           0 :   on = 1;
     314           0 :   if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL,
     315             :                  (char *) &on, sizeof(on)) < 0)
     316           0 :     zlog_warn("sendto %s", safe_strerror (errno));
     317             : 
     318             : 
     319           0 :   if(dst == INADDR_BROADCAST ) {
     320           0 :     on = 1;
     321           0 :     if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST,
     322             :                    (char *) &on, sizeof(on)) < 0)
     323           0 :       zlog_warn("sendto %s", safe_strerror (errno));
     324             :   }
     325             : 
     326           0 :   if(dst !=  INADDR_BROADCAST) {
     327           0 :       on = 0; 
     328           0 :       if( setsockopt(irdp_sock,IPPROTO_IP, IP_MULTICAST_LOOP, 
     329             :                      (char *)&on,sizeof(on)) < 0)
     330           0 :         zlog_warn("sendto %s", safe_strerror (errno));
     331             :   }
     332             : 
     333           0 :   memset(&sockdst,0,sizeof(sockdst));
     334           0 :   sockdst.sin_family=AF_INET;
     335           0 :   sockdst.sin_addr.s_addr = dst;
     336             : 
     337           0 :   cmsg = (struct cmsghdr *) (msgbuf + sizeof(struct msghdr));
     338           0 :   cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo);
     339           0 :   cmsg->cmsg_level = SOL_IP;
     340           0 :   cmsg->cmsg_type = IP_PKTINFO;
     341           0 :   pktinfo = (struct in_pktinfo *) CMSG_DATA(cmsg);
     342           0 :   pktinfo->ipi_ifindex = ifp->ifindex;
     343           0 :   pktinfo->ipi_spec_dst.s_addr = src;
     344           0 :   pktinfo->ipi_addr.s_addr = src;
     345             :  
     346           0 :   iovector.iov_base = (void *) buf;
     347           0 :   iovector.iov_len = ip->ip_len; 
     348           0 :   msg = (struct msghdr *) msgbuf;
     349           0 :   msg->msg_name = &sockdst;
     350           0 :   msg->msg_namelen = sizeof(sockdst);
     351           0 :   msg->msg_iov = &iovector;
     352           0 :   msg->msg_iovlen = 1;
     353           0 :   msg->msg_control = cmsg;
     354           0 :   msg->msg_controllen = cmsg->cmsg_len;
     355             :  
     356           0 :   sockopt_iphdrincl_swab_htosys (ip);
     357             :   
     358           0 :   if (sendmsg(irdp_sock, msg, 0) < 0) {
     359           0 :     zlog_warn("sendto %s", safe_strerror (errno));
     360             :   }
     361             :   /*   printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
     362             : }
     363             : 
     364             : 
     365             : #endif /* HAVE_IRDP */
     366             : 
     367             : 
     368             : 

Generated by: LCOV version 1.10