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$ 00040 * Revision 1.15 2008/10/05 16:48:52 haraldkipp 00041 * Security fix. Check various lengths of incoming packets. 00042 * 00043 * Revision 1.14 2008/08/20 06:57:00 haraldkipp 00044 * Implemented IP demultiplexer. 00045 * 00046 * Revision 1.13 2008/08/11 07:00:30 haraldkipp 00047 * BSD types replaced by stdint types (feature request #1282721). 00048 * 00049 * Revision 1.12 2008/04/18 13:13:11 haraldkipp 00050 * Using fast ints. 00051 * 00052 * Revision 1.11 2007/07/09 16:20:19 olereinhardt 00053 * 2007-07-09 Ole Reinhardt <ole.reinhardt@embedded-it.de> 00054 * * net/Makefile: Commented in igmp_in.c and igmp_out.c again 00055 * * net/ipin.c: igmp support reenabled 00056 * 00057 * Revision 1.10 2007/07/09 15:59:00 olereinhardt 00058 * 2007-07-09 Ole Reinhardt <ole.reinhardt@embedded-it.de> 00059 * * ipin.c: commented out igmp support as long as it does not compile 00060 * 00061 * Revision 1.9 2007/05/02 11:18:32 haraldkipp 00062 * IGMP support added. Incomplete. 00063 * 00064 * Revision 1.8 2007/03/23 12:43:50 haraldkipp 00065 * ARP method wasn't actually disabled by default. Fixed. 00066 * 00067 * Revision 1.7 2006/09/05 12:35:39 haraldkipp 00068 * DHCP servers may probe an IP/MAC relationship by sending an 00069 * ICMP request. This triggered the Nut/Net ARP method and 00070 * terminated the DHCP client, leaving the system with default 00071 * configurations of the network mask (255.255.255.0) and 00072 * default gateway (none). The rarely used ARP method is now 00073 * disabled by default. 00074 * 00075 * Revision 1.6 2006/07/10 17:46:59 haraldkipp 00076 * Now really like Jan suggested to fix it. 00077 * 00078 * Revision 1.5 2006/07/10 08:49:47 haraldkipp 00079 * Do not respond to broadcasts with unknown protocols. Many thanks to Jan. 00080 * 00081 * Revision 1.4 2005/06/05 16:48:26 haraldkipp 00082 * Additional parameter enables NutUdpInput() to avoid responding to UDP 00083 * broadcasts with ICMP unreachable messages. Fixes bug #1215192. 00084 * 00085 * Revision 1.3 2004/12/16 18:48:50 haraldkipp 00086 * Added Damian Slee's IP filter function. 00087 * 00088 * Revision 1.2 2004/02/02 18:59:25 drsung 00089 * Some more ICMP support added. 00090 * 00091 * Revision 1.1.1.1 2003/05/09 14:41:32 haraldkipp 00092 * Initial using 3.2.1 00093 * 00094 * Revision 1.16 2003/05/06 18:14:18 harald 00095 * Allow incoming DHCP telegrams, even if not broadcasted 00096 * 00097 * Revision 1.15 2003/03/31 12:26:05 harald 00098 * Accept masks with all bits set 00099 * 00100 * Revision 1.14 2003/02/04 18:14:57 harald 00101 * Version 3 released 00102 * 00103 * Revision 1.13 2002/06/26 17:29:36 harald 00104 * First pre-release with 2.4 stack 00105 * 00106 */ 00107 00108 #include <cfg/ip.h> 00109 00110 #include <net/route.h> 00111 #include <netinet/in.h> 00112 #include <netinet/ip.h> 00113 #include <netinet/icmp.h> 00114 #include <netinet/ip_icmp.h> 00115 #include <netinet/igmp.h> 00116 #include <netinet/udp.h> 00117 #include <sys/socket.h> 00118 #include <arpa/inet.h> 00119 00124 00125 static NutIpFilterFunc NutIpFilter; 00126 00140 void NutIpSetInputFilter(NutIpFilterFunc callbackFunc) 00141 { 00142 NutIpFilter = callbackFunc; 00143 } 00144 00150 int (*ip_demux) (NUTDEVICE *, NETBUF *); 00151 00165 void NutIpInput(NUTDEVICE * dev, NETBUF * nb) 00166 { 00167 IPHDR *ip; 00168 uint_fast8_t hdrlen; 00169 uint32_t dst; 00170 uint_fast8_t bcast; 00171 IFNET *nif; 00172 00173 ip = nb->nb_nw.vp; 00174 00175 /* 00176 * Silently discard datagrams of different IP version as well as 00177 * fragmented or filtered datagrams. 00178 */ 00179 if (ip->ip_v != IPVERSION || /* Version check. */ 00180 (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK)) != 0 || /* Fragmentation. */ 00181 (NutIpFilter && NutIpFilter(ip->ip_src))) { /* Filter. */ 00182 NutNetBufFree(nb); 00183 return; 00184 } 00185 00186 /* 00187 ** IP header length is given in 32-bit fields. Calculate the size in 00188 ** bytes and make sure that the header we know will fit in. Check 00189 ** further, that the header length is not larger than the bytes we 00190 ** received. 00191 */ 00192 hdrlen = ip->ip_hl * 4; 00193 if (hdrlen < sizeof(IPHDR) || hdrlen > nb->nb_nw.sz) { 00194 NutNetBufFree(nb); 00195 return; 00196 } 00197 00198 #if NUT_IP_INCHKSUM 00199 /* Optional checksum calculation on incoming datagrams. */ 00200 #endif 00201 00202 /* 00203 * Check for broadcast. 00204 */ 00205 dst = ip->ip_dst; 00206 nif = dev->dev_icb; 00207 00208 if (dst == INADDR_BROADCAST || 00209 (nif->if_local_ip && nif->if_mask != INADDR_BROADCAST && (dst | nif->if_mask) == INADDR_BROADCAST)) { 00210 bcast = 1; 00211 } 00212 00213 /* 00214 * Check for multicast. 00215 */ 00216 else if (IN_MULTICAST(dst)) { 00217 MCASTENTRY *mca; 00218 00219 for (mca = nif->if_mcast; mca; mca = mca->mca_next) { 00220 if (dst == mca->mca_ip) { 00221 break; 00222 } 00223 } 00224 if (mca == NULL) { 00225 NutNetBufFree(nb); 00226 return; 00227 } 00228 bcast = 2; 00229 } 00230 00231 /* 00232 * Packet is unicast. 00233 */ 00234 else { 00235 bcast = 0; 00236 nb->nb_flags |= NBAF_UNICAST; 00237 00238 #ifdef NUTIPCONF_ICMP_ARPMETHOD 00239 /* 00240 * Silently discard datagrams for other destinations. 00241 * However, if we haven't got an IP address yet, we 00242 * allow ICMP datagrams to support dynamic IP ARP method, 00243 * if this option had been enabled. 00244 */ 00245 if (nif->if_local_ip == 0 && ip->ip_p == IPPROTO_ICMP && (dst & 0xff000000) != 0xff000000 && (dst & 0xff000000) != 0) { 00246 NutNetIfSetup(dev, dst, 0, 0); 00247 } 00248 #endif 00249 if (nif->if_local_ip && (dst == 0 || dst != nif->if_local_ip)) { 00250 NutNetBufFree(nb); 00251 return; 00252 } 00253 } 00254 00255 /* Check the IP data length. */ 00256 nb->nb_tp.sz = htons(ip->ip_len); 00257 if (nb->nb_tp.sz < hdrlen || nb->nb_tp.sz > nb->nb_nw.sz) { 00258 NutNetBufFree(nb); 00259 return; 00260 } 00261 nb->nb_nw.sz = hdrlen; 00262 nb->nb_tp.sz -= hdrlen; 00263 if (nb->nb_tp.sz) { 00264 nb->nb_tp.vp = ((char *) ip) + hdrlen; 00265 } 00266 00267 if (ip_demux == NULL || (*ip_demux) (dev, nb)) { 00268 switch (ip->ip_p) { 00269 case IPPROTO_ICMP: 00270 NutIcmpInput(dev, nb); 00271 break; 00272 case IPPROTO_IGMP: 00273 NutIgmpInput(dev, nb); 00274 break; 00275 default: 00276 /* Unkown protocol, send ICMP destination (protocol) 00277 * unreachable message. 00278 */ 00279 if (bcast || !NutIcmpResponse(ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, nb)) 00280 NutNetBufFree(nb); 00281 break; 00282 } 00283 } 00284 } 00285