ipin.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 by egnite GmbH.
00003  * Copyright (C) 2001-2007 by egnite Software GmbH.
00004  * Copyright (c) 1983, 1993 by The Regents of the University of California.
00005  * Copyright (c) 1993 by Digital Equipment Corporation.
00006  *
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  *
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  * 3. Neither the name of the copyright holders nor the names of
00019  *    contributors may be used to endorse or promote products derived
00020  *    from this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00023  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00026  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00029  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00030  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00031  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00032  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00033  * SUCH DAMAGE.
00034  *
00035  * For additional information see http://www.ethernut.de/
00036  */
00037 
00038 /*
00039  * $Log: ipin.c,v $
00040  * Revision 1.14  2008/08/20 06:57:00  haraldkipp
00041  * Implemented IP demultiplexer.
00042  *
00043  * Revision 1.13  2008/08/11 07:00:30  haraldkipp
00044  * BSD types replaced by stdint types (feature request #1282721).
00045  *
00046  * Revision 1.12  2008/04/18 13:13:11  haraldkipp
00047  * Using fast ints.
00048  *
00049  * Revision 1.11  2007/07/09 16:20:19  olereinhardt
00050  * 2007-07-09  Ole Reinhardt <ole.reinhardt@embedded-it.de>
00051  *         * net/Makefile: Commented in igmp_in.c and igmp_out.c again
00052  *         * net/ipin.c: igmp support reenabled
00053  *
00054  * Revision 1.10  2007/07/09 15:59:00  olereinhardt
00055  * 2007-07-09  Ole Reinhardt <ole.reinhardt@embedded-it.de>
00056  *  * ipin.c: commented out igmp support as long as it does not compile
00057  *
00058  * Revision 1.9  2007/05/02 11:18:32  haraldkipp
00059  * IGMP support added. Incomplete.
00060  *
00061  * Revision 1.8  2007/03/23 12:43:50  haraldkipp
00062  * ARP method wasn't actually disabled by default. Fixed.
00063  *
00064  * Revision 1.7  2006/09/05 12:35:39  haraldkipp
00065  * DHCP servers may probe an IP/MAC relationship by sending an
00066  * ICMP request. This triggered the Nut/Net ARP method and
00067  * terminated the DHCP client, leaving the system with default
00068  * configurations of the network mask (255.255.255.0) and
00069  * default gateway (none). The rarely used ARP method is now
00070  * disabled by default.
00071  *
00072  * Revision 1.6  2006/07/10 17:46:59  haraldkipp
00073  * Now really like Jan suggested to fix it.
00074  *
00075  * Revision 1.5  2006/07/10 08:49:47  haraldkipp
00076  * Do not respond to broadcasts with unknown protocols. Many thanks to Jan.
00077  *
00078  * Revision 1.4  2005/06/05 16:48:26  haraldkipp
00079  * Additional parameter enables NutUdpInput() to avoid responding to UDP
00080  * broadcasts with ICMP unreachable messages. Fixes bug #1215192.
00081  *
00082  * Revision 1.3  2004/12/16 18:48:50  haraldkipp
00083  * Added Damian Slee's IP filter function.
00084  *
00085  * Revision 1.2  2004/02/02 18:59:25  drsung
00086  * Some more ICMP support added.
00087  *
00088  * Revision 1.1.1.1  2003/05/09 14:41:32  haraldkipp
00089  * Initial using 3.2.1
00090  *
00091  * Revision 1.16  2003/05/06 18:14:18  harald
00092  * Allow incoming DHCP telegrams, even if not broadcasted
00093  *
00094  * Revision 1.15  2003/03/31 12:26:05  harald
00095  * Accept masks with all bits set
00096  *
00097  * Revision 1.14  2003/02/04 18:14:57  harald
00098  * Version 3 released
00099  *
00100  * Revision 1.13  2002/06/26 17:29:36  harald
00101  * First pre-release with 2.4 stack
00102  *
00103  */
00104 
00105 #include <cfg/ip.h>
00106 
00107 #include <net/route.h>
00108 #include <netinet/in.h>
00109 #include <netinet/ip.h>
00110 #include <netinet/icmp.h>
00111 #include <netinet/ip_icmp.h>
00112 #include <netinet/igmp.h>
00113 #include <netinet/udp.h>
00114 #include <sys/socket.h>
00115 #include <arpa/inet.h>
00116 
00121 
00122 static NutIpFilterFunc NutIpFilter;
00123 
00137 void NutIpSetInputFilter(NutIpFilterFunc callbackFunc)
00138 {
00139     NutIpFilter = callbackFunc;
00140 }
00141 
00147 int (*ip_demux) (NUTDEVICE *, NETBUF *);
00148 
00162 void NutIpInput(NUTDEVICE * dev, NETBUF * nb)
00163 {
00164     IPHDR *ip;
00165     uint16_t ip_hdrlen;
00166     uint32_t dst;
00167     uint_fast8_t bcast;
00168     IFNET *nif;
00169 
00170     ip = nb->nb_nw.vp;
00171 
00172     /*
00173      * Silently discard datagrams of different IP version as well as
00174      * fragmented or filtered datagrams.
00175      */
00176     if (ip->ip_v != IPVERSION ||        /* Version check. */
00177         (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK)) != 0 ||      /* Fragmentation. */
00178         (NutIpFilter && NutIpFilter(ip->ip_src))) {     /* Filter. */
00179         NutNetBufFree(nb);
00180         return;
00181     }
00182 
00183     /*
00184      * IP header length is given in 32-bit fields. Calculate the size in
00185      * bytes and make sure that the header we know will fit in.
00186      */
00187     ip_hdrlen = ip->ip_hl * 4;
00188     if (ip_hdrlen < sizeof(IPHDR)) {
00189         NutNetBufFree(nb);
00190         return;
00191     }
00192 
00193     /*
00194      * No checksum calculation on incoming datagrams!
00195      */
00196 
00197     /*
00198      * Check for broadcast.
00199      */
00200     dst = ip->ip_dst;
00201     nif = dev->dev_icb;
00202 
00203     if (dst == INADDR_BROADCAST || 
00204         (nif->if_local_ip && nif->if_mask != INADDR_BROADCAST && (dst | nif->if_mask) == INADDR_BROADCAST)) {
00205         bcast = 1;
00206     }
00207 
00208     /*
00209      * Check for multicast.
00210      */
00211     else if (IN_MULTICAST(dst)) {
00212         MCASTENTRY *mca;
00213 
00214         for (mca = nif->if_mcast; mca; mca = mca->mca_next) {
00215             if (dst == mca->mca_ip) {
00216                 break;
00217             }
00218         }
00219         if (mca == NULL) {
00220             NutNetBufFree(nb);
00221             return;
00222         }
00223         bcast = 2;
00224     }
00225 
00226     /*
00227      * Packet is unicast.
00228      */
00229     else {
00230         bcast = 0;
00231         nb->nb_flags |= NBAF_UNICAST;
00232 
00233 #ifdef NUTIPCONF_ICMP_ARPMETHOD
00234         /*
00235          * Silently discard datagrams for other destinations.
00236          * However, if we haven't got an IP address yet, we
00237          * allow ICMP datagrams to support dynamic IP ARP method,
00238          * if this option had been enabled.
00239          */
00240         if (nif->if_local_ip == 0 && ip->ip_p == IPPROTO_ICMP && (dst & 0xff000000) != 0xff000000 && (dst & 0xff000000) != 0) {
00241             NutNetIfSetup(dev, dst, 0, 0);
00242         }
00243 #endif
00244         if (nif->if_local_ip && (dst == 0 || dst != nif->if_local_ip)) {
00245             NutNetBufFree(nb);
00246             return;
00247         }
00248     }
00249 
00250     nb->nb_nw.sz = ip_hdrlen;
00251     nb->nb_tp.vp = ((char *) ip) + (ip_hdrlen);
00252     nb->nb_tp.sz = htons(ip->ip_len) - (ip_hdrlen);
00253 
00254     if (ip_demux == NULL || (*ip_demux) (dev, nb)) {
00255         switch (ip->ip_p) {
00256         case IPPROTO_ICMP:
00257             NutIcmpInput(dev, nb);
00258             break;
00259 #if 0
00260         case IPPROTO_IGMP:
00261             NutIgmpInput(dev, nb);
00262             break;
00263 #endif
00264         default:
00265             /* Unkown protocol, send ICMP destination (protocol)
00266             * unreachable message.
00267             */
00268             if (bcast || !NutIcmpResponse(ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, nb))
00269                 NutNetBufFree(nb);
00270             break;
00271         }
00272     }
00273 }
00274 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/