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