source: rtems/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c @ 9c1133e

4.104.114.84.95
Last change on this file since 9c1133e was 7b0c547a, checked in by Joel Sherrill <joel.sherrill@…>, on 01/20/03 at 19:53:27

2003-01-20 Joel Sherrill <joel@…>

  • startup/linkcmds: Add FreeBSD SYSCTL() sections for networking.
  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Created from if_ethersubr.c by Andy Dachs <a.dachs@sstl.co.uk>
3 * Surrey Satellite Technology Limited (SSTL), 2001
4 * Modified (hacked) to support IP frames transmitted over HDLC. This
5 * all needs tidying up in future but it does actually work for point
6 * to point communications. I have an SDL WANic400 synchronous
7 * communications card that comes with Windows NT drivers.  The drivers
8 * support a mode that they call "Ethernet Emulation".  That simply
9 * puts the IP frame in an HDLC frame without any ethernet header. i.e.
10 * <HDLC Flag><IpFrame><CRC><HDLC Flag>.  There is no addressing beyond
11 * the IP header information so is only suitable for point to point links
12 * with a single protocol. "At some point" I will add a Frame Relay header
13 * but at the moment I have difficulties getting the WANic card driver's
14 * Frame Relay driver to work.
15 *
16 * Copyright (c) 1982, 1989, 1993
17 *      The Regents of the University of California.  All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 *    notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 *    notice, this list of conditions and the following disclaimer in the
26 *    documentation and/or other materials provided with the distribution.
27 * 3. All advertising materials mentioning features or use of this software
28 *    must display the following acknowledgement:
29 *      This product includes software developed by the University of
30 *      California, Berkeley and its contributors.
31 * 4. Neither the name of the University nor the names of its contributors
32 *    may be used to endorse or promote products derived from this software
33 *    without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 *
47 *      @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
48 * $Id$
49 */
50
51#include <sys/param.h>
52/*#include <sys/systm.h>
53#include <sys/kernel.h> */
54#define KERNEL
55#include <sys/malloc.h>
56#include <sys/mbuf.h>
57#include <sys/protosw.h>
58#include <sys/socket.h>
59#include <sys/ioctl.h>
60#include <sys/errno.h>
61#include <sys/syslog.h>
62#include <sys/sysctl.h>
63
64#include <net/if.h>
65#include <net/netisr.h>
66#include <net/route.h>
67#include <net/if_llc.h>
68#include <net/if_dl.h>
69#include <net/if_types.h>
70#include <net/ethernet.h>
71
72#include <netinet/in.h>
73#include <netinet/in_var.h>
74#include <netinet/if_ether.h>
75
76#include <stdio.h>
77
78#include "if_hdlcsubr.h"
79
80
81/*
82u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
83*/
84#define senderr(e) { error = (e); goto bad;}
85
86/*
87 * HDLC output routine.
88 * Just transmit the packet (hardware adds flags and CRC)
89 */
90int
91hdlc_output(ifp, m0, dst, rt0)
92        register struct ifnet *ifp;
93        struct mbuf *m0;
94        struct sockaddr *dst;
95        struct rtentry *rt0;
96{
97        short type;
98        int s, error = 0;
99#if 0
100        u_char  edst[6];
101#endif
102        register struct mbuf *m = m0;
103        register struct rtentry *rt;
104        struct mbuf *mcopy = (struct mbuf *)0;
105/*      register struct ether_header *eh; */
106        int off, len = m->m_pkthdr.len;
107       
108/*      printk( "hdlc output" ); */
109/*      struct arpcom *ac = (struct arpcom *)ifp; */
110
111        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
112                senderr(ENETDOWN);
113        rt = rt0;
114        if (rt) {
115                if ((rt->rt_flags & RTF_UP) == 0) {
116                        rt0 = rt = rtalloc1(dst, 1, 0UL);
117                        if (rt0)
118                                rt->rt_refcnt--;
119                        else
120                                senderr(EHOSTUNREACH);
121                }
122                if (rt->rt_flags & RTF_GATEWAY) {
123                        if (rt->rt_gwroute == 0)
124                                goto lookup;
125                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
126                                rtfree(rt); rt = rt0;
127                        lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
128                                                          0UL);
129                                if ((rt = rt->rt_gwroute) == 0)
130                                        senderr(EHOSTUNREACH);
131                        }
132                }
133                if (rt->rt_flags & RTF_REJECT)
134                        if (rt->rt_rmx.rmx_expire == 0 ||
135                            rtems_bsdnet_seconds_since_boot() < rt->rt_rmx.rmx_expire)
136                                senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
137        }
138        switch (dst->sa_family) {
139
140        case AF_INET:
141#if 0
142                if (!arpresolve(ac, rt, m, dst, edst, rt0))
143                        return (0);     /* if not yet resolved */
144#endif
145
146                /* If broadcasting on a simplex interface, loopback a copy */
147                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
148                        mcopy = m_copy(m, 0, (int)M_COPYALL);
149                off = m->m_pkthdr.len - m->m_len;
150                type = htons(ETHERTYPE_IP);
151                break;
152#if 0
153        case AF_UNSPEC:
154                eh = (struct ether_header *)dst->sa_data;
155                (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
156                type = eh->ether_type;
157                break;
158#endif
159        default:
160                printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
161                        dst->sa_family);
162                senderr(EAFNOSUPPORT);
163        }
164
165
166        if (mcopy)
167                (void) looutput(ifp, mcopy, dst, rt);
168#if 0
169        /*
170         * Add local net header.  If no space in first mbuf,
171         * allocate another.
172         */
173        M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
174#endif
175
176        if (m == 0)
177                senderr(ENOBUFS);
178               
179#if 0   
180        eh = mtod(m, struct ether_header *);
181        (void)memcpy(&eh->ether_type, &type,
182                sizeof(eh->ether_type));
183        (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
184        (void)memcpy(eh->ether_shost, ac->ac_enaddr,
185            sizeof(eh->ether_shost));
186#endif
187
188        s = splimp();
189        /*
190         * Queue message on interface, and start output if interface
191         * not yet active.
192         */
193        if (IF_QFULL(&ifp->if_snd)) {
194                IF_DROP(&ifp->if_snd);
195                splx(s);
196                senderr(ENOBUFS);
197        }
198        IF_ENQUEUE(&ifp->if_snd, m);
199        if ((ifp->if_flags & IFF_OACTIVE) == 0)
200                (*ifp->if_start)(ifp);
201        splx(s);
202       
203        ifp->if_obytes += len /*+ sizeof (struct ether_header)*/;
204        if (m->m_flags & M_MCAST)
205                ifp->if_omcasts++;
206        return (error);
207
208bad:
209        if (m)
210                m_freem(m);
211        return (error);
212}
213
214/*
215 * Process a received Ethernet packet;
216 * the packet is in the mbuf chain m without
217 * the ether header, which is provided separately.
218 */
219void
220hdlc_input(ifp, m)
221        struct ifnet *ifp;
222        struct mbuf *m;
223{
224        register struct ifqueue *inq;
225        int s;
226       
227        struct ether_header eh;
228       
229        if ((ifp->if_flags & IFF_UP) == 0) {
230                m_freem(m);
231                return;
232        }
233        ifp->if_ibytes += m->m_pkthdr.len;
234/*     
235        if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
236            sizeof(etherbroadcastaddr)) == 0)
237                m->m_flags |= M_BCAST;
238        else if (eh->ether_dhost[0] & 1)
239                m->m_flags |= M_MCAST;
240*/             
241        if (m->m_flags & (M_BCAST|M_MCAST))
242                ifp->if_imcasts++;
243
244
245        /*
246         * RTEMS addition -- allow application to `tap into'
247         * the incoming packet stream.
248         */
249        if (ifp->if_tap && (*ifp->if_tap)(ifp, &eh, m)) {
250                m_freem(m);
251                return;
252        }
253
254        schednetisr(NETISR_IP);
255        inq = &ipintrq;
256
257
258        s = splimp();
259        if (IF_QFULL(inq)) {
260          IF_DROP(inq);
261          m_freem(m);
262        } else
263          IF_ENQUEUE(inq, m);
264        splx(s);
265}
266
267/*
268 * Perform common duties while attaching to interface list
269 */
270void
271hdlc_ifattach(ifp)
272        register struct ifnet *ifp;
273{
274        register struct ifaddr *ifa;
275        register struct sockaddr_dl *sdl;
276
277        ifp->if_type = IFT_ETHER;
278        ifp->if_addrlen = 0;
279        ifp->if_hdrlen  = 0;
280        ifp->if_mtu  = 2048;
281        if (ifp->if_baudrate == 0)
282            ifp->if_baudrate = 8000000;
283        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
284                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
285                    sdl->sdl_family == AF_LINK) {
286                        sdl->sdl_type = IFT_ETHER;
287                        sdl->sdl_alen = ifp->if_addrlen;
288/*                     
289                        bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
290                              LLADDR(sdl), ifp->if_addrlen);
291*/                     
292                        break;
293                }
294}
295
296
297/* SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); */
298
299int
300hdlc_ioctl(struct ifnet *ifp, int command, caddr_t data)
301{
302        struct ifaddr *ifa = (struct ifaddr *) data;
303        struct ifreq *ifr = (struct ifreq *) data;
304        int error = 0;
305
306        switch (command) {
307        case SIOCSIFADDR:
308                ifp->if_flags |= IFF_UP;
309
310                switch (ifa->ifa_addr->sa_family) {
311#if 0           
312#ifdef INET
313                case AF_INET:
314                        ifp->if_init(ifp->if_softc);    /* before arpwhohas */
315
316                        arp_ifinit((struct arpcom *)ifp, ifa);
317                        break;
318#endif
319#endif
320                default:
321                        ifp->if_init(ifp->if_softc);
322                        break;
323                }
324                break;
325
326        case SIOCGIFADDR:
327                {
328                        struct sockaddr *sa;
329
330                        sa = (struct sockaddr *) & ifr->ifr_data;
331/*                     
332                        bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
333                              (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
334*/                     
335                }
336                break;
337
338        case SIOCSIFMTU:
339                /*
340                 * Set the interface MTU.
341                 */
342                if (ifr->ifr_mtu > ETHERMTU) {
343                        error = EINVAL;
344                } else {
345                        ifp->if_mtu = ifr->ifr_mtu;
346                }
347                break;
348        }
349        return (error);
350}
Note: See TracBrowser for help on using the repository browser.