00001 /* 00002 * Copyright (C) 2001-2004 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00021 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.ethernut.de/ 00031 * 00032 * - 00033 * Portions Copyright (C) 2000 David J. Hudson <dave@humbug.demon.co.uk> 00034 * 00035 * This file is distributed in the hope that it will be useful, but WITHOUT 00036 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00037 * FITNESS FOR A PARTICULAR PURPOSE. 00038 * 00039 * You can redistribute this file and/or modify it under the terms of the GNU 00040 * General Public License (GPL) as published by the Free Software Foundation; 00041 * either version 2 of the License, or (at your discretion) any later version. 00042 * See the accompanying file "copying-gpl.txt" for more details. 00043 * 00044 * As a special exception to the GPL, permission is granted for additional 00045 * uses of the text contained in this file. See the accompanying file 00046 * "copying-liquorice.txt" for details. 00047 * - 00048 * Portions Copyright (c) 1983, 1993 by 00049 * The Regents of the University of California. All rights reserved. 00050 * 00051 * Redistribution and use in source and binary forms, with or without 00052 * modification, are permitted provided that the following conditions 00053 * are met: 00054 * 1. Redistributions of source code must retain the above copyright 00055 * notice, this list of conditions and the following disclaimer. 00056 * 2. Redistributions in binary form must reproduce the above copyright 00057 * notice, this list of conditions and the following disclaimer in the 00058 * documentation and/or other materials provided with the distribution. 00059 * 3. Neither the name of the University nor the names of its contributors 00060 * may be used to endorse or promote products derived from this software 00061 * without specific prior written permission. 00062 * 00063 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00064 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00065 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00066 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00067 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00068 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00069 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00070 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00071 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00072 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00073 * SUCH DAMAGE. 00074 * - 00075 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 00076 * 00077 * Permission to use, copy, modify, and distribute this software for any 00078 * purpose with or without fee is hereby granted, provided that the above 00079 * copyright notice and this permission notice appear in all copies, and that 00080 * the name of Digital Equipment Corporation not be used in advertising or 00081 * publicity pertaining to distribution of the document or software without 00082 * specific, written prior permission. 00083 * 00084 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 00085 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 00086 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 00087 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 00088 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 00089 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 00090 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00091 * SOFTWARE. 00092 */ 00093 00094 /* 00095 * $Log$ 00096 * Revision 1.9 2009/02/22 12:39:51 olereinhardt 00097 * Added ICMP destination unreachable support for UDP sockets and give a 00098 * more detailed errno to TCP sockets as well. ICMP support for UDP sockets 00099 * will just be enabled when defining NUT_UDP_ICMP_SUPPORT int the configurator 00100 * 00101 * Revision 1.8 2008/10/05 16:48:52 haraldkipp 00102 * Security fix. Check various lengths of incoming packets. 00103 * 00104 * Revision 1.7 2008/08/11 07:00:29 haraldkipp 00105 * BSD types replaced by stdint types (feature request #1282721). 00106 * 00107 * Revision 1.6 2008/05/24 22:23:55 olereinhardt 00108 * Fixed cvs log message 00109 * 00110 * Revision 1.5 2008/05/24 22:22:26 olereinhardt 00111 * Fixed size comparision in NutIcmpUnreach 00112 * 00113 * Revision 1.4 2004/03/18 10:28:36 haraldkipp 00114 * Comments updated 00115 * 00116 * Revision 1.3 2004/02/06 19:23:59 drsung 00117 * Bugfix. After last changes, ping didn't work any more. Thanks to Pavel Celeda, who discovered this bug. 00118 * 00119 * Revision 1.2 2004/02/02 18:59:25 drsung 00120 * Some more ICMP support added. 00121 * 00122 * Revision 1.1.1.1 2003/05/09 14:41:28 haraldkipp 00123 * Initial using 3.2.1 00124 * 00125 * Revision 1.11 2003/02/04 18:14:57 harald 00126 * Version 3 released 00127 * 00128 * Revision 1.10 2002/06/26 17:29:35 harald 00129 * First pre-release with 2.4 stack 00130 * 00131 */ 00132 00133 #include <netinet/ip_icmp.h> 00134 #include <netinet/ipcsum.h> 00135 #include <netinet/icmp.h> 00136 #include <sys/socket.h> 00137 #include <netinet/tcp.h> 00138 #include <netinet/udp.h> 00139 #include <netinet/in.h> 00140 #include <errno.h> 00141 00146 00151 static CONST int icmp_code2errno[16] = 00152 { 00153 ENETUNREACH, 00154 EHOSTUNREACH, 00155 ENOPROTOOPT, 00156 ECONNREFUSED, 00157 EMSGSIZE, 00158 EOPNOTSUPP, 00159 ENETUNREACH, 00160 EHOSTDOWN, 00161 ENETUNREACH, 00162 ENETUNREACH, 00163 EHOSTUNREACH, 00164 ENETUNREACH, 00165 EHOSTUNREACH, 00166 EHOSTUNREACH, 00167 EHOSTUNREACH, 00168 EHOSTUNREACH, 00169 }; 00170 00171 /* 00172 * Send out ICMP echo response. 00173 */ 00174 static int NutIcmpReflect(NUTDEVICE * dev, uint8_t type, NETBUF * nb) 00175 { 00176 IPHDR *ip; 00177 uint32_t dest; 00178 IFNET *nif; 00179 00180 ip = nb->nb_nw.vp; 00181 dest = ip->ip_src; 00182 nif = dev->dev_icb; 00183 ip->ip_src = nif->if_local_ip; 00184 ip->ip_ttl = MAXTTL; 00185 00186 return NutIcmpOutput(type, dest, nb); 00187 } 00188 00189 /* 00190 * Process incoming ICMP messages for destination unreachable. 00191 */ 00192 static int NutIcmpUnreach(NETBUF * nb, int icmp_code) 00193 { 00194 IPHDR *ih; 00195 00196 if (nb->nb_ap.sz < sizeof(IPHDR) + 8) 00197 return -1; 00198 00199 ih = nb->nb_ap.vp; 00200 00201 switch (ih->ip_p) { 00202 case IPPROTO_TCP: 00203 { 00204 TCPHDR *th; 00205 TCPSOCKET *sock_tcp; 00206 00207 th = (TCPHDR *) ((char *) ih) + sizeof(IPHDR); 00208 sock_tcp = NutTcpFindSocket(th->th_dport, th->th_sport, ih->ip_src); 00209 if (sock_tcp == 0) 00210 return -1; 00211 00212 if (sock_tcp->so_state != TCPS_SYN_SENT && sock_tcp->so_state != TCPS_ESTABLISHED) 00213 return -1; 00214 00215 NutTcpAbortSocket(sock_tcp, icmp_code2errno[icmp_code]); 00216 } 00217 break; 00218 00219 #ifdef NUT_UDP_ICMP_SUPPORT 00220 case IPPROTO_UDP: 00221 { 00222 UDPHDR *uh; 00223 UDPSOCKET *sock_udp; 00224 00225 uh = (UDPHDR *) (((char *) ih) + sizeof(IPHDR)); 00226 sock_udp = NutUdpFindSocket(uh->uh_dport); 00227 00228 if (sock_udp == NULL) 00229 return -1; 00230 00231 if (NutUdpSetSocketError(sock_udp, ih->ip_dst, uh->uh_dport, icmp_code2errno[icmp_code])) 00232 return -1; 00233 } 00234 break; 00235 #endif 00236 00237 default: 00238 return -1; 00239 } 00240 00241 00242 return 0; 00243 } 00244 00261 void NutIcmpInput(NUTDEVICE * dev, NETBUF * nb) 00262 { 00263 ICMPHDR *icp = (ICMPHDR *) nb->nb_tp.vp; 00264 00265 /* Silently discard packets, which are too small. */ 00266 if (icp == NULL || nb->nb_tp.sz < sizeof(ICMPHDR)) { 00267 NutNetBufFree(nb); 00268 return; 00269 } 00270 00271 nb->nb_ap.sz = nb->nb_tp.sz - sizeof(ICMPHDR); 00272 if (nb->nb_ap.sz) { 00273 nb->nb_ap.vp = icp + 1; 00274 nb->nb_tp.sz = sizeof(ICMPHDR); 00275 } 00276 00277 switch (icp->icmp_type) { 00278 case ICMP_ECHO: 00279 if (NutIcmpReflect(dev, ICMP_ECHOREPLY, nb)) { 00280 break; 00281 } 00282 case ICMP_UNREACH: 00283 NutIcmpUnreach(nb, icp->icmp_code); 00284 default: 00285 NutNetBufFree(nb); 00286 } 00287 } 00288