Nut/OS  4.10.3
API Reference
icmpin.c
Go to the documentation of this file.
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