source: rtems/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c @ 993b7d1

Last change on this file since 993b7d1 was 993b7d1, checked in by Joel Sherrill <joel.sherrill@…>, on 09/27/04 at 21:52:24

2004-09-27 Joel Sherrill <joel@…>

PR 680/bsps

  • network/if_hdlcsubr.c: Add missing #include <rtems/rtems_bsdnet.h>.
  • 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 <rtems/rtems_bsdnet.h>
52
53#include <sys/param.h>
54/*#include <sys/systm.h>
55#include <sys/kernel.h> */
56#define KERNEL
57#include <sys/malloc.h>
58#include <sys/mbuf.h>
59#include <sys/protosw.h>
60#include <sys/socket.h>
61#include <sys/ioctl.h>
62#include <sys/errno.h>
63#include <sys/syslog.h>
64#include <sys/sysctl.h>
65
66#include <net/if.h>
67#include <net/netisr.h>
68#include <net/route.h>
69#include <net/if_llc.h>
70#include <net/if_dl.h>
71#include <net/if_types.h>
72#include <net/ethernet.h>
73
74#include <netinet/in.h>
75#include <netinet/in_var.h>
76#include <netinet/if_ether.h>
77
78#include <stdio.h>
79
80#include "if_hdlcsubr.h"
81
82
83/*
84u_char  etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
85*/
86#define senderr(e) { error = (e); goto bad;}
87
88/*
89 * HDLC output routine.
90 * Just transmit the packet (hardware adds flags and CRC)
91 */
92int
93hdlc_output(ifp, m0, dst, rt0)
94        register struct ifnet *ifp;
95        struct mbuf *m0;
96        struct sockaddr *dst;
97        struct rtentry *rt0;
98{
99        short type;
100        int s, error = 0;
101#if 0
102        u_char  edst[6];
103#endif
104        register struct mbuf *m = m0;
105        register struct rtentry *rt;
106        struct mbuf *mcopy = (struct mbuf *)0;
107/*      register struct ether_header *eh; */
108        int off, len = m->m_pkthdr.len;
109       
110/*      printk( "hdlc output" ); */
111/*      struct arpcom *ac = (struct arpcom *)ifp; */
112
113        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
114                senderr(ENETDOWN);
115        rt = rt0;
116        if (rt) {
117                if ((rt->rt_flags & RTF_UP) == 0) {
118                        rt0 = rt = rtalloc1(dst, 1, 0UL);
119                        if (rt0)
120                                rt->rt_refcnt--;
121                        else
122                                senderr(EHOSTUNREACH);
123                }
124                if (rt->rt_flags & RTF_GATEWAY) {
125                        if (rt->rt_gwroute == 0)
126                                goto lookup;
127                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
128                                rtfree(rt); rt = rt0;
129                        lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
130                                                          0UL);
131                                if ((rt = rt->rt_gwroute) == 0)
132                                        senderr(EHOSTUNREACH);
133                        }
134                }
135                if (rt->rt_flags & RTF_REJECT)
136                        if (rt->rt_rmx.rmx_expire == 0 ||
137                            rtems_bsdnet_seconds_since_boot() < rt->rt_rmx.rmx_expire)
138                                senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
139        }
140        switch (dst->sa_family) {
141
142        case AF_INET:
143#if 0
144                if (!arpresolve(ac, rt, m, dst, edst, rt0))
145                        return (0);     /* if not yet resolved */
146#endif
147
148                /* If broadcasting on a simplex interface, loopback a copy */
149                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
150                        mcopy = m_copy(m, 0, (int)M_COPYALL);
151                off = m->m_pkthdr.len - m->m_len;
152                type = htons(ETHERTYPE_IP);
153                break;
154#if 0
155        case AF_UNSPEC:
156                eh = (struct ether_header *)dst->sa_data;
157                (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
158                type = eh->ether_type;
159                break;
160#endif
161        default:
162                printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
163                        dst->sa_family);
164                senderr(EAFNOSUPPORT);
165        }
166
167
168        if (mcopy)
169                (void) looutput(ifp, mcopy, dst, rt);
170#if 0
171        /*
172         * Add local net header.  If no space in first mbuf,
173         * allocate another.
174         */
175        M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
176#endif
177
178        if (m == 0)
179                senderr(ENOBUFS);
180               
181#if 0   
182        eh = mtod(m, struct ether_header *);
183        (void)memcpy(&eh->ether_type, &type,
184                sizeof(eh->ether_type));
185        (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
186        (void)memcpy(eh->ether_shost, ac->ac_enaddr,
187            sizeof(eh->ether_shost));
188#endif
189
190        s = splimp();
191        /*
192         * Queue message on interface, and start output if interface
193         * not yet active.
194         */
195        if (IF_QFULL(&ifp->if_snd)) {
196                IF_DROP(&ifp->if_snd);
197                splx(s);
198                senderr(ENOBUFS);
199        }
200        IF_ENQUEUE(&ifp->if_snd, m);
201        if ((ifp->if_flags & IFF_OACTIVE) == 0)
202                (*ifp->if_start)(ifp);
203        splx(s);
204       
205        ifp->if_obytes += len /*+ sizeof (struct ether_header)*/;
206        if (m->m_flags & M_MCAST)
207                ifp->if_omcasts++;
208        return (error);
209
210bad:
211        if (m)
212                m_freem(m);
213        return (error);
214}
215
216/*
217 * Process a received Ethernet packet;
218 * the packet is in the mbuf chain m without
219 * the ether header, which is provided separately.
220 */
221void
222hdlc_input(ifp, m)
223        struct ifnet *ifp;
224        struct mbuf *m;
225{
226        register struct ifqueue *inq;
227        int s;
228       
229        struct ether_header eh;
230       
231        if ((ifp->if_flags & IFF_UP) == 0) {
232                m_freem(m);
233                return;
234        }
235        ifp->if_ibytes += m->m_pkthdr.len;
236/*     
237        if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
238            sizeof(etherbroadcastaddr)) == 0)
239                m->m_flags |= M_BCAST;
240        else if (eh->ether_dhost[0] & 1)
241                m->m_flags |= M_MCAST;
242*/             
243        if (m->m_flags & (M_BCAST|M_MCAST))
244                ifp->if_imcasts++;
245
246
247        /*
248         * RTEMS addition -- allow application to `tap into'
249         * the incoming packet stream.
250         */
251        if (ifp->if_tap && (*ifp->if_tap)(ifp, &eh, m)) {
252                m_freem(m);
253                return;
254        }
255
256        schednetisr(NETISR_IP);
257        inq = &ipintrq;
258
259
260        s = splimp();
261        if (IF_QFULL(inq)) {
262          IF_DROP(inq);
263          m_freem(m);
264        } else
265          IF_ENQUEUE(inq, m);
266        splx(s);
267}
268
269/*
270 * Perform common duties while attaching to interface list
271 */
272void
273hdlc_ifattach(ifp)
274        register struct ifnet *ifp;
275{
276        register struct ifaddr *ifa;
277        register struct sockaddr_dl *sdl;
278
279        ifp->if_type = IFT_ETHER;
280        ifp->if_addrlen = 0;
281        ifp->if_hdrlen  = 0;
282        ifp->if_mtu  = 2048;
283        if (ifp->if_baudrate == 0)
284            ifp->if_baudrate = 8000000;
285        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
286                if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
287                    sdl->sdl_family == AF_LINK) {
288                        sdl->sdl_type = IFT_ETHER;
289                        sdl->sdl_alen = ifp->if_addrlen;
290/*                     
291                        bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
292                              LLADDR(sdl), ifp->if_addrlen);
293*/                     
294                        break;
295                }
296}
297
298
299/* SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); */
300
301int
302hdlc_ioctl(struct ifnet *ifp, int command, caddr_t data)
303{
304        struct ifaddr *ifa = (struct ifaddr *) data;
305        struct ifreq *ifr = (struct ifreq *) data;
306        int error = 0;
307
308        switch (command) {
309        case SIOCSIFADDR:
310                ifp->if_flags |= IFF_UP;
311
312                switch (ifa->ifa_addr->sa_family) {
313#if 0           
314#ifdef INET
315                case AF_INET:
316                        ifp->if_init(ifp->if_softc);    /* before arpwhohas */
317
318                        arp_ifinit((struct arpcom *)ifp, ifa);
319                        break;
320#endif
321#endif
322                default:
323                        ifp->if_init(ifp->if_softc);
324                        break;
325                }
326                break;
327
328        case SIOCGIFADDR:
329                {
330                        struct sockaddr *sa;
331
332                        sa = (struct sockaddr *) & ifr->ifr_data;
333/*                     
334                        bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
335                              (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
336*/                     
337                }
338                break;
339
340        case SIOCSIFMTU:
341                /*
342                 * Set the interface MTU.
343                 */
344                if (ifr->ifr_mtu > ETHERMTU) {
345                        error = EINVAL;
346                } else {
347                        ifp->if_mtu = ifr->ifr_mtu;
348                }
349                break;
350        }
351        return (error);
352}
Note: See TracBrowser for help on using the repository browser.