summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2000-02-04 03:21:18 +0000
committerRoland McGrath <roland@gnu.org>2000-02-04 03:21:18 +0000
commit9fd51e9b0ad33a89a83fdbbb66bd20d85f7893fb (patch)
tree8845b79f170028cb4380045c50277bbf075b5b7d
Import of Linux 2.2.12 subset (ipv4 stack and related)
-rw-r--r--pfinet/linux-src/arch/alpha/lib/checksum.c169
-rw-r--r--pfinet/linux-src/arch/arm/lib/checksum.S730
-rw-r--r--pfinet/linux-src/arch/i386/lib/checksum.S447
-rw-r--r--pfinet/linux-src/arch/i386/lib/old-checksum.c19
-rw-r--r--pfinet/linux-src/arch/m68k/lib/checksum.c420
-rw-r--r--pfinet/linux-src/arch/ppc/lib/checksum.S194
-rw-r--r--pfinet/linux-src/arch/sparc/lib/checksum.S581
-rw-r--r--pfinet/linux-src/arch/sparc64/lib/checksum.S278
-rw-r--r--pfinet/linux-src/include/asm-alpha/checksum.h90
-rw-r--r--pfinet/linux-src/include/asm-arm/checksum.h162
-rw-r--r--pfinet/linux-src/include/asm-i386/checksum.h215
-rw-r--r--pfinet/linux-src/include/asm-m68k/checksum.h154
-rw-r--r--pfinet/linux-src/include/asm-mips/checksum.h255
-rw-r--r--pfinet/linux-src/include/asm-ppc/checksum.h113
-rw-r--r--pfinet/linux-src/include/asm-sparc/checksum.h252
-rw-r--r--pfinet/linux-src/include/asm-sparc64/checksum.h207
-rw-r--r--pfinet/linux-src/include/linux/a.out.h268
-rw-r--r--pfinet/linux-src/include/linux/acct.h88
-rw-r--r--pfinet/linux-src/include/linux/adfs_fs.h175
-rw-r--r--pfinet/linux-src/include/linux/adfs_fs_i.h17
-rw-r--r--pfinet/linux-src/include/linux/adfs_fs_sb.h33
-rw-r--r--pfinet/linux-src/include/linux/affs_fs.h115
-rw-r--r--pfinet/linux-src/include/linux/affs_fs_i.h47
-rw-r--r--pfinet/linux-src/include/linux/affs_fs_sb.h74
-rw-r--r--pfinet/linux-src/include/linux/affs_hardblocks.h66
-rw-r--r--pfinet/linux-src/include/linux/amifd.h61
-rw-r--r--pfinet/linux-src/include/linux/amifdreg.h81
-rw-r--r--pfinet/linux-src/include/linux/amigaffs.h228
-rw-r--r--pfinet/linux-src/include/linux/apm_bios.h143
-rw-r--r--pfinet/linux-src/include/linux/arcdevice.h354
-rw-r--r--pfinet/linux-src/include/linux/atalk.h180
-rw-r--r--pfinet/linux-src/include/linux/atari_rootsec.h34
-rw-r--r--pfinet/linux-src/include/linux/auto_fs.h83
-rw-r--r--pfinet/linux-src/include/linux/awe_voice.h524
-rw-r--r--pfinet/linux-src/include/linux/ax25.h98
-rw-r--r--pfinet/linux-src/include/linux/b1lli.h136
-rw-r--r--pfinet/linux-src/include/linux/b1pcmcia.h36
-rw-r--r--pfinet/linux-src/include/linux/baycom.h39
-rw-r--r--pfinet/linux-src/include/linux/binfmts.h77
-rw-r--r--pfinet/linux-src/include/linux/bios32.h34
-rw-r--r--pfinet/linux-src/include/linux/bitops.h72
-rw-r--r--pfinet/linux-src/include/linux/blk.h467
-rw-r--r--pfinet/linux-src/include/linux/blkdev.h94
-rw-r--r--pfinet/linux-src/include/linux/bpqether.h41
-rw-r--r--pfinet/linux-src/include/linux/busmouse.h104
-rw-r--r--pfinet/linux-src/include/linux/capability.h337
-rw-r--r--pfinet/linux-src/include/linux/capi.h127
-rw-r--r--pfinet/linux-src/include/linux/cd1400.h292
-rw-r--r--pfinet/linux-src/include/linux/cdk.h486
-rw-r--r--pfinet/linux-src/include/linux/cdrom.h433
-rw-r--r--pfinet/linux-src/include/linux/coda.h800
-rw-r--r--pfinet/linux-src/include/linux/coda_cache.h77
-rw-r--r--pfinet/linux-src/include/linux/coda_fs_i.h56
-rw-r--r--pfinet/linux-src/include/linux/coda_linux.h143
-rw-r--r--pfinet/linux-src/include/linux/coda_opstats.h94
-rw-r--r--pfinet/linux-src/include/linux/coda_proc.h145
-rw-r--r--pfinet/linux-src/include/linux/coda_psdev.h131
-rw-r--r--pfinet/linux-src/include/linux/coff.h351
-rw-r--r--pfinet/linux-src/include/linux/comstats.h119
-rw-r--r--pfinet/linux-src/include/linux/concap.h113
-rw-r--r--pfinet/linux-src/include/linux/config.h6
-rw-r--r--pfinet/linux-src/include/linux/console.h115
-rw-r--r--pfinet/linux-src/include/linux/console_struct.h109
-rw-r--r--pfinet/linux-src/include/linux/consolemap.h15
-rw-r--r--pfinet/linux-src/include/linux/ctype.h54
-rw-r--r--pfinet/linux-src/include/linux/cyclades.h793
-rw-r--r--pfinet/linux-src/include/linux/dcache.h194
-rw-r--r--pfinet/linux-src/include/linux/delay.h37
-rw-r--r--pfinet/linux-src/include/linux/devpts_fs.h74
-rw-r--r--pfinet/linux-src/include/linux/digi1.h100
-rw-r--r--pfinet/linux-src/include/linux/digiFep1.h136
-rw-r--r--pfinet/linux-src/include/linux/digiPCI.h42
-rw-r--r--pfinet/linux-src/include/linux/dio.h204
-rw-r--r--pfinet/linux-src/include/linux/dirent.h11
-rw-r--r--pfinet/linux-src/include/linux/dlists.h108
-rw-r--r--pfinet/linux-src/include/linux/dmascc.h43
-rw-r--r--pfinet/linux-src/include/linux/dtlk.h104
-rw-r--r--pfinet/linux-src/include/linux/efs_dir.h42
-rw-r--r--pfinet/linux-src/include/linux/efs_fs.h67
-rw-r--r--pfinet/linux-src/include/linux/efs_fs_i.h68
-rw-r--r--pfinet/linux-src/include/linux/efs_fs_sb.h63
-rw-r--r--pfinet/linux-src/include/linux/efs_vh.h70
-rw-r--r--pfinet/linux-src/include/linux/elf.h597
-rw-r--r--pfinet/linux-src/include/linux/elfcore.h88
-rw-r--r--pfinet/linux-src/include/linux/epca.h170
-rw-r--r--pfinet/linux-src/include/linux/epcaconfig.h8
-rw-r--r--pfinet/linux-src/include/linux/errno.h16
-rw-r--r--pfinet/linux-src/include/linux/errqueue.h42
-rw-r--r--pfinet/linux-src/include/linux/etherdevice.h56
-rw-r--r--pfinet/linux-src/include/linux/ext2_fs.h624
-rw-r--r--pfinet/linux-src/include/linux/ext2_fs_i.h42
-rw-r--r--pfinet/linux-src/include/linux/ext2_fs_sb.h66
-rw-r--r--pfinet/linux-src/include/linux/fat_cvf.h49
-rw-r--r--pfinet/linux-src/include/linux/fb.h492
-rw-r--r--pfinet/linux-src/include/linux/fcdevice.h40
-rw-r--r--pfinet/linux-src/include/linux/fcntl.h6
-rw-r--r--pfinet/linux-src/include/linux/fd.h378
-rw-r--r--pfinet/linux-src/include/linux/fddidevice.h39
-rw-r--r--pfinet/linux-src/include/linux/fdreg.h143
-rw-r--r--pfinet/linux-src/include/linux/file.h71
-rw-r--r--pfinet/linux-src/include/linux/filter.h140
-rw-r--r--pfinet/linux-src/include/linux/firewall.h61
-rw-r--r--pfinet/linux-src/include/linux/fs.h953
-rw-r--r--pfinet/linux-src/include/linux/ftape-header-segment.h122
-rw-r--r--pfinet/linux-src/include/linux/ftape-vendors.h137
-rw-r--r--pfinet/linux-src/include/linux/ftape.h212
-rw-r--r--pfinet/linux-src/include/linux/genhd.h267
-rw-r--r--pfinet/linux-src/include/linux/ghash.h218
-rw-r--r--pfinet/linux-src/include/linux/hayesesp.h127
-rw-r--r--pfinet/linux-src/include/linux/hdlcdrv.h383
-rw-r--r--pfinet/linux-src/include/linux/hdreg.h282
-rw-r--r--pfinet/linux-src/include/linux/hfmodem.h256
-rw-r--r--pfinet/linux-src/include/linux/hfs_fs.h325
-rw-r--r--pfinet/linux-src/include/linux/hfs_fs_i.h43
-rw-r--r--pfinet/linux-src/include/linux/hfs_fs_sb.h53
-rw-r--r--pfinet/linux-src/include/linux/hfs_sysdep.h245
-rw-r--r--pfinet/linux-src/include/linux/hippidevice.h58
-rw-r--r--pfinet/linux-src/include/linux/hpfs_fs.h13
-rw-r--r--pfinet/linux-src/include/linux/hpfs_fs_i.h24
-rw-r--r--pfinet/linux-src/include/linux/hpfs_fs_sb.h32
-rw-r--r--pfinet/linux-src/include/linux/i2c.h188
-rw-r--r--pfinet/linux-src/include/linux/icmp.h102
-rw-r--r--pfinet/linux-src/include/linux/icmpv6.h149
-rw-r--r--pfinet/linux-src/include/linux/if.h163
-rw-r--r--pfinet/linux-src/include/linux/if_arcnet.h63
-rw-r--r--pfinet/linux-src/include/linux/if_arp.h133
-rw-r--r--pfinet/linux-src/include/linux/if_cablemodem.h22
-rw-r--r--pfinet/linux-src/include/linux/if_ec.h47
-rw-r--r--pfinet/linux-src/include/linux/if_eql.h81
-rw-r--r--pfinet/linux-src/include/linux/if_ether.h98
-rw-r--r--pfinet/linux-src/include/linux/if_fc.h50
-rw-r--r--pfinet/linux-src/include/linux/if_fddi.h223
-rw-r--r--pfinet/linux-src/include/linux/if_frad.h201
-rw-r--r--pfinet/linux-src/include/linux/if_hippi.h157
-rw-r--r--pfinet/linux-src/include/linux/if_ltalk.h12
-rw-r--r--pfinet/linux-src/include/linux/if_packet.h50
-rw-r--r--pfinet/linux-src/include/linux/if_plip.h28
-rw-r--r--pfinet/linux-src/include/linux/if_ppp.h143
-rw-r--r--pfinet/linux-src/include/linux/if_pppvar.h135
-rw-r--r--pfinet/linux-src/include/linux/if_shaper.h64
-rw-r--r--pfinet/linux-src/include/linux/if_slip.h30
-rw-r--r--pfinet/linux-src/include/linux/if_strip.h25
-rw-r--r--pfinet/linux-src/include/linux/if_tr.h100
-rw-r--r--pfinet/linux-src/include/linux/if_tunnel.h29
-rw-r--r--pfinet/linux-src/include/linux/igmp.h129
-rw-r--r--pfinet/linux-src/include/linux/in.h189
-rw-r--r--pfinet/linux-src/include/linux/in6.h193
-rw-r--r--pfinet/linux-src/include/linux/in_route.h32
-rw-r--r--pfinet/linux-src/include/linux/in_systm.h32
-rw-r--r--pfinet/linux-src/include/linux/inet.h52
-rw-r--r--pfinet/linux-src/include/linux/inetdevice.h126
-rw-r--r--pfinet/linux-src/include/linux/init.h68
-rw-r--r--pfinet/linux-src/include/linux/interrupt.h84
-rw-r--r--pfinet/linux-src/include/linux/ioctl.h7
-rw-r--r--pfinet/linux-src/include/linux/ioport.h35
-rw-r--r--pfinet/linux-src/include/linux/ip.h137
-rw-r--r--pfinet/linux-src/include/linux/ip_fw.h193
-rw-r--r--pfinet/linux-src/include/linux/ip_masq.h140
-rw-r--r--pfinet/linux-src/include/linux/ipc.h49
-rw-r--r--pfinet/linux-src/include/linux/ipsec.h69
-rw-r--r--pfinet/linux-src/include/linux/ipv6.h123
-rw-r--r--pfinet/linux-src/include/linux/ipv6_route.h56
-rw-r--r--pfinet/linux-src/include/linux/ipx.h89
-rw-r--r--pfinet/linux-src/include/linux/irda.h120
-rw-r--r--pfinet/linux-src/include/linux/isdn.h901
-rw-r--r--pfinet/linux-src/include/linux/isdn_compat.h108
-rw-r--r--pfinet/linux-src/include/linux/isdn_divertif.h62
-rw-r--r--pfinet/linux-src/include/linux/isdn_ppp.h240
-rw-r--r--pfinet/linux-src/include/linux/isdnif.h622
-rw-r--r--pfinet/linux-src/include/linux/isicom.h310
-rw-r--r--pfinet/linux-src/include/linux/iso_fs.h230
-rw-r--r--pfinet/linux-src/include/linux/iso_fs_i.h14
-rw-r--r--pfinet/linux-src/include/linux/iso_fs_sb.h31
-rw-r--r--pfinet/linux-src/include/linux/istallion.h134
-rw-r--r--pfinet/linux-src/include/linux/joystick.h299
-rw-r--r--pfinet/linux-src/include/linux/kbd_diacr.h8
-rw-r--r--pfinet/linux-src/include/linux/kbd_kern.h164
-rw-r--r--pfinet/linux-src/include/linux/kbd_ll.h12
-rw-r--r--pfinet/linux-src/include/linux/kd.h180
-rw-r--r--pfinet/linux-src/include/linux/kdev_t.h114
-rw-r--r--pfinet/linux-src/include/linux/kernel.h96
-rw-r--r--pfinet/linux-src/include/linux/kernel_stat.h50
-rw-r--r--pfinet/linux-src/include/linux/kernelcapi.h136
-rw-r--r--pfinet/linux-src/include/linux/keyboard.h430
-rw-r--r--pfinet/linux-src/include/linux/kmod.h12
-rw-r--r--pfinet/linux-src/include/linux/lapb.h56
-rw-r--r--pfinet/linux-src/include/linux/limits.h19
-rw-r--r--pfinet/linux-src/include/linux/linkage.h54
-rw-r--r--pfinet/linux-src/include/linux/linux_logo.h1445
-rw-r--r--pfinet/linux-src/include/linux/list.h99
-rw-r--r--pfinet/linux-src/include/linux/lists.h62
-rw-r--r--pfinet/linux-src/include/linux/locks.h62
-rw-r--r--pfinet/linux-src/include/linux/loop.h130
-rw-r--r--pfinet/linux-src/include/linux/lp.h188
-rw-r--r--pfinet/linux-src/include/linux/lp_intern.h22
-rw-r--r--pfinet/linux-src/include/linux/lp_m68k.h135
-rw-r--r--pfinet/linux-src/include/linux/lp_mfc.h14
-rw-r--r--pfinet/linux-src/include/linux/major.h131
-rw-r--r--pfinet/linux-src/include/linux/malloc.h5
-rw-r--r--pfinet/linux-src/include/linux/mc146818rtc.h149
-rw-r--r--pfinet/linux-src/include/linux/mca.h100
-rw-r--r--pfinet/linux-src/include/linux/md.h300
-rw-r--r--pfinet/linux-src/include/linux/minix_fs.h127
-rw-r--r--pfinet/linux-src/include/linux/minix_fs_i.h14
-rw-r--r--pfinet/linux-src/include/linux/minix_fs_sb.h26
-rw-r--r--pfinet/linux-src/include/linux/miscdevice.h43
-rw-r--r--pfinet/linux-src/include/linux/mm.h393
-rw-r--r--pfinet/linux-src/include/linux/mman.h8
-rw-r--r--pfinet/linux-src/include/linux/modsetver.h10
-rw-r--r--pfinet/linux-src/include/linux/module.h287
-rw-r--r--pfinet/linux-src/include/linux/mount.h47
-rw-r--r--pfinet/linux-src/include/linux/mpp.h18
-rw-r--r--pfinet/linux-src/include/linux/mroute.h223
-rw-r--r--pfinet/linux-src/include/linux/msdos_fs.h336
-rw-r--r--pfinet/linux-src/include/linux/msdos_fs_i.h39
-rw-r--r--pfinet/linux-src/include/linux/msdos_fs_sb.h59
-rw-r--r--pfinet/linux-src/include/linux/msg.h80
-rw-r--r--pfinet/linux-src/include/linux/mtio.h373
-rw-r--r--pfinet/linux-src/include/linux/nbd.h85
-rw-r--r--pfinet/linux-src/include/linux/ncp.h204
-rw-r--r--pfinet/linux-src/include/linux/ncp_fs.h331
-rw-r--r--pfinet/linux-src/include/linux/ncp_fs_i.h36
-rw-r--r--pfinet/linux-src/include/linux/ncp_fs_sb.h96
-rw-r--r--pfinet/linux-src/include/linux/ncp_mount.h45
-rw-r--r--pfinet/linux-src/include/linux/net.h145
-rw-r--r--pfinet/linux-src/include/linux/netbeui.h16
-rw-r--r--pfinet/linux-src/include/linux/netdevice.h461
-rw-r--r--pfinet/linux-src/include/linux/netlink.h158
-rw-r--r--pfinet/linux-src/include/linux/netrom.h34
-rw-r--r--pfinet/linux-src/include/linux/nfs.h226
-rw-r--r--pfinet/linux-src/include/linux/nfs3.h252
-rw-r--r--pfinet/linux-src/include/linux/nfs_fs.h284
-rw-r--r--pfinet/linux-src/include/linux/nfs_fs_i.h71
-rw-r--r--pfinet/linux-src/include/linux/nfs_fs_sb.h31
-rw-r--r--pfinet/linux-src/include/linux/nfs_mount.h53
-rw-r--r--pfinet/linux-src/include/linux/nfsiod.h52
-rw-r--r--pfinet/linux-src/include/linux/nls.h56
-rw-r--r--pfinet/linux-src/include/linux/notifier.h115
-rw-r--r--pfinet/linux-src/include/linux/ntfs_fs.h7
-rw-r--r--pfinet/linux-src/include/linux/ntfs_fs_i.h83
-rw-r--r--pfinet/linux-src/include/linux/ntfs_fs_sb.h44
-rw-r--r--pfinet/linux-src/include/linux/nubus.h96
-rw-r--r--pfinet/linux-src/include/linux/nvram.h18
-rw-r--r--pfinet/linux-src/include/linux/openpic.h363
-rw-r--r--pfinet/linux-src/include/linux/pagemap.h153
-rw-r--r--pfinet/linux-src/include/linux/param.h6
-rw-r--r--pfinet/linux-src/include/linux/parport.h393
-rw-r--r--pfinet/linux-src/include/linux/parport_pc.h151
-rw-r--r--pfinet/linux-src/include/linux/pc_keyb.h130
-rw-r--r--pfinet/linux-src/include/linux/pci.h1320
-rw-r--r--pfinet/linux-src/include/linux/personality.h57
-rw-r--r--pfinet/linux-src/include/linux/pg.h63
-rw-r--r--pfinet/linux-src/include/linux/pipe_fs_i.h34
-rw-r--r--pfinet/linux-src/include/linux/pkt_cls.h146
-rw-r--r--pfinet/linux-src/include/linux/pkt_sched.h277
-rw-r--r--pfinet/linux-src/include/linux/poll.h107
-rw-r--r--pfinet/linux-src/include/linux/posix_types.h56
-rw-r--r--pfinet/linux-src/include/linux/ppp-comp.h198
-rw-r--r--pfinet/linux-src/include/linux/ppp.h4
-rw-r--r--pfinet/linux-src/include/linux/ppp_defs.h182
-rw-r--r--pfinet/linux-src/include/linux/prctl.h9
-rw-r--r--pfinet/linux-src/include/linux/proc_fs.h470
-rw-r--r--pfinet/linux-src/include/linux/ps2esdi.h98
-rw-r--r--pfinet/linux-src/include/linux/ptrace.h26
-rw-r--r--pfinet/linux-src/include/linux/qic117.h290
-rw-r--r--pfinet/linux-src/include/linux/qnx4_fs.h123
-rw-r--r--pfinet/linux-src/include/linux/qnx4_fs_i.h38
-rw-r--r--pfinet/linux-src/include/linux/qnx4_fs_sb.h27
-rw-r--r--pfinet/linux-src/include/linux/qnxtypes.h28
-rw-r--r--pfinet/linux-src/include/linux/quota.h209
-rw-r--r--pfinet/linux-src/include/linux/quotaops.h135
-rw-r--r--pfinet/linux-src/include/linux/raid0.h27
-rw-r--r--pfinet/linux-src/include/linux/raid1.h49
-rw-r--r--pfinet/linux-src/include/linux/raid5.h110
-rw-r--r--pfinet/linux-src/include/linux/random.h73
-rw-r--r--pfinet/linux-src/include/linux/reboot.h52
-rw-r--r--pfinet/linux-src/include/linux/resource.h60
-rw-r--r--pfinet/linux-src/include/linux/rocket.h55
-rw-r--r--pfinet/linux-src/include/linux/romfs_fs.h62
-rw-r--r--pfinet/linux-src/include/linux/romfs_fs_i.h11
-rw-r--r--pfinet/linux-src/include/linux/romfs_fs_sb.h10
-rw-r--r--pfinet/linux-src/include/linux/rose.h87
-rw-r--r--pfinet/linux-src/include/linux/route.h70
-rw-r--r--pfinet/linux-src/include/linux/rpcsock.h121
-rw-r--r--pfinet/linux-src/include/linux/rtnetlink.h667
-rw-r--r--pfinet/linux-src/include/linux/sc26198.h533
-rw-r--r--pfinet/linux-src/include/linux/scc.h258
-rw-r--r--pfinet/linux-src/include/linux/sched.h810
-rw-r--r--pfinet/linux-src/include/linux/sdla.h339
-rw-r--r--pfinet/linux-src/include/linux/sdla_fr.h422
-rw-r--r--pfinet/linux-src/include/linux/sdla_ppp.h536
-rw-r--r--pfinet/linux-src/include/linux/sdla_x25.h625
-rw-r--r--pfinet/linux-src/include/linux/sdladrv.h61
-rw-r--r--pfinet/linux-src/include/linux/sdlasfm.h92
-rw-r--r--pfinet/linux-src/include/linux/securebits.h30
-rw-r--r--pfinet/linux-src/include/linux/selection.h44
-rw-r--r--pfinet/linux-src/include/linux/sem.h114
-rw-r--r--pfinet/linux-src/include/linux/serial.h142
-rw-r--r--pfinet/linux-src/include/linux/serial167.h175
-rw-r--r--pfinet/linux-src/include/linux/serialP.h119
-rw-r--r--pfinet/linux-src/include/linux/serial_reg.h144
-rw-r--r--pfinet/linux-src/include/linux/shm.h79
-rw-r--r--pfinet/linux-src/include/linux/signal.h212
-rw-r--r--pfinet/linux-src/include/linux/skbuff.h584
-rw-r--r--pfinet/linux-src/include/linux/slab.h71
-rw-r--r--pfinet/linux-src/include/linux/smb.h123
-rw-r--r--pfinet/linux-src/include/linux/smb_fs.h240
-rw-r--r--pfinet/linux-src/include/linux/smb_fs_i.h35
-rw-r--r--pfinet/linux-src/include/linux/smb_fs_sb.h50
-rw-r--r--pfinet/linux-src/include/linux/smb_mount.h25
-rw-r--r--pfinet/linux-src/include/linux/smbno.h278
-rw-r--r--pfinet/linux-src/include/linux/smp.h86
-rw-r--r--pfinet/linux-src/include/linux/smp_lock.h17
-rw-r--r--pfinet/linux-src/include/linux/socket.h280
-rw-r--r--pfinet/linux-src/include/linux/sockios.h109
-rw-r--r--pfinet/linux-src/include/linux/sound.h15
-rw-r--r--pfinet/linux-src/include/linux/soundcard.h1270
-rw-r--r--pfinet/linux-src/include/linux/soundmodem.h90
-rw-r--r--pfinet/linux-src/include/linux/stallion.h156
-rw-r--r--pfinet/linux-src/include/linux/stat.h57
-rw-r--r--pfinet/linux-src/include/linux/stddef.h10
-rw-r--r--pfinet/linux-src/include/linux/string.h46
-rw-r--r--pfinet/linux-src/include/linux/swap.h175
-rw-r--r--pfinet/linux-src/include/linux/swapctl.h35
-rw-r--r--pfinet/linux-src/include/linux/synclink.h253
-rw-r--r--pfinet/linux-src/include/linux/sys.h30
-rw-r--r--pfinet/linux-src/include/linux/sysctl.h555
-rw-r--r--pfinet/linux-src/include/linux/sysrq.h40
-rw-r--r--pfinet/linux-src/include/linux/sysv_fs.h414
-rw-r--r--pfinet/linux-src/include/linux/sysv_fs_i.h16
-rw-r--r--pfinet/linux-src/include/linux/sysv_fs_sb.h122
-rw-r--r--pfinet/linux-src/include/linux/tasks.h25
-rw-r--r--pfinet/linux-src/include/linux/tcp.h90
-rw-r--r--pfinet/linux-src/include/linux/termios.h7
-rw-r--r--pfinet/linux-src/include/linux/time.h92
-rw-r--r--pfinet/linux-src/include/linux/timer.h96
-rw-r--r--pfinet/linux-src/include/linux/times.h11
-rw-r--r--pfinet/linux-src/include/linux/timex.h277
-rw-r--r--pfinet/linux-src/include/linux/tpqic02.h739
-rw-r--r--pfinet/linux-src/include/linux/tqueue.h124
-rw-r--r--pfinet/linux-src/include/linux/trdevice.h40
-rw-r--r--pfinet/linux-src/include/linux/tty.h413
-rw-r--r--pfinet/linux-src/include/linux/tty_driver.h227
-rw-r--r--pfinet/linux-src/include/linux/tty_flip.h35
-rw-r--r--pfinet/linux-src/include/linux/tty_ldisc.h138
-rw-r--r--pfinet/linux-src/include/linux/types.h108
-rw-r--r--pfinet/linux-src/include/linux/udp.h29
-rw-r--r--pfinet/linux-src/include/linux/ufs_fs.h571
-rw-r--r--pfinet/linux-src/include/linux/ufs_fs_i.h32
-rw-r--r--pfinet/linux-src/include/linux/ufs_fs_sb.h245
-rw-r--r--pfinet/linux-src/include/linux/uio.h37
-rw-r--r--pfinet/linux-src/include/linux/ultrasound.h103
-rw-r--r--pfinet/linux-src/include/linux/umsdos_fs.h188
-rw-r--r--pfinet/linux-src/include/linux/umsdos_fs.p118
-rw-r--r--pfinet/linux-src/include/linux/umsdos_fs_i.h75
-rw-r--r--pfinet/linux-src/include/linux/un.h11
-rw-r--r--pfinet/linux-src/include/linux/unistd.h11
-rw-r--r--pfinet/linux-src/include/linux/user.h1
-rw-r--r--pfinet/linux-src/include/linux/utime.h9
-rw-r--r--pfinet/linux-src/include/linux/uts.h23
-rw-r--r--pfinet/linux-src/include/linux/utsname.h36
-rw-r--r--pfinet/linux-src/include/linux/vfs.h6
-rw-r--r--pfinet/linux-src/include/linux/video_decoder.h37
-rw-r--r--pfinet/linux-src/include/linux/video_encoder.h21
-rw-r--r--pfinet/linux-src/include/linux/videodev.h292
-rw-r--r--pfinet/linux-src/include/linux/videotext.h144
-rw-r--r--pfinet/linux-src/include/linux/vmalloc.h24
-rw-r--r--pfinet/linux-src/include/linux/vt.h54
-rw-r--r--pfinet/linux-src/include/linux/vt_buffer.h83
-rw-r--r--pfinet/linux-src/include/linux/vt_kern.h94
-rw-r--r--pfinet/linux-src/include/linux/wait.h33
-rw-r--r--pfinet/linux-src/include/linux/wanpipe.h218
-rw-r--r--pfinet/linux-src/include/linux/wanrouter.h381
-rw-r--r--pfinet/linux-src/include/linux/watchdog.h40
-rw-r--r--pfinet/linux-src/include/linux/wavefront.h675
-rw-r--r--pfinet/linux-src/include/linux/wireless.h397
-rw-r--r--pfinet/linux-src/include/linux/wrapper.h40
-rw-r--r--pfinet/linux-src/include/linux/x25.h93
-rw-r--r--pfinet/linux-src/include/linux/yam.h82
-rw-r--r--pfinet/linux-src/include/linux/zftape.h87
-rw-r--r--pfinet/linux-src/include/linux/zorro.h736
-rw-r--r--pfinet/linux-src/include/net/addrconf.h158
-rw-r--r--pfinet/linux-src/include/net/af_unix.h35
-rw-r--r--pfinet/linux-src/include/net/arp.h24
-rw-r--r--pfinet/linux-src/include/net/atalkcall.h2
-rw-r--r--pfinet/linux-src/include/net/ax25.h349
-rw-r--r--pfinet/linux-src/include/net/ax25call.h2
-rw-r--r--pfinet/linux-src/include/net/br.h305
-rw-r--r--pfinet/linux-src/include/net/checksum.h110
-rw-r--r--pfinet/linux-src/include/net/datalink.h16
-rw-r--r--pfinet/linux-src/include/net/dst.h178
-rw-r--r--pfinet/linux-src/include/net/flow.h101
-rw-r--r--pfinet/linux-src/include/net/icmp.h42
-rw-r--r--pfinet/linux-src/include/net/if_inet6.h134
-rw-r--r--pfinet/linux-src/include/net/inet_common.h45
-rw-r--r--pfinet/linux-src/include/net/ip.h251
-rw-r--r--pfinet/linux-src/include/net/ip6_fib.h177
-rw-r--r--pfinet/linux-src/include/net/ip6_fw.h54
-rw-r--r--pfinet/linux-src/include/net/ip6_route.h111
-rw-r--r--pfinet/linux-src/include/net/ip_fib.h257
-rw-r--r--pfinet/linux-src/include/net/ip_masq.h362
-rw-r--r--pfinet/linux-src/include/net/ip_masq_mod.h86
-rw-r--r--pfinet/linux-src/include/net/ipconfig.h21
-rw-r--r--pfinet/linux-src/include/net/ipip.h33
-rw-r--r--pfinet/linux-src/include/net/ipv6.h325
-rw-r--r--pfinet/linux-src/include/net/ipx.h82
-rw-r--r--pfinet/linux-src/include/net/ipxcall.h2
-rw-r--r--pfinet/linux-src/include/net/lapb.h150
-rw-r--r--pfinet/linux-src/include/net/lapbcall.h2
-rw-r--r--pfinet/linux-src/include/net/llc.h135
-rw-r--r--pfinet/linux-src/include/net/llc_frame.h98
-rw-r--r--pfinet/linux-src/include/net/llc_name.h7
-rw-r--r--pfinet/linux-src/include/net/llc_state.h4
-rw-r--r--pfinet/linux-src/include/net/llccall.h3
-rw-r--r--pfinet/linux-src/include/net/ndisc.h123
-rw-r--r--pfinet/linux-src/include/net/neighbour.h272
-rw-r--r--pfinet/linux-src/include/net/netbeuicall.h2
-rw-r--r--pfinet/linux-src/include/net/netrom.h181
-rw-r--r--pfinet/linux-src/include/net/nrcall.h2
-rw-r--r--pfinet/linux-src/include/net/p8022.h7
-rw-r--r--pfinet/linux-src/include/net/p8022call.h2
-rw-r--r--pfinet/linux-src/include/net/pkt_cls.h93
-rw-r--r--pfinet/linux-src/include/net/pkt_sched.h407
-rw-r--r--pfinet/linux-src/include/net/profile.h311
-rw-r--r--pfinet/linux-src/include/net/protocol.h82
-rw-r--r--pfinet/linux-src/include/net/psnap.h7
-rw-r--r--pfinet/linux-src/include/net/psnapcall.h2
-rw-r--r--pfinet/linux-src/include/net/rarp.h12
-rw-r--r--pfinet/linux-src/include/net/raw.h38
-rw-r--r--pfinet/linux-src/include/net/rawv6.h27
-rw-r--r--pfinet/linux-src/include/net/rose.h241
-rw-r--r--pfinet/linux-src/include/net/rosecall.h2
-rw-r--r--pfinet/linux-src/include/net/route.h153
-rw-r--r--pfinet/linux-src/include/net/scm.h67
-rw-r--r--pfinet/linux-src/include/net/slhc.h6
-rw-r--r--pfinet/linux-src/include/net/slhc_vj.h187
-rw-r--r--pfinet/linux-src/include/net/snmp.h183
-rw-r--r--pfinet/linux-src/include/net/sock.h950
-rw-r--r--pfinet/linux-src/include/net/spx.h93
-rw-r--r--pfinet/linux-src/include/net/spxcall.h2
-rw-r--r--pfinet/linux-src/include/net/tcp.h1100
-rw-r--r--pfinet/linux-src/include/net/transp_v6.h46
-rw-r--r--pfinet/linux-src/include/net/udp.h66
-rw-r--r--pfinet/linux-src/include/net/x25.h221
-rw-r--r--pfinet/linux-src/include/net/x25call.h2
-rw-r--r--pfinet/linux-src/net/core/Makefile41
-rw-r--r--pfinet/linux-src/net/core/datagram.c249
-rw-r--r--pfinet/linux-src/net/core/dev.c2026
-rw-r--r--pfinet/linux-src/net/core/dev_mcast.c252
-rw-r--r--pfinet/linux-src/net/core/dst.c145
-rw-r--r--pfinet/linux-src/net/core/filter.c454
-rw-r--r--pfinet/linux-src/net/core/firewall.c160
-rw-r--r--pfinet/linux-src/net/core/iovec.c278
-rw-r--r--pfinet/linux-src/net/core/neighbour.c1394
-rw-r--r--pfinet/linux-src/net/core/profile.c305
-rw-r--r--pfinet/linux-src/net/core/rtnetlink.c512
-rw-r--r--pfinet/linux-src/net/core/scm.c280
-rw-r--r--pfinet/linux-src/net/core/skbuff.c385
-rw-r--r--pfinet/linux-src/net/core/sock.c1051
-rw-r--r--pfinet/linux-src/net/core/sysctl_net_core.c61
-rw-r--r--pfinet/linux-src/net/core/utils.c66
-rw-r--r--pfinet/linux-src/net/ethernet/Makefile33
-rw-r--r--pfinet/linux-src/net/ethernet/eth.c298
-rw-r--r--pfinet/linux-src/net/ethernet/pe2.c38
-rw-r--r--pfinet/linux-src/net/ethernet/sysctl_net_ether.c13
-rw-r--r--pfinet/linux-src/net/ipv4/Config.in88
-rw-r--r--pfinet/linux-src/net/ipv4/Makefile116
-rw-r--r--pfinet/linux-src/net/ipv4/af_inet.c1161
-rw-r--r--pfinet/linux-src/net/ipv4/arp.c1154
-rw-r--r--pfinet/linux-src/net/ipv4/devinet.c1034
-rw-r--r--pfinet/linux-src/net/ipv4/fib_frontend.c628
-rw-r--r--pfinet/linux-src/net/ipv4/fib_hash.c885
-rw-r--r--pfinet/linux-src/net/ipv4/fib_rules.c419
-rw-r--r--pfinet/linux-src/net/ipv4/fib_semantics.c991
-rw-r--r--pfinet/linux-src/net/ipv4/icmp.c1155
-rw-r--r--pfinet/linux-src/net/ipv4/igmp.c698
-rw-r--r--pfinet/linux-src/net/ipv4/ip_forward.c297
-rw-r--r--pfinet/linux-src/net/ipv4/ip_fragment.c593
-rw-r--r--pfinet/linux-src/net/ipv4/ip_fw.c1759
-rw-r--r--pfinet/linux-src/net/ipv4/ip_gre.c1223
-rw-r--r--pfinet/linux-src/net/ipv4/ip_input.c549
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq.c2545
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_app.c603
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_autofw.c448
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_cuseeme.c264
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_ftp.c393
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_irc.c345
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_mfw.c769
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_mod.c322
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_portfw.c508
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_quake.c322
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_raudio.c578
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_user.c473
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_vdolive.c294
-rw-r--r--pfinet/linux-src/net/ipv4/ip_nat_dumb.c158
-rw-r--r--pfinet/linux-src/net/ipv4/ip_options.c617
-rw-r--r--pfinet/linux-src/net/ipv4/ip_output.c992
-rw-r--r--pfinet/linux-src/net/ipv4/ip_sockglue.c739
-rw-r--r--pfinet/linux-src/net/ipv4/ipconfig.c970
-rw-r--r--pfinet/linux-src/net/ipv4/ipip.c870
-rw-r--r--pfinet/linux-src/net/ipv4/ipmr.c1609
-rw-r--r--pfinet/linux-src/net/ipv4/proc.c387
-rw-r--r--pfinet/linux-src/net/ipv4/protocol.c211
-rw-r--r--pfinet/linux-src/net/ipv4/rarp.c606
-rw-r--r--pfinet/linux-src/net/ipv4/raw.c573
-rw-r--r--pfinet/linux-src/net/ipv4/route.c2048
-rw-r--r--pfinet/linux-src/net/ipv4/syncookies.c201
-rw-r--r--pfinet/linux-src/net/ipv4/sysctl_net_ipv4.c205
-rw-r--r--pfinet/linux-src/net/ipv4/tcp.c1826
-rw-r--r--pfinet/linux-src/net/ipv4/tcp_input.c2432
-rw-r--r--pfinet/linux-src/net/ipv4/tcp_ipv4.c2044
-rw-r--r--pfinet/linux-src/net/ipv4/tcp_output.c1143
-rw-r--r--pfinet/linux-src/net/ipv4/tcp_timer.c595
-rw-r--r--pfinet/linux-src/net/ipv4/timer.c127
-rw-r--r--pfinet/linux-src/net/ipv4/udp.c1191
-rw-r--r--pfinet/linux-src/net/ipv4/utils.c91
516 files changed, 118264 insertions, 0 deletions
diff --git a/pfinet/linux-src/arch/alpha/lib/checksum.c b/pfinet/linux-src/arch/alpha/lib/checksum.c
new file mode 100644
index 00000000..5165279f
--- /dev/null
+++ b/pfinet/linux-src/arch/alpha/lib/checksum.c
@@ -0,0 +1,169 @@
+/*
+ * arch/alpha/lib/checksum.c
+ *
+ * This file contains network checksum routines that are better done
+ * in an architecture-specific manner due to speed..
+ */
+
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+
+static inline unsigned short from64to16(unsigned long x)
+{
+ /* add up 32-bit words for 33 bits */
+ x = (x & 0xffffffff) + (x >> 32);
+ /* add up 16-bit and 17-bit words for 17+c bits */
+ x = (x & 0xffff) + (x >> 16);
+ /* add up 16-bit and 2-bit for 16+c bit */
+ x = (x & 0xffff) + (x >> 16);
+ /* add up carry.. */
+ x = (x & 0xffff) + (x >> 16);
+ return x;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return ~from64to16(saddr + daddr + sum +
+ ((unsigned long) ntohs(len) << 16) +
+ ((unsigned long) proto << 8));
+}
+
+unsigned int csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ unsigned long result;
+
+ result = (saddr + daddr + sum +
+ ((unsigned long) ntohs(len) << 16) +
+ ((unsigned long) proto << 8));
+
+ /* Fold down to 32-bits so we don't loose in the typedef-less
+ network stack. */
+ /* 64 to 33 */
+ result = (result & 0xffffffff) + (result >> 32);
+ /* 33 to 32 */
+ result = (result & 0xffffffff) + (result >> 32);
+ return result;
+}
+
+/*
+ * Do a 64-bit checksum on an arbitrary memory area..
+ *
+ * This isn't a great routine, but it's not _horrible_ either. The
+ * inner loop could be unrolled a bit further, and there are better
+ * ways to do the carry, but this is reasonable.
+ */
+static inline unsigned long do_csum(const unsigned char * buff, int len)
+{
+ int odd, count;
+ unsigned long result = 0;
+
+ if (len <= 0)
+ goto out;
+ odd = 1 & (unsigned long) buff;
+ if (odd) {
+ result = *buff << 8;
+ len--;
+ buff++;
+ }
+ count = len >> 1; /* nr of 16-bit words.. */
+ if (count) {
+ if (2 & (unsigned long) buff) {
+ result += *(unsigned short *) buff;
+ count--;
+ len -= 2;
+ buff += 2;
+ }
+ count >>= 1; /* nr of 32-bit words.. */
+ if (count) {
+ if (4 & (unsigned long) buff) {
+ result += *(unsigned int *) buff;
+ count--;
+ len -= 4;
+ buff += 4;
+ }
+ count >>= 1; /* nr of 64-bit words.. */
+ if (count) {
+ unsigned long carry = 0;
+ do {
+ unsigned long w = *(unsigned long *) buff;
+ count--;
+ buff += 8;
+ result += carry;
+ result += w;
+ carry = (w > result);
+ } while (count);
+ result += carry;
+ result = (result & 0xffffffff) + (result >> 32);
+ }
+ if (len & 4) {
+ result += *(unsigned int *) buff;
+ buff += 4;
+ }
+ }
+ if (len & 2) {
+ result += *(unsigned short *) buff;
+ buff += 2;
+ }
+ }
+ if (len & 1)
+ result += *buff;
+ result = from64to16(result);
+ if (odd)
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+ return result;
+}
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+ return ~do_csum(iph,ihl*4);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+{
+ unsigned long result = do_csum(buff, len);
+
+ /* add in old sum, and carry.. */
+ result += sum;
+ /* 32+c bits -> 32 bits */
+ result = (result & 0xffffffff) + (result >> 32);
+ return result;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+ return ~from64to16(do_csum(buff,len));
+}
diff --git a/pfinet/linux-src/arch/arm/lib/checksum.S b/pfinet/linux-src/arch/arm/lib/checksum.S
new file mode 100644
index 00000000..bd5c78d3
--- /dev/null
+++ b/pfinet/linux-src/arch/arm/lib/checksum.S
@@ -0,0 +1,730 @@
+/*
+ * linux/arch/arm/lib/checksum.S
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 Russell King
+ */
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+#include "constants.h"
+
+ .text
+
+/* Function: __u32 csum_partial(const char *src, int len, __u32)
+ * Params : r0 = buffer, r1 = len, r2 = checksum
+ * Returns : r0 = new checksum
+ */
+
+ENTRY(csum_partial)
+ tst r0, #2
+ beq 1f
+ subs r1, r1, #2
+ addmi r1, r1, #2
+ bmi 3f
+ bic r0, r0, #3
+ ldr r3, [r0], #4
+ adds r2, r2, r3, lsr #16
+ adcs r2, r2, #0
+1: adds r2, r2, #0
+ bics ip, r1, #31
+ beq 3f
+ stmfd sp!, {r4 - r6}
+2: ldmia r0!, {r3 - r6}
+ adcs r2, r2, r3
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ adcs r2, r2, r6
+ ldmia r0!, {r3 - r6}
+ adcs r2, r2, r3
+ adcs r2, r2, r4
+ adcs r2, r2, r5
+ adcs r2, r2, r6
+ sub ip, ip, #32
+ teq ip, #0
+ bne 2b
+ adcs r2, r2, #0
+ ldmfd sp!, {r4 - r6}
+3: ands ip, r1, #0x1c
+ beq 5f
+4: ldr r3, [r0], #4
+ adcs r2, r2, r3
+ sub ip, ip, #4
+ teq ip, #0
+ bne 4b
+ adcs r2, r2, #0
+5: ands ip, r1, #3
+ moveq r0, r2
+ RETINSTR(moveq,pc,lr)
+ mov ip, ip, lsl #3
+ rsb ip, ip, #32
+ ldr r3, [r0]
+ mov r3, r3, lsl ip
+ adds r2, r2, r3, lsr ip
+ adc r0, r2, #0
+ RETINSTR(mov,pc,lr)
+
+/* Function: __u32 csum_partial_copy_from_user (const char *src, char *dst, int len, __u32 sum, int *err_ptr)
+ * Params : r0 = src, r1 = dst, r2 = len, r3 = sum, [sp, #0] = &err
+ * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT
+ */
+#if defined(CONFIG_CPU_32)
+
+ .macro save_regs
+ stmfd sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}
+ .endm
+
+#define LOAD_REGS(cond) \
+ LOADREGS(##cond##ea,fp,{r1 - r2, r4 - r8, fp, sp, pc})
+
+ .macro load1b, reg1
+9999: ldrbt \reg1, [r0], $1
+ .section __ex_table, "a"
+ .align 3
+ .long 9999b, 6001f
+ .previous
+ .endm
+
+ .macro load2b, reg1, reg2
+9999: ldrbt \reg1, [r0], $1
+9998: ldrbt \reg2, [r0], $1
+ .section __ex_table, "a"
+ .long 9999b, 6001f
+ .long 9998b, 6001f
+ .previous
+ .endm
+
+ .macro load1l, reg1
+9999: ldrt \reg1, [r0], $4
+ .section __ex_table, "a"
+ .align 3
+ .long 9999b, 6001f
+ .previous
+ .endm
+
+ .macro load2l, reg1, reg2
+9999: ldrt \reg1, [r0], $4
+9998: ldrt \reg2, [r0], $4
+ .section __ex_table, "a"
+ .long 9999b, 6001f
+ .long 9998b, 6001f
+ .previous
+ .endm
+
+ .macro load4l, reg1, reg2, reg3, reg4
+9999: ldrt \reg1, [r0], $4
+9998: ldrt \reg2, [r0], $4
+9997: ldrt \reg3, [r0], $4
+9996: ldrt \reg4, [r0], $4
+ .section __ex_table, "a"
+ .long 9999b, 6001f
+ .long 9998b, 6001f
+ .long 9997b, 6001f
+ .long 9996b, 6001f
+ .previous
+ .endm
+
+#elif defined(CONFIG_CPU_26)
+
+ .macro save_regs
+ stmfd sp!, {r1 - r2, r4 - r9, fp, ip, lr, pc}
+ mov r9, sp, lsr #13
+ mov r9, r9, lsl #13
+ ldr r9, [r9, #TSK_ADDR_LIMIT]
+ mov r9, r9, lsr #24
+ .endm
+
+#define LOAD_REGS(cond) \
+ LOADREGS(##cond##ea,fp,{r1 - r2, r4 - r9, fp, sp, pc})
+
+ .macro load1b, reg1
+ tst r9, #0x01
+9999: ldreqbt \reg1, [r0], #1
+ ldrneb \reg1, [r0], #1
+ .section __ex_table, "a"
+ .align 3
+ .long 9999b, 6001f
+ .previous
+ .endm
+
+ .macro load2b, reg1, reg2
+ tst r9, #0x01
+9999: ldreqbt \reg1, [r0], #1
+ ldrneb \reg1, [r0], #1
+9998: ldreqbt \reg2, [r0], #1
+ ldrneb \reg2, [r0], #1
+ .section __ex_table, "a"
+ .long 9999b, 6001f
+ .long 9998b, 6001f
+ .previous
+ .endm
+
+ .macro load1l, reg1
+ tst r9, #0x01
+9999: ldreqt \reg1, [r0], #4
+ ldrne \reg1, [r0], #4
+ .section __ex_table, "a"
+ .align 3
+ .long 9999b, 6001f
+ .previous
+ .endm
+
+ .macro load2l, reg1, reg2
+ tst r9, #0x01
+ ldmneia r0!, {\reg1, \reg2}
+9999: ldreqt \reg1, [r0], #4
+9998: ldreqt \reg2, [r0], #4
+ .section __ex_table, "a"
+ .long 9999b, 6001f
+ .long 9998b, 6001f
+ .previous
+ .endm
+
+ .macro load4l, reg1, reg2, reg3, reg4
+ tst r9, #0x01
+ ldmneia r0!, {\reg1, \reg2, \reg3, \reg4}
+9999: ldreqt \reg1, [r0], #4
+9998: ldreqt \reg2, [r0], #4
+9997: ldreqt \reg3, [r0], #4
+9996: ldreqt \reg4, [r0], #4
+ .section __ex_table, "a"
+ .long 9999b, 6001f
+ .long 9998b, 6001f
+ .long 9997b, 6001f
+ .long 9996b, 6001f
+ .previous
+ .endm
+
+#else
+#error Unknown CPU architecture
+#endif
+
+ENTRY(csum_partial_copy_from_user)
+ mov ip, sp
+ save_regs
+ sub fp, ip, #4
+ cmp r2, #4
+ blt .too_small_user
+ tst r1, #2 @ Test destination alignment
+ beq .dst_aligned_user
+ subs r2, r2, #2 @ We do not know if SRC is aligned...
+ load2b ip, r8
+ orr ip, ip, r8, lsl #8
+ adds r3, r3, ip
+ adcs r3, r3, #0
+ strb ip, [r1], #1
+ mov ip, ip, lsr #8
+ strb ip, [r1], #1 @ Destination now aligned
+.dst_aligned_user:
+ tst r0, #3
+ bne .src_not_aligned_user
+ adds r3, r3, #0
+ bics ip, r2, #15 @ Routine for src & dst aligned
+ beq 2f
+1: load4l r4, r5, r6, r7
+ stmia r1!, {r4, r5, r6, r7}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ adcs r3, r3, r6
+ adcs r3, r3, r7
+ sub ip, ip, #16
+ teq ip, #0
+ bne 1b
+2: ands ip, r2, #12
+ beq 4f
+ tst ip, #8
+ beq 3f
+ load2l r4, r5
+ stmia r1!, {r4, r5}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ tst ip, #4
+ beq 4f
+3: load1l r4
+ str r4, [r1], #4
+ adcs r3, r3, r4
+4: ands r2, r2, #3
+ adceq r0, r3, #0
+ LOAD_REGS(eq)
+ load1l r4
+ tst r2, #2
+ beq .exit
+ adcs r3, r3, r4, lsl #16
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+.exit: tst r2, #1
+ strneb r4, [r1], #1
+ andne r4, r4, #255
+ adcnes r3, r3, r4
+ adcs r0, r3, #0
+ LOAD_REGS(al)
+
+.too_small_user:
+ teq r2, #0
+ LOAD_REGS(eq)
+ cmp r2, #2
+ blt .too_small_user1
+ load2b ip, r8
+ orr ip, ip, r8, lsl #8
+ adds r3, r3, ip
+ strb ip, [r1], #1
+ strb r8, [r1], #1
+ tst r2, #1
+.too_small_user1: @ C = 0
+ beq .csum_exit
+ load1b ip
+ strb ip, [r1], #1
+ adcs r3, r3, ip
+.csum_exit: adc r0, r3, #0
+ LOAD_REGS(al)
+
+.src_not_aligned_user:
+ cmp r2, #4
+ blt .too_small_user
+ and ip, r0, #3
+ bic r0, r0, #3
+ load1l r4
+ cmp ip, #2
+ beq .src2_aligned_user
+ bhi .src3_aligned_user
+ mov r4, r4, lsr #8
+ adds r3, r3, #0
+ bics ip, r2, #15
+ beq 2f
+1: load4l r5, r6, r7, r8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ mov r6, r6, lsr #8
+ orr r6, r6, r7, lsl #24
+ mov r7, r7, lsr #8
+ orr r7, r7, r8, lsl #24
+ stmia r1!, {r4, r5, r6, r7}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ adcs r3, r3, r6
+ adcs r3, r3, r7
+ mov r4, r8, lsr #8
+ sub ip, ip, #16
+ teq ip, #0
+ bne 1b
+2: ands ip, r2, #12
+ beq 4f
+ tst ip, #8
+ beq 3f
+ load2l r5, r6
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ stmia r1!, {r4, r5}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ mov r4, r6, lsr #8
+ tst ip, #4
+ beq 4f
+3: load1l r5
+ orr r4, r4, r5, lsl #24
+ str r4, [r1], #4
+ adcs r3, r3, r4
+ mov r4, r5, lsr #8
+4: ands r2, r2, #3
+ adceq r0, r3, #0
+ LOAD_REGS(eq)
+ tst r2, #2
+ beq .exit
+ adcs r3, r3, r4, lsl #16
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ b .exit
+
+.src2_aligned_user:
+ mov r4, r4, lsr #16
+ adds r3, r3, #0
+ bics ip, r2, #15
+ beq 2f
+1: load4l r5, r6, r7, r8
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ mov r6, r6, lsr #16
+ orr r6, r6, r7, lsl #16
+ mov r7, r7, lsr #16
+ orr r7, r7, r8, lsl #16
+ stmia r1!, {r4, r5, r6, r7}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ adcs r3, r3, r6
+ adcs r3, r3, r7
+ mov r4, r8, lsr #16
+ sub ip, ip, #16
+ teq ip, #0
+ bne 1b
+2: ands ip, r2, #12
+ beq 4f
+ tst ip, #8
+ beq 3f
+ load2l r5, r6
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ stmia r1!, {r4, r5}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ mov r4, r6, lsr #16
+ tst ip, #4
+ beq 4f
+3: load1l r5
+ orr r4, r4, r5, lsl #16
+ str r4, [r1], #4
+ adcs r3, r3, r4
+ mov r4, r5, lsr #16
+4: ands r2, r2, #3
+ adceq r0, r3, #0
+ LOAD_REGS(eq)
+ tst r2, #2
+ beq .exit
+ adcs r3, r3, r4, lsl #16
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ strb r4, [r1], #1
+ load1b r4
+ b .exit
+
+.src3_aligned_user:
+ mov r4, r4, lsr #24
+ adds r3, r3, #0
+ bics ip, r2, #15
+ beq 2f
+1: load4l r5, r6, r7, r8
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ mov r6, r6, lsr #24
+ orr r6, r6, r7, lsl #8
+ mov r7, r7, lsr #24
+ orr r7, r7, r8, lsl #8
+ stmia r1!, {r4, r5, r6, r7}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ adcs r3, r3, r6
+ adcs r3, r3, r7
+ mov r4, r8, lsr #24
+ sub ip, ip, #16
+ teq ip, #0
+ bne 1b
+2: ands ip, r2, #12
+ beq 4f
+ tst ip, #8
+ beq 3f
+ load2l r5, r6
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ stmia r1!, {r4, r5}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ mov r4, r6, lsr #24
+ tst ip, #4
+ beq 4f
+3: load1l r5
+ orr r4, r4, r5, lsl #8
+ str r4, [r1], #4
+ adcs r3, r3, r4
+ mov r4, r5, lsr #24
+4: ands r2, r2, #3
+ adceq r0, r3, #0
+ LOAD_REGS(eq)
+ tst r2, #2
+ beq .exit
+ adcs r3, r3, r4, lsl #16
+ strb r4, [r1], #1
+ load1l r4
+ strb r4, [r1], #1
+ adcs r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ b .exit
+
+#if defined(CONFIG_CPU_32)
+ .section .fixup,"ax"
+#endif
+ .align 4
+6001: mov r4, #-EFAULT
+ ldr r5, [fp, #4]
+ str r4, [r5]
+ ldmia sp, {r1, r2} @ retrieve original arguments
+ add r2, r2, r1
+ mov r3, #0 @ zero the buffer
+6002: teq r2, r1
+ strneb r3, [r1], #1
+ bne 6002b
+ LOAD_REGS(al)
+#if defined(CONFIG_CPU_32)
+ .previous
+#endif
+
+/* Function: __u32 csum_partial_copy (const char *src, char *dst, int len, __u32 sum)
+ * Params : r0 = src, r1 = dst, r2 = len, r3 = checksum
+ * Returns : r0 = new checksum
+ */
+ENTRY(csum_partial_copy_nocheck)
+ENTRY(csum_partial_copy)
+ mov ip, sp
+ stmfd sp!, {r4 - r8, fp, ip, lr, pc}
+ sub fp, ip, #4
+ cmp r2, #4
+ blt Ltoo_small
+ tst r1, #2 @ Test destination alignment
+ beq Ldst_aligned
+ subs r2, r2, #2 @ We do not know if SRC is aligned...
+ ldrb ip, [r0], #1
+ ldrb r8, [r0], #1
+ orr ip, ip, r8, lsl #8
+ adds r3, r3, ip
+ adcs r3, r3, #0
+ strb ip, [r1], #1
+ mov ip, ip, lsr #8
+ strb ip, [r1], #1 @ Destination now aligned
+Ldst_aligned: tst r0, #3
+ bne Lsrc_not_aligned
+ adds r3, r3, #0
+ bics ip, r2, #15 @ Routine for src & dst aligned
+ beq 3f
+1: ldmia r0!, {r4, r5, r6, r7}
+ stmia r1!, {r4, r5, r6, r7}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ adcs r3, r3, r6
+ adcs r3, r3, r7
+ sub ip, ip, #16
+ teq ip, #0
+ bne 1b
+3: ands ip, r2, #12
+ beq 5f
+ tst ip, #8
+ beq 4f
+ ldmia r0!, {r4, r5}
+ stmia r1!, {r4, r5}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ tst ip, #4
+ beq 5f
+4: ldr r4, [r0], #4
+ str r4, [r1], #4
+ adcs r3, r3, r4
+5: ands r2, r2, #3
+ adceq r0, r3, #0
+ LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+ ldr r4, [r0], #4
+ tst r2, #2
+ beq Lexit
+ adcs r3, r3, r4, lsl #16
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ b Lexit
+
+Ltoo_small: teq r2, #0
+ LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+ cmp r2, #2
+ blt Ltoo_small1
+ ldrb ip, [r0], #1
+ ldrb r8, [r0], #1
+ orr ip, ip, r8, lsl #8
+ adds r3, r3, ip
+ strb ip, [r1], #1
+ strb r8, [r1], #1
+Lexit: tst r2, #1
+Ltoo_small1: ldrneb ip, [r0], #1
+ strneb ip, [r1], #1
+ adcnes r3, r3, ip
+ adcs r0, r3, #0
+ LOADREGS(ea,fp,{r4 - r8, fp, sp, pc})
+
+Lsrc_not_aligned:
+ cmp r2, #4
+ blt Ltoo_small
+ and ip, r0, #3
+ bic r0, r0, #3
+ ldr r4, [r0], #4
+ cmp ip, #2
+ beq Lsrc2_aligned
+ bhi Lsrc3_aligned
+ mov r4, r4, lsr #8
+ adds r3, r3, #0
+ bics ip, r2, #15
+ beq 2f
+1: ldmia r0!, {r5, r6, r7, r8}
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ mov r6, r6, lsr #8
+ orr r6, r6, r7, lsl #24
+ mov r7, r7, lsr #8
+ orr r7, r7, r8, lsl #24
+ stmia r1!, {r4, r5, r6, r7}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ adcs r3, r3, r6
+ adcs r3, r3, r7
+ mov r4, r8, lsr #8
+ sub ip, ip, #16
+ teq ip, #0
+ bne 1b
+2: ands ip, r2, #12
+ beq 4f
+ tst ip, #8
+ beq 3f
+ ldmia r0!, {r5, r6}
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ stmia r1!, {r4, r5}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ mov r4, r6, lsr #8
+ tst ip, #4
+ beq 4f
+3: ldr r5, [r0], #4
+ orr r4, r4, r5, lsl #24
+ str r4, [r1], #4
+ adcs r3, r3, r4
+ mov r4, r5, lsr #8
+4: ands r2, r2, #3
+ adceq r0, r3, #0
+ LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+ tst r2, #2
+ beq Lexit
+ adcs r3, r3, r4, lsl #16
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ b Lexit
+
+Lsrc2_aligned: mov r4, r4, lsr #16
+ adds r3, r3, #0
+ bics ip, r2, #15
+ beq 2f
+1: ldmia r0!, {r5, r6, r7, r8}
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ mov r6, r6, lsr #16
+ orr r6, r6, r7, lsl #16
+ mov r7, r7, lsr #16
+ orr r7, r7, r8, lsl #16
+ stmia r1!, {r4, r5, r6, r7}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ adcs r3, r3, r6
+ adcs r3, r3, r7
+ mov r4, r8, lsr #16
+ sub ip, ip, #16
+ teq ip, #0
+ bne 1b
+2: ands ip, r2, #12
+ beq 4f
+ tst ip, #8
+ beq 3f
+ ldmia r0!, {r5, r6}
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ stmia r1!, {r4, r5}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ mov r4, r6, lsr #16
+ tst ip, #4
+ beq 4f
+3: ldr r5, [r0], #4
+ orr r4, r4, r5, lsl #16
+ str r4, [r1], #4
+ adcs r3, r3, r4
+ mov r4, r5, lsr #16
+4: ands r2, r2, #3
+ adceq r0, r3, #0
+ LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+ tst r2, #2
+ beq Lexit
+ adcs r3, r3, r4, lsl #16
+ strb r4, [r1], #1
+ mov r4, r4, lsr #8
+ strb r4, [r1], #1
+ ldrb r4, [r0], #1
+ b Lexit
+
+Lsrc3_aligned: mov r4, r4, lsr #24
+ adds r3, r3, #0
+ bics ip, r2, #15
+ beq 2f
+1: ldmia r0!, {r5, r6, r7, r8}
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ mov r6, r6, lsr #24
+ orr r6, r6, r7, lsl #8
+ mov r7, r7, lsr #24
+ orr r7, r7, r8, lsl #8
+ stmia r1!, {r4, r5, r6, r7}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ adcs r3, r3, r6
+ adcs r3, r3, r7
+ mov r4, r8, lsr #24
+ sub ip, ip, #16
+ teq ip, #0
+ bne 1b
+2: ands ip, r2, #12
+ beq 4f
+ tst ip, #8
+ beq 3f
+ ldmia r0!, {r5, r6}
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ stmia r1!, {r4, r5}
+ adcs r3, r3, r4
+ adcs r3, r3, r5
+ mov r4, r6, lsr #24
+ tst ip, #4
+ beq 4f
+3: ldr r5, [r0], #4
+ orr r4, r4, r5, lsl #8
+ str r4, [r1], #4
+ adcs r3, r3, r4
+ mov r4, r5, lsr #24
+4: ands r2, r2, #3
+ adceq r0, r3, #0
+ LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+ tst r2, #2
+ beq Lexit
+ adcs r3, r3, r4, lsl #16
+ strb r4, [r1], #1
+ ldr r4, [r0], #4
+ strb r4, [r1], #1
+ adcs r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ b Lexit
+
+ENTRY(__csum_ipv6_magic)
+ stmfd sp!, {lr}
+ adds ip, r2, r3
+ ldmia r1, {r1 - r3, lr}
+ adcs ip, ip, r1
+ adcs ip, ip, r2
+ adcs ip, ip, r3
+ adcs ip, ip, lr
+ ldmia r0, {r0 - r3}
+ adcs r0, ip, r0
+ adcs r0, r0, r1
+ adcs r0, r0, r2
+ adcs r0, r0, r3
+ ldr r3, [sp, #4]
+ adcs r0, r0, r3
+ adcs r0, r0, #0
+ LOADREGS(fd, sp!, {pc})
diff --git a/pfinet/linux-src/arch/i386/lib/checksum.S b/pfinet/linux-src/arch/i386/lib/checksum.S
new file mode 100644
index 00000000..af10dc7c
--- /dev/null
+++ b/pfinet/linux-src/arch/i386/lib/checksum.S
@@ -0,0 +1,447 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IP/TCP/UDP checksumming routines
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Tom May, <ftom@netcom.com>
+ * Pentium Pro/II routines:
+ * Alexander Kjeldaas <astor@guardian.no>
+ * Finn Arne Gangstad <finnag@guardian.no>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ * handling.
+ * Andi Kleen, add zeroing on error
+ * converted to pure assembler
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/errno.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+
+.text
+.align 4
+.globl csum_partial
+
+#if CPU!=686
+
+ /*
+ * Experiments with Ethernet and SLIP connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary. We get at
+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+ * alignment for the unrolled loop.
+ */
+csum_partial:
+ pushl %esi
+ pushl %ebx
+ movl 20(%esp),%eax # Function arg: unsigned int sum
+ movl 16(%esp),%ecx # Function arg: int len
+ movl 12(%esp),%esi # Function arg: unsigned char *buff
+ testl $2, %esi # Check alignment.
+ jz 2f # Jump if alignment is ok.
+ subl $2, %ecx # Alignment uses up two bytes.
+ jae 1f # Jump if we had at least two bytes.
+ addl $2, %ecx # ecx was < 2. Deal with it.
+ jmp 4f
+1: movw (%esi), %bx
+ addl $2, %esi
+ addw %bx, %ax
+ adcl $0, %eax
+2:
+ movl %ecx, %edx
+ shrl $5, %ecx
+ jz 2f
+ testl %esi, %esi
+1: movl (%esi), %ebx
+ adcl %ebx, %eax
+ movl 4(%esi), %ebx
+ adcl %ebx, %eax
+ movl 8(%esi), %ebx
+ adcl %ebx, %eax
+ movl 12(%esi), %ebx
+ adcl %ebx, %eax
+ movl 16(%esi), %ebx
+ adcl %ebx, %eax
+ movl 20(%esi), %ebx
+ adcl %ebx, %eax
+ movl 24(%esi), %ebx
+ adcl %ebx, %eax
+ movl 28(%esi), %ebx
+ adcl %ebx, %eax
+ lea 32(%esi), %esi
+ dec %ecx
+ jne 1b
+ adcl $0, %eax
+2: movl %edx, %ecx
+ andl $0x1c, %edx
+ je 4f
+ shrl $2, %edx # This clears CF
+3: adcl (%esi), %eax
+ lea 4(%esi), %esi
+ dec %edx
+ jne 3b
+ adcl $0, %eax
+4: andl $3, %ecx
+ jz 7f
+ cmpl $2, %ecx
+ jb 5f
+ movw (%esi),%cx
+ leal 2(%esi),%esi
+ je 6f
+ shll $16,%ecx
+5: movb (%esi),%cl
+6: addl %ecx,%eax
+ adcl $0, %eax
+7:
+ popl %ebx
+ popl %esi
+ ret
+
+#else /* CPU==686 */
+
+csum_partial:
+ movl 12(%esp),%eax # Function arg: unsigned int sum
+ movl 8(%esp),%ecx # Function arg: int len
+ movl 4(%esp),%esi # Function arg: const unsigned char *buf
+
+ testl $2, %esi
+ jnz 30f
+10:
+ movl %ecx, %edx
+ movl %ecx, %ebx
+ andl $0x7c, %ebx
+ shrl $7, %ecx
+ addl %ebx,%esi
+ shrl $2, %ebx
+ negl %ebx
+ lea 45f(%ebx,%ebx,2), %ebx
+ testl %esi, %esi
+ jmp *%ebx
+
+ # Handle 2-byte-aligned regions
+20: addw (%esi), %ax
+ lea 2(%esi), %esi
+ adcl $0, %eax
+ jmp 10b
+
+30: subl $2, %ecx
+ ja 20b
+ je 32f
+ movzbl (%esi),%ebx # csumming 1 byte, 2-aligned
+ addl %ebx, %eax
+ adcl $0, %eax
+ jmp 80f
+32:
+ addw (%esi), %ax # csumming 2 bytes, 2-aligned
+ adcl $0, %eax
+ jmp 80f
+
+40:
+ addl -128(%esi), %eax
+ adcl -124(%esi), %eax
+ adcl -120(%esi), %eax
+ adcl -116(%esi), %eax
+ adcl -112(%esi), %eax
+ adcl -108(%esi), %eax
+ adcl -104(%esi), %eax
+ adcl -100(%esi), %eax
+ adcl -96(%esi), %eax
+ adcl -92(%esi), %eax
+ adcl -88(%esi), %eax
+ adcl -84(%esi), %eax
+ adcl -80(%esi), %eax
+ adcl -76(%esi), %eax
+ adcl -72(%esi), %eax
+ adcl -68(%esi), %eax
+ adcl -64(%esi), %eax
+ adcl -60(%esi), %eax
+ adcl -56(%esi), %eax
+ adcl -52(%esi), %eax
+ adcl -48(%esi), %eax
+ adcl -44(%esi), %eax
+ adcl -40(%esi), %eax
+ adcl -36(%esi), %eax
+ adcl -32(%esi), %eax
+ adcl -28(%esi), %eax
+ adcl -24(%esi), %eax
+ adcl -20(%esi), %eax
+ adcl -16(%esi), %eax
+ adcl -12(%esi), %eax
+ adcl -8(%esi), %eax
+ adcl -4(%esi), %eax
+45:
+ lea 128(%esi), %esi
+ adcl $0, %eax
+ dec %ecx
+ jge 40b
+ movl %edx, %ecx
+50: andl $3, %ecx
+ jz 80f
+
+ # Handle the last 1-3 bytes without jumping
+ notl %ecx # 1->2, 2->1, 3->0, higher bits are masked
+ movl $0xffffff,%ebx # by the shll and shrl instructions
+ shll $3,%ecx
+ shrl %cl,%ebx
+ andl -128(%esi),%ebx # esi is 4-aligned so should be ok
+ addl %ebx,%eax
+ adcl $0,%eax
+80:
+ ret
+
+#endif /* CPU==686 */
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst,
+ int len, int sum, int *src_err_ptr, int *dst_err_ptr)
+ */
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ * DST definitions? It's damn hard to trigger all cases. I hope I got
+ * them all but there's no guarantee.
+ */
+
+#define SRC(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6001f ; \
+ .previous
+
+#define DST(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6002f ; \
+ .previous
+
+.align 4
+.globl csum_partial_copy_generic
+
+#if CPU!=686
+
+#define ARGBASE 16
+#define FP 12
+
+csum_partial_copy_generic:
+ subl $4,%esp
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ movl ARGBASE+16(%esp),%eax # sum
+ movl ARGBASE+12(%esp),%ecx # len
+ movl ARGBASE+4(%esp),%esi # src
+ movl ARGBASE+8(%esp),%edi # dst
+
+ testl $2, %edi # Check alignment.
+ jz 2f # Jump if alignment is ok.
+ subl $2, %ecx # Alignment uses up two bytes.
+ jae 1f # Jump if we had at least two bytes.
+ addl $2, %ecx # ecx was < 2. Deal with it.
+ jmp 4f
+SRC(1: movw (%esi), %bx )
+ addl $2, %esi
+DST( movw %bx, (%edi) )
+ addl $2, %edi
+ addw %bx, %ax
+ adcl $0, %eax
+2:
+ movl %ecx, FP(%esp)
+ shrl $5, %ecx
+ jz 2f
+ testl %esi, %esi
+SRC(1: movl (%esi), %ebx )
+SRC( movl 4(%esi), %edx )
+ adcl %ebx, %eax
+DST( movl %ebx, (%edi) )
+ adcl %edx, %eax
+DST( movl %edx, 4(%edi) )
+
+SRC( movl 8(%esi), %ebx )
+SRC( movl 12(%esi), %edx )
+ adcl %ebx, %eax
+DST( movl %ebx, 8(%edi) )
+ adcl %edx, %eax
+DST( movl %edx, 12(%edi) )
+
+SRC( movl 16(%esi), %ebx )
+SRC( movl 20(%esi), %edx )
+ adcl %ebx, %eax
+DST( movl %ebx, 16(%edi) )
+ adcl %edx, %eax
+DST( movl %edx, 20(%edi) )
+
+SRC( movl 24(%esi), %ebx )
+SRC( movl 28(%esi), %edx )
+ adcl %ebx, %eax
+DST( movl %ebx, 24(%edi) )
+ adcl %edx, %eax
+DST( movl %edx, 28(%edi) )
+
+ lea 32(%esi), %esi
+ lea 32(%edi), %edi
+ dec %ecx
+ jne 1b
+ adcl $0, %eax
+2: movl FP(%esp), %edx
+ movl %edx, %ecx
+ andl $0x1c, %edx
+ je 4f
+ shrl $2, %edx # This clears CF
+SRC(3: movl (%esi), %ebx )
+ adcl %ebx, %eax
+DST( movl %ebx, (%edi) )
+ lea 4(%esi), %esi
+ lea 4(%edi), %edi
+ dec %edx
+ jne 3b
+ adcl $0, %eax
+4: andl $3, %ecx
+ jz 7f
+ cmpl $2, %ecx
+ jb 5f
+SRC( movw (%esi), %cx )
+ leal 2(%esi), %esi
+DST( movw %cx, (%edi) )
+ leal 2(%edi), %edi
+ je 6f
+ shll $16,%ecx
+SRC(5: movb (%esi), %cl )
+DST( movb %cl, (%edi) )
+6: addl %ecx, %eax
+ adcl $0, %eax
+7:
+5000:
+
+# Exception handler:
+.section .fixup, "ax"
+
+6001:
+ movl ARGBASE+20(%esp), %ebx # src_err_ptr
+ movl $-EFAULT, (%ebx)
+
+ # zero the complete destination - computing the rest
+ # is too much work
+ movl ARGBASE+8(%esp), %edi # dst
+ movl ARGBASE+12(%esp), %ecx # len
+ xorl %eax,%eax
+ rep ; stosb
+
+ jmp 5000b
+
+6002:
+ movl ARGBASE+24(%esp), %ebx # dst_err_ptr
+ movl $-EFAULT,(%ebx)
+ jmp 5000b
+
+.previous
+
+ popl %ebx
+ popl %esi
+ popl %edi
+ popl %ecx # equivalent to addl $4,%esp
+ ret
+
+#else
+
+/* Version for PentiumII/PPro */
+
+#define ROUND1(x) \
+ SRC(movl x(%esi), %ebx ) ; \
+ addl %ebx, %eax ; \
+ DST(movl %ebx, x(%edi) ) ;
+
+#define ROUND(x) \
+ SRC(movl x(%esi), %ebx ) ; \
+ adcl %ebx, %eax ; \
+ DST(movl %ebx, x(%edi) ) ;
+
+#define ARGBASE 12
+
+csum_partial_copy_generic:
+ pushl %ebx
+ pushl %edi
+ pushl %esi
+ movl ARGBASE+4(%esp),%esi #src
+ movl ARGBASE+8(%esp),%edi #dst
+ movl ARGBASE+12(%esp),%ecx #len
+ movl ARGBASE+16(%esp),%eax #sum
+ movl %ecx, %edx
+ movl %ecx, %ebx
+ shrl $6, %ecx
+ andl $0x3c, %ebx
+ negl %ebx
+ subl %ebx, %esi
+ subl %ebx, %edi
+ lea 3f(%ebx,%ebx), %ebx
+ testl %esi, %esi
+ jmp *%ebx
+1: addl $64,%esi
+ addl $64,%edi
+ ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)
+ ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)
+ ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)
+ ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4)
+3: adcl $0,%eax
+ dec %ecx
+ jge 1b
+4: andl $3, %edx
+ jz 7f
+ cmpl $2, %edx
+ jb 5f
+SRC( movw (%esi), %dx )
+ leal 2(%esi), %esi
+DST( movw %dx, (%edi) )
+ leal 2(%edi), %edi
+ je 6f
+ shll $16,%edx
+5:
+SRC( movb (%esi), %dl )
+DST( movb %dl, (%edi) )
+6: addl %edx, %eax
+ adcl $0, %eax
+7:
+.section .fixup, "ax"
+6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
+ movl $-EFAULT, (%ebx)
+ # zero the complete destination (computing the rest is too much work)
+ movl ARGBASE+8(%esp),%edi # dst
+ movl ARGBASE+12(%esp),%ecx # len
+ xorl %eax,%eax
+ rep; stosb
+ jmp 7b
+6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr
+ movl $-EFAULT, (%ebx)
+ jmp 7b
+.previous
+
+ popl %esi
+ popl %edi
+ popl %ebx
+ ret
+
+#undef ROUND
+#undef ROUND1
+
+#endif /* CPU==i686 */
diff --git a/pfinet/linux-src/arch/i386/lib/old-checksum.c b/pfinet/linux-src/arch/i386/lib/old-checksum.c
new file mode 100644
index 00000000..ae3a3804
--- /dev/null
+++ b/pfinet/linux-src/arch/i386/lib/old-checksum.c
@@ -0,0 +1,19 @@
+/*
+ * FIXME: old compatibility stuff, will be removed soon.
+ */
+
+#include <net/checksum.h>
+
+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum)
+{
+ int src_err=0, dst_err=0;
+
+ sum = csum_partial_copy_generic ( src, dst, len, sum, &src_err, &dst_err);
+
+ if (src_err || dst_err)
+ printk("old csum_partial_copy_fromuser(), tell mingo to convert me.\n");
+
+ return sum;
+}
+
+
diff --git a/pfinet/linux-src/arch/m68k/lib/checksum.c b/pfinet/linux-src/arch/m68k/lib/checksum.c
new file mode 100644
index 00000000..5110cac4
--- /dev/null
+++ b/pfinet/linux-src/arch/m68k/lib/checksum.c
@@ -0,0 +1,420 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IP/TCP/UDP checksumming routines
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Tom May, <ftom@netcom.com>
+ * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
+ * Fixed some nasty bugs, causing some horrible crashes.
+ * A: At some points, the sum (%0) was used as
+ * length-counter instead of the length counter
+ * (%1). Thanks to Roman Hodek for pointing this out.
+ * B: GCC seems to mess up if one uses too many
+ * data-registers to hold input values and one tries to
+ * specify d0 and d1 as scratch registers. Letting gcc
+ * choose these registers itself solves the problem.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * 1998/8/31 Andreas Schwab:
+ * Zero out rest of buffer on exception in
+ * csum_partial_copy_from_user.
+ */
+
+#include <net/checksum.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+unsigned int
+csum_partial (const unsigned char *buff, int len, unsigned int sum)
+{
+ unsigned long tmp1, tmp2;
+ /*
+ * Experiments with ethernet and slip connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary.
+ */
+ __asm__("movel %2,%3\n\t"
+ "btst #1,%3\n\t" /* Check alignment */
+ "jeq 2f\n\t"
+ "subql #2,%1\n\t" /* buff%4==2: treat first word */
+ "jgt 1f\n\t"
+ "addql #2,%1\n\t" /* len was == 2, treat only rest */
+ "jra 4f\n"
+ "1:\t"
+ "addw %2@+,%0\n\t" /* add first word to sum */
+ "clrl %3\n\t"
+ "addxl %3,%0\n" /* add X bit */
+ "2:\t"
+ /* unrolled loop for the main part: do 8 longs at once */
+ "movel %1,%3\n\t" /* save len in tmp1 */
+ "lsrl #5,%1\n\t" /* len/32 */
+ "jeq 2f\n\t" /* not enough... */
+ "subql #1,%1\n"
+ "1:\t"
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "dbra %1,1b\n\t"
+ "clrl %4\n\t"
+ "addxl %4,%0\n\t" /* add X bit */
+ "clrw %1\n\t"
+ "subql #1,%1\n\t"
+ "jcc 1b\n"
+ "2:\t"
+ "movel %3,%1\n\t" /* restore len from tmp1 */
+ "andw #0x1c,%3\n\t" /* number of rest longs */
+ "jeq 4f\n\t"
+ "lsrw #2,%3\n\t"
+ "subqw #1,%3\n"
+ "3:\t"
+ /* loop for rest longs */
+ "movel %2@+,%4\n\t"
+ "addxl %4,%0\n\t"
+ "dbra %3,3b\n\t"
+ "clrl %4\n\t"
+ "addxl %4,%0\n" /* add X bit */
+ "4:\t"
+ /* now check for rest bytes that do not fit into longs */
+ "andw #3,%1\n\t"
+ "jeq 7f\n\t"
+ "clrl %4\n\t" /* clear tmp2 for rest bytes */
+ "subqw #2,%1\n\t"
+ "jlt 5f\n\t"
+ "movew %2@+,%4\n\t" /* have rest >= 2: get word */
+ "swap %4\n\t" /* into bits 16..31 */
+ "tstw %1\n\t" /* another byte? */
+ "jeq 6f\n"
+ "5:\t"
+ "moveb %2@,%4\n\t" /* have odd rest: get byte */
+ "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */
+ "6:\t"
+ "addl %4,%0\n\t" /* now add rest long to sum */
+ "clrl %4\n\t"
+ "addxl %4,%0\n" /* add X bit */
+ "7:\t"
+ : "=d" (sum), "=d" (len), "=a" (buff),
+ "=&d" (tmp1), "=&d" (tmp2)
+ : "0" (sum), "1" (len), "2" (buff)
+ );
+ return(sum);
+}
+
+
+
+/*
+ * copy from user space while checksumming, with exception handling.
+ */
+
+unsigned int
+csum_partial_copy_from_user(const char *src, char *dst, int len,
+ int sum, int *csum_err)
+{
+ /*
+ * GCC doesn't like more than 10 operands for the asm
+ * statements so we have to use tmp2 for the error
+ * code.
+ */
+ unsigned long tmp1, tmp2;
+
+ __asm__("movel %2,%4\n\t"
+ "btst #1,%4\n\t" /* Check alignment */
+ "jeq 2f\n\t"
+ "subql #2,%1\n\t" /* buff%4==2: treat first word */
+ "jgt 1f\n\t"
+ "addql #2,%1\n\t" /* len was == 2, treat only rest */
+ "jra 4f\n"
+ "1:\n"
+ "10:\t"
+ "movesw %2@+,%4\n\t" /* add first word to sum */
+ "addw %4,%0\n\t"
+ "movew %4,%3@+\n\t"
+ "clrl %4\n\t"
+ "addxl %4,%0\n" /* add X bit */
+ "2:\t"
+ /* unrolled loop for the main part: do 8 longs at once */
+ "movel %1,%4\n\t" /* save len in tmp1 */
+ "lsrl #5,%1\n\t" /* len/32 */
+ "jeq 2f\n\t" /* not enough... */
+ "subql #1,%1\n"
+ "1:\n"
+ "11:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "12:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "13:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "14:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "15:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "16:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "17:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "18:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "dbra %1,1b\n\t"
+ "clrl %5\n\t"
+ "addxl %5,%0\n\t" /* add X bit */
+ "clrw %1\n\t"
+ "subql #1,%1\n\t"
+ "jcc 1b\n"
+ "2:\t"
+ "movel %4,%1\n\t" /* restore len from tmp1 */
+ "andw #0x1c,%4\n\t" /* number of rest longs */
+ "jeq 4f\n\t"
+ "lsrw #2,%4\n\t"
+ "subqw #1,%4\n"
+ "3:\n"
+ /* loop for rest longs */
+ "19:\t"
+ "movesl %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "dbra %4,3b\n\t"
+ "clrl %5\n\t"
+ "addxl %5,%0\n" /* add X bit */
+ "4:\t"
+ /* now check for rest bytes that do not fit into longs */
+ "andw #3,%1\n\t"
+ "jeq 7f\n\t"
+ "clrl %5\n\t" /* clear tmp2 for rest bytes */
+ "subqw #2,%1\n\t"
+ "jlt 5f\n\t"
+ "20:\t"
+ "movesw %2@+,%5\n\t" /* have rest >= 2: get word */
+ "movew %5,%3@+\n\t"
+ "swap %5\n\t" /* into bits 16..31 */
+ "tstw %1\n\t" /* another byte? */
+ "jeq 6f\n"
+ "5:\n"
+ "21:\t"
+ "movesb %2@,%5\n\t" /* have odd rest: get byte */
+ "moveb %5,%3@+\n\t"
+ "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */
+ "6:\t"
+ "addl %5,%0\n\t" /* now add rest long to sum */
+ "clrl %5\n\t"
+ "addxl %5,%0\n\t" /* add X bit */
+ "7:\t"
+ "clrl %5\n" /* no error - clear return value */
+ "8:\n"
+ ".section .fixup,\"ax\"\n"
+ ".even\n"
+ /* If any execption occurs zero out the rest.
+ Similarities with the code above are intentional :-) */
+ "90:\t"
+ "clrw %3@+\n\t"
+ "movel %1,%4\n\t"
+ "lsrl #5,%1\n\t"
+ "jeq 1f\n\t"
+ "subql #1,%1\n"
+ "91:\t"
+ "clrl %3@+\n"
+ "92:\t"
+ "clrl %3@+\n"
+ "93:\t"
+ "clrl %3@+\n"
+ "94:\t"
+ "clrl %3@+\n"
+ "95:\t"
+ "clrl %3@+\n"
+ "96:\t"
+ "clrl %3@+\n"
+ "97:\t"
+ "clrl %3@+\n"
+ "98:\t"
+ "clrl %3@+\n\t"
+ "dbra %1,91b\n\t"
+ "clrw %1\n\t"
+ "subql #1,%1\n\t"
+ "jcc 91b\n"
+ "1:\t"
+ "movel %4,%1\n\t"
+ "andw #0x1c,%4\n\t"
+ "jeq 1f\n\t"
+ "lsrw #2,%4\n\t"
+ "subqw #1,%4\n"
+ "99:\t"
+ "clrl %3@+\n\t"
+ "dbra %4,99b\n\t"
+ "1:\t"
+ "andw #3,%1\n\t"
+ "jeq 9f\n"
+ "100:\t"
+ "clrw %3@+\n\t"
+ "tstw %1\n\t"
+ "jeq 9f\n"
+ "101:\t"
+ "clrb %3@+\n"
+ "9:\t"
+#define STR(X) STR1(X)
+#define STR1(X) #X
+ "moveq #-" STR(EFAULT) ",%5\n\t"
+ "jra 8b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ ".long 10b,90b\n"
+ ".long 11b,91b\n"
+ ".long 12b,92b\n"
+ ".long 13b,93b\n"
+ ".long 14b,94b\n"
+ ".long 15b,95b\n"
+ ".long 16b,96b\n"
+ ".long 17b,97b\n"
+ ".long 18b,98b\n"
+ ".long 19b,99b\n"
+ ".long 20b,100b\n"
+ ".long 21b,101b\n"
+ ".previous"
+ : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
+ "=&d" (tmp1), "=d" (tmp2)
+ : "0" (sum), "1" (len), "2" (src), "3" (dst)
+ );
+
+ *csum_err = tmp2;
+
+ return(sum);
+}
+
+/*
+ * copy from kernel space while checksumming, otherwise like csum_partial
+ */
+
+unsigned int
+csum_partial_copy(const char *src, char *dst, int len, int sum)
+{
+ unsigned long tmp1, tmp2;
+ __asm__("movel %2,%4\n\t"
+ "btst #1,%4\n\t" /* Check alignment */
+ "jeq 2f\n\t"
+ "subql #2,%1\n\t" /* buff%4==2: treat first word */
+ "jgt 1f\n\t"
+ "addql #2,%1\n\t" /* len was == 2, treat only rest */
+ "jra 4f\n"
+ "1:\t"
+ "movew %2@+,%4\n\t" /* add first word to sum */
+ "addw %4,%0\n\t"
+ "movew %4,%3@+\n\t"
+ "clrl %4\n\t"
+ "addxl %4,%0\n" /* add X bit */
+ "2:\t"
+ /* unrolled loop for the main part: do 8 longs at once */
+ "movel %1,%4\n\t" /* save len in tmp1 */
+ "lsrl #5,%1\n\t" /* len/32 */
+ "jeq 2f\n\t" /* not enough... */
+ "subql #1,%1\n"
+ "1:\t"
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "dbra %1,1b\n\t"
+ "clrl %5\n\t"
+ "addxl %5,%0\n\t" /* add X bit */
+ "clrw %1\n\t"
+ "subql #1,%1\n\t"
+ "jcc 1b\n"
+ "2:\t"
+ "movel %4,%1\n\t" /* restore len from tmp1 */
+ "andw #0x1c,%4\n\t" /* number of rest longs */
+ "jeq 4f\n\t"
+ "lsrw #2,%4\n\t"
+ "subqw #1,%4\n"
+ "3:\t"
+ /* loop for rest longs */
+ "movel %2@+,%5\n\t"
+ "addxl %5,%0\n\t"
+ "movel %5,%3@+\n\t"
+ "dbra %4,3b\n\t"
+ "clrl %5\n\t"
+ "addxl %5,%0\n" /* add X bit */
+ "4:\t"
+ /* now check for rest bytes that do not fit into longs */
+ "andw #3,%1\n\t"
+ "jeq 7f\n\t"
+ "clrl %5\n\t" /* clear tmp2 for rest bytes */
+ "subqw #2,%1\n\t"
+ "jlt 5f\n\t"
+ "movew %2@+,%5\n\t" /* have rest >= 2: get word */
+ "movew %5,%3@+\n\t"
+ "swap %5\n\t" /* into bits 16..31 */
+ "tstw %1\n\t" /* another byte? */
+ "jeq 6f\n"
+ "5:\t"
+ "moveb %2@,%5\n\t" /* have odd rest: get byte */
+ "moveb %5,%3@+\n\t"
+ "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */
+ "6:\t"
+ "addl %5,%0\n\t" /* now add rest long to sum */
+ "clrl %5\n\t"
+ "addxl %5,%0\n" /* add X bit */
+ "7:\t"
+ : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
+ "=&d" (tmp1), "=&d" (tmp2)
+ : "0" (sum), "1" (len), "2" (src), "3" (dst)
+ );
+ return(sum);
+}
diff --git a/pfinet/linux-src/arch/ppc/lib/checksum.S b/pfinet/linux-src/arch/ppc/lib/checksum.S
new file mode 100644
index 00000000..66a2e3aa
--- /dev/null
+++ b/pfinet/linux-src/arch/ppc/lib/checksum.S
@@ -0,0 +1,194 @@
+/*
+ * This file contains assembly-language implementations
+ * of IP-style 1's complement checksum routines.
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Severely hacked about by Paul Mackerras (paulus@cs.anu.edu.au).
+ */
+
+#include <linux/sys.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include "../kernel/ppc_asm.tmpl"
+
+ .text
+
+/*
+ * ip_fast_csum(buf, len) -- Optimized for IP header
+ * len is in words and is always >= 5.
+ */
+_GLOBAL(ip_fast_csum)
+ lwz r0,0(r3)
+ lwzu r5,4(r3)
+ addi r4,r4,-2
+ addc r0,r0,r5
+ mtctr r4
+1: lwzu r4,4(r3)
+ adde r0,r0,r4
+ bdnz 1b
+ addze r0,r0 /* add in final carry */
+ rlwinm r3,r0,16,0,31 /* fold two halves together */
+ add r3,r0,r3
+ not r3,r3
+ srwi r3,r3,16
+ blr
+
+/*
+ * Compute checksum of TCP or UDP pseudo-header:
+ * csum_tcpudp_magic(saddr, daddr, len, proto, sum)
+ */
+_GLOBAL(csum_tcpudp_magic)
+ rlwimi r5,r6,16,0,15 /* put proto in upper half of len */
+ addc r0,r3,r4 /* add 4 32-bit words together */
+ adde r0,r0,r5
+ adde r0,r0,r7
+ addze r0,r0 /* add in final carry */
+ rlwinm r3,r0,16,0,31 /* fold two halves together */
+ add r3,r0,r3
+ not r3,r3
+ srwi r3,r3,16
+ blr
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * csum_partial(buff, len, sum)
+ */
+_GLOBAL(csum_partial)
+ addic r0,r5,0
+ subi r3,r3,4
+ srwi. r6,r4,2
+ beq 3f /* if we're doing < 4 bytes */
+ andi. r5,r3,2 /* Align buffer to longword boundary */
+ beq+ 1f
+ lhz r5,4(r3) /* do 2 bytes to get aligned */
+ addi r3,r3,2
+ subi r4,r4,2
+ addc r0,r0,r5
+ srwi. r6,r4,2 /* # words to do */
+ beq 3f
+1: mtctr r6
+2: lwzu r5,4(r3) /* the bdnz has zero overhead, so it should */
+ adde r0,r0,r5 /* be unnecessary to unroll this loop */
+ bdnz 2b
+ andi. r4,r4,3
+3: cmpi 0,r4,2
+ blt+ 4f
+ lhz r5,4(r3)
+ addi r3,r3,2
+ subi r4,r4,2
+ adde r0,r0,r5
+4: cmpi 0,r4,1
+ bne+ 5f
+ lbz r5,4(r3)
+ slwi r5,r5,8 /* Upper byte of word */
+ adde r0,r0,r5
+5: addze r3,r0 /* add in final carry */
+ blr
+
+/*
+ * Computes the checksum of a memory block at src, length len,
+ * and adds in "sum" (32-bit), while copying the block to dst.
+ * If an access exception occurs on src or dst, it stores -EFAULT
+ * to *src_err or *dst_err respectively, and (for an error on
+ * src) zeroes the rest of dst.
+ *
+ * csum_partial_copy_generic(src, dst, len, sum, src_err, dst_err)
+ */
+_GLOBAL(csum_partial_copy_generic)
+ addic r0,r6,0
+ subi r3,r3,4
+ subi r4,r4,4
+ srwi. r6,r5,2
+ beq 3f /* if we're doing < 4 bytes */
+ andi. r9,r4,2 /* Align dst to longword boundary */
+ beq+ 1f
+81: lhz r6,4(r3) /* do 2 bytes to get aligned */
+ addi r3,r3,2
+ subi r5,r5,2
+91: sth r6,4(r4)
+ addi r4,r4,2
+ addc r0,r0,r6
+ srwi. r6,r5,2 /* # words to do */
+ beq 3f
+1: mtctr r6
+82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */
+92: stwu r6,4(r4) /* be unnecessary to unroll this loop */
+ adde r0,r0,r6
+ bdnz 82b
+ andi. r5,r5,3
+3: cmpi 0,r5,2
+ blt+ 4f
+83: lhz r6,4(r3)
+ addi r3,r3,2
+ subi r5,r5,2
+93: sth r6,4(r4)
+ addi r4,r4,2
+ adde r0,r0,r6
+4: cmpi 0,r5,1
+ bne+ 5f
+84: lbz r6,4(r3)
+94: stb r6,4(r4)
+ slwi r6,r6,8 /* Upper byte of word */
+ adde r0,r0,r6
+5: addze r3,r0 /* add in final carry */
+ blr
+
+/* These shouldn't go in the fixup section, since that would
+ cause the ex_table addresses to get out of order. */
+
+src_error_1:
+ li r6,0
+ subi r5,r5,2
+95: sth r6,4(r4)
+ addi r4,r4,2
+ srwi. r6,r5,2
+ beq 3f
+ mtctr r6
+src_error_2:
+ li r6,0
+96: stwu r6,4(r4)
+ bdnz 96b
+3: andi. r5,r5,3
+ beq src_error
+src_error_3:
+ li r6,0
+ mtctr r5
+ addi r4,r4,3
+97: stbu r6,1(r4)
+ bdnz 97b
+src_error:
+ cmpi 0,r7,0
+ beq 1f
+ li r6,-EFAULT
+ stw r6,0(r7)
+1: addze r3,r0
+ blr
+
+dst_error:
+ cmpi 0,r8,0
+ beq 1f
+ li r6,-EFAULT
+ stw r6,0(r8)
+1: addze r3,r0
+ blr
+
+.section __ex_table,"a"
+ .long 81b,src_error_1
+ .long 91b,dst_error
+ .long 82b,src_error_2
+ .long 92b,dst_error
+ .long 83b,src_error_3
+ .long 93b,dst_error
+ .long 84b,src_error_3
+ .long 94b,dst_error
+ .long 95b,dst_error
+ .long 96b,dst_error
+ .long 97b,dst_error
diff --git a/pfinet/linux-src/arch/sparc/lib/checksum.S b/pfinet/linux-src/arch/sparc/lib/checksum.S
new file mode 100644
index 00000000..d02b6dfb
--- /dev/null
+++ b/pfinet/linux-src/arch/sparc/lib/checksum.S
@@ -0,0 +1,581 @@
+/* checksum.S: Sparc optimized checksum code.
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ * Linux/Alpha checksum c-code
+ * Linux/ix86 inline checksum assembly
+ * RFC1071 Computing the Internet Checksum (esp. Jacobsons m68k code)
+ * David Mosberger-Tang for optimized reference c-code
+ * BSD4.4 portable checksum routine
+ */
+
+#include <asm/cprefix.h>
+#include <asm/errno.h>
+
+#define CSUM_BIGCHUNK(buf, offset, sum, t0, t1, t2, t3, t4, t5) \
+ ldd [buf + offset + 0x00], t0; \
+ ldd [buf + offset + 0x08], t2; \
+ addxcc t0, sum, sum; \
+ addxcc t1, sum, sum; \
+ ldd [buf + offset + 0x10], t4; \
+ addxcc t2, sum, sum; \
+ addxcc t3, sum, sum; \
+ ldd [buf + offset + 0x18], t0; \
+ addxcc t4, sum, sum; \
+ addxcc t5, sum, sum; \
+ addxcc t0, sum, sum; \
+ addxcc t1, sum, sum;
+
+#define CSUM_LASTCHUNK(buf, offset, sum, t0, t1, t2, t3) \
+ ldd [buf - offset - 0x08], t0; \
+ ldd [buf - offset - 0x00], t2; \
+ addxcc t0, sum, sum; \
+ addxcc t1, sum, sum; \
+ addxcc t2, sum, sum; \
+ addxcc t3, sum, sum;
+
+ /* Do end cruft out of band to get better cache patterns. */
+csum_partial_end_cruft:
+ be 1f ! caller asks %o1 & 0x8
+ andcc %o1, 4, %g0 ! nope, check for word remaining
+ ldd [%o0], %g2 ! load two
+ addcc %g2, %o2, %o2 ! add first word to sum
+ addxcc %g3, %o2, %o2 ! add second word as well
+ add %o0, 8, %o0 ! advance buf ptr
+ addx %g0, %o2, %o2 ! add in final carry
+ andcc %o1, 4, %g0 ! check again for word remaining
+1: be 1f ! nope, skip this code
+ andcc %o1, 3, %o1 ! check for trailing bytes
+ ld [%o0], %g2 ! load it
+ addcc %g2, %o2, %o2 ! add to sum
+ add %o0, 4, %o0 ! advance buf ptr
+ addx %g0, %o2, %o2 ! add in final carry
+ andcc %o1, 3, %g0 ! check again for trailing bytes
+1: be 1f ! no trailing bytes, return
+ addcc %o1, -1, %g0 ! only one byte remains?
+ bne 2f ! at least two bytes more
+ subcc %o1, 2, %o1 ! only two bytes more?
+ b 4f ! only one byte remains
+ or %g0, %g0, %o4 ! clear fake hword value
+2: lduh [%o0], %o4 ! get hword
+ be 6f ! jmp if only hword remains
+ add %o0, 2, %o0 ! advance buf ptr either way
+ sll %o4, 16, %o4 ! create upper hword
+4: ldub [%o0], %o5 ! get final byte
+ sll %o5, 8, %o5 ! put into place
+ or %o5, %o4, %o4 ! coalese with hword (if any)
+6: addcc %o4, %o2, %o2 ! add to sum
+1: retl ! get outta here
+ addx %g0, %o2, %o0 ! add final carry into retval
+
+ /* Also do alignment out of band to get better cache patterns. */
+csum_partial_fix_alignment:
+ cmp %o1, 6
+ bl cpte - 0x4
+ andcc %o0, 0x2, %g0
+ be 1f
+ andcc %o0, 0x4, %g0
+ lduh [%o0 + 0x00], %g2
+ sub %o1, 2, %o1
+ add %o0, 2, %o0
+ sll %g2, 16, %g2
+ addcc %g2, %o2, %o2
+ srl %o2, 16, %g3
+ addx %g0, %g3, %g2
+ sll %o2, 16, %o2
+ sll %g2, 16, %g3
+ srl %o2, 16, %o2
+ andcc %o0, 0x4, %g0
+ or %g3, %o2, %o2
+1: be cpa
+ andcc %o1, 0xffffff80, %o3
+ ld [%o0 + 0x00], %g2
+ sub %o1, 4, %o1
+ addcc %g2, %o2, %o2
+ add %o0, 4, %o0
+ addx %g0, %o2, %o2
+ b cpa
+ andcc %o1, 0xffffff80, %o3
+
+ /* The common case is to get called with a nicely aligned
+ * buffer of size 0x20. Follow the code path for that case.
+ */
+ .globl C_LABEL(csum_partial)
+C_LABEL(csum_partial): /* %o0=buf, %o1=len, %o2=sum */
+ andcc %o0, 0x7, %g0 ! alignment problems?
+ bne csum_partial_fix_alignment ! yep, handle it
+ sethi %hi(cpte - 8), %g7 ! prepare table jmp ptr
+ andcc %o1, 0xffffff80, %o3 ! num loop iterations
+cpa: be 3f ! none to do
+ andcc %o1, 0x70, %g1 ! clears carry flag too
+5: CSUM_BIGCHUNK(%o0, 0x00, %o2, %o4, %o5, %g2, %g3, %g4, %g5)
+ CSUM_BIGCHUNK(%o0, 0x20, %o2, %o4, %o5, %g2, %g3, %g4, %g5)
+ CSUM_BIGCHUNK(%o0, 0x40, %o2, %o4, %o5, %g2, %g3, %g4, %g5)
+ CSUM_BIGCHUNK(%o0, 0x60, %o2, %o4, %o5, %g2, %g3, %g4, %g5)
+ addx %g0, %o2, %o2 ! sink in final carry
+ subcc %o3, 128, %o3 ! detract from loop iters
+ bne 5b ! more to do
+ add %o0, 128, %o0 ! advance buf ptr
+ andcc %o1, 0x70, %g1 ! clears carry flag too
+3: be cpte ! nope
+ andcc %o1, 0xf, %g0 ! anything left at all?
+ srl %g1, 1, %o4 ! compute offset
+ sub %g7, %g1, %g7 ! adjust jmp ptr
+ sub %g7, %o4, %g7 ! final jmp ptr adjust
+ jmp %g7 + %lo(cpte - 8) ! enter the table
+ add %o0, %g1, %o0 ! advance buf ptr
+cptbl: CSUM_LASTCHUNK(%o0, 0x68, %o2, %g2, %g3, %g4, %g5)
+ CSUM_LASTCHUNK(%o0, 0x58, %o2, %g2, %g3, %g4, %g5)
+ CSUM_LASTCHUNK(%o0, 0x48, %o2, %g2, %g3, %g4, %g5)
+ CSUM_LASTCHUNK(%o0, 0x38, %o2, %g2, %g3, %g4, %g5)
+ CSUM_LASTCHUNK(%o0, 0x28, %o2, %g2, %g3, %g4, %g5)
+ CSUM_LASTCHUNK(%o0, 0x18, %o2, %g2, %g3, %g4, %g5)
+ CSUM_LASTCHUNK(%o0, 0x08, %o2, %g2, %g3, %g4, %g5)
+ addx %g0, %o2, %o2 ! fetch final carry
+ andcc %o1, 0xf, %g0 ! anything left at all?
+cpte: bne csum_partial_end_cruft ! yep, handle it
+ andcc %o1, 8, %g0 ! check how much
+cpout: retl ! get outta here
+ mov %o2, %o0 ! return computed csum
+
+ .globl C_LABEL(__csum_partial_copy_start), C_LABEL(__csum_partial_copy_end)
+C_LABEL(__csum_partial_copy_start):
+
+#define EX(x,y,a,b,z) \
+98: x,y; \
+ .section .fixup,z##alloc,z##execinstr; \
+ .align 4; \
+99: ba 30f; \
+ a, b, %o3; \
+ .section __ex_table,z##alloc; \
+ .align 4; \
+ .word 98b, 99b; \
+ .text; \
+ .align 4
+
+#define EX2(x,y,z) \
+98: x,y; \
+ .section __ex_table,z##alloc; \
+ .align 4; \
+ .word 98b, 30f; \
+ .text; \
+ .align 4
+
+#define EX3(x,y,z) \
+98: x,y; \
+ .section __ex_table,z##alloc; \
+ .align 4; \
+ .word 98b, 96f; \
+ .text; \
+ .align 4
+
+#define EXT(start,end,handler,z) \
+ .section __ex_table,z##alloc; \
+ .align 4; \
+ .word start, 0, end, handler; \
+ .text; \
+ .align 4
+
+ /* This aligned version executes typically in 8.5 superscalar cycles, this
+ * is the best I can do. I say 8.5 because the final add will pair with
+ * the next ldd in the main unrolled loop. Thus the pipe is always full.
+ * If you change these macros (including order of instructions),
+ * please check the fixup code below as well.
+ */
+#define CSUMCOPY_BIGCHUNK_ALIGNED(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7) \
+ ldd [src + off + 0x00], t0; \
+ ldd [src + off + 0x08], t2; \
+ addxcc t0, sum, sum; \
+ ldd [src + off + 0x10], t4; \
+ addxcc t1, sum, sum; \
+ ldd [src + off + 0x18], t6; \
+ addxcc t2, sum, sum; \
+ std t0, [dst + off + 0x00]; \
+ addxcc t3, sum, sum; \
+ std t2, [dst + off + 0x08]; \
+ addxcc t4, sum, sum; \
+ std t4, [dst + off + 0x10]; \
+ addxcc t5, sum, sum; \
+ std t6, [dst + off + 0x18]; \
+ addxcc t6, sum, sum; \
+ addxcc t7, sum, sum;
+
+ /* 12 superscalar cycles seems to be the limit for this case,
+ * because of this we thus do all the ldd's together to get
+ * Viking MXCC into streaming mode. Ho hum...
+ */
+#define CSUMCOPY_BIGCHUNK(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7) \
+ ldd [src + off + 0x00], t0; \
+ ldd [src + off + 0x08], t2; \
+ ldd [src + off + 0x10], t4; \
+ ldd [src + off + 0x18], t6; \
+ st t0, [dst + off + 0x00]; \
+ addxcc t0, sum, sum; \
+ st t1, [dst + off + 0x04]; \
+ addxcc t1, sum, sum; \
+ st t2, [dst + off + 0x08]; \
+ addxcc t2, sum, sum; \
+ st t3, [dst + off + 0x0c]; \
+ addxcc t3, sum, sum; \
+ st t4, [dst + off + 0x10]; \
+ addxcc t4, sum, sum; \
+ st t5, [dst + off + 0x14]; \
+ addxcc t5, sum, sum; \
+ st t6, [dst + off + 0x18]; \
+ addxcc t6, sum, sum; \
+ st t7, [dst + off + 0x1c]; \
+ addxcc t7, sum, sum;
+
+ /* Yuck, 6 superscalar cycles... */
+#define CSUMCOPY_LASTCHUNK(src, dst, sum, off, t0, t1, t2, t3) \
+ ldd [src - off - 0x08], t0; \
+ ldd [src - off - 0x00], t2; \
+ addxcc t0, sum, sum; \
+ st t0, [dst - off - 0x08]; \
+ addxcc t1, sum, sum; \
+ st t1, [dst - off - 0x04]; \
+ addxcc t2, sum, sum; \
+ st t2, [dst - off - 0x00]; \
+ addxcc t3, sum, sum; \
+ st t3, [dst - off + 0x04];
+
+ /* Handle the end cruft code out of band for better cache patterns. */
+cc_end_cruft:
+ be 1f
+ andcc %o3, 4, %g0
+ EX(ldd [%o0 + 0x00], %g2, and %o3, 0xf,#)
+ add %o1, 8, %o1
+ addcc %g2, %g7, %g7
+ add %o0, 8, %o0
+ addxcc %g3, %g7, %g7
+ EX2(st %g2, [%o1 - 0x08],#)
+ addx %g0, %g7, %g7
+ andcc %o3, 4, %g0
+ EX2(st %g3, [%o1 - 0x04],#)
+1: be 1f
+ andcc %o3, 3, %o3
+ EX(ld [%o0 + 0x00], %g2, add %o3, 4,#)
+ add %o1, 4, %o1
+ addcc %g2, %g7, %g7
+ EX2(st %g2, [%o1 - 0x04],#)
+ addx %g0, %g7, %g7
+ andcc %o3, 3, %g0
+ add %o0, 4, %o0
+1: be 1f
+ addcc %o3, -1, %g0
+ bne 2f
+ subcc %o3, 2, %o3
+ b 4f
+ or %g0, %g0, %o4
+2: EX(lduh [%o0 + 0x00], %o4, add %o3, 2,#)
+ add %o0, 2, %o0
+ EX2(sth %o4, [%o1 + 0x00],#)
+ be 6f
+ add %o1, 2, %o1
+ sll %o4, 16, %o4
+4: EX(ldub [%o0 + 0x00], %o5, add %g0, 1,#)
+ EX2(stb %o5, [%o1 + 0x00],#)
+ sll %o5, 8, %o5
+ or %o5, %o4, %o4
+6: addcc %o4, %g7, %g7
+1: retl
+ addx %g0, %g7, %o0
+
+ /* Also, handle the alignment code out of band. */
+cc_dword_align:
+ cmp %g1, 6
+ bl,a ccte
+ andcc %g1, 0xf, %o3
+ andcc %o0, 0x1, %g0
+ bne ccslow
+ andcc %o0, 0x2, %g0
+ be 1f
+ andcc %o0, 0x4, %g0
+ EX(lduh [%o0 + 0x00], %g4, add %g1, 0,#)
+ sub %g1, 2, %g1
+ EX2(sth %g4, [%o1 + 0x00],#)
+ add %o0, 2, %o0
+ sll %g4, 16, %g4
+ addcc %g4, %g7, %g7
+ add %o1, 2, %o1
+ srl %g7, 16, %g3
+ addx %g0, %g3, %g4
+ sll %g7, 16, %g7
+ sll %g4, 16, %g3
+ srl %g7, 16, %g7
+ andcc %o0, 0x4, %g0
+ or %g3, %g7, %g7
+1: be 3f
+ andcc %g1, 0xffffff80, %g0
+ EX(ld [%o0 + 0x00], %g4, add %g1, 0,#)
+ sub %g1, 4, %g1
+ EX2(st %g4, [%o1 + 0x00],#)
+ add %o0, 4, %o0
+ addcc %g4, %g7, %g7
+ add %o1, 4, %o1
+ addx %g0, %g7, %g7
+ b 3f
+ andcc %g1, 0xffffff80, %g0
+
+ /* Sun, you just can't beat me, you just can't. Stop trying,
+ * give up. I'm serious, I am going to kick the living shit
+ * out of you, game over, lights out.
+ */
+ .align 8
+ .globl C_LABEL(__csum_partial_copy_sparc_generic)
+C_LABEL(__csum_partial_copy_sparc_generic):
+ /* %o0=src, %o1=dest, %g1=len, %g7=sum */
+ xor %o0, %o1, %o4 ! get changing bits
+ andcc %o4, 3, %g0 ! check for mismatched alignment
+ bne ccslow ! better this than unaligned/fixups
+ andcc %o0, 7, %g0 ! need to align things?
+ bne cc_dword_align ! yes, we check for short lengths there
+ andcc %g1, 0xffffff80, %g0 ! can we use unrolled loop?
+3: be 3f ! nope, less than one loop remains
+ andcc %o1, 4, %g0 ! dest aligned on 4 or 8 byte boundry?
+ be ccdbl + 4 ! 8 byte aligned, kick ass
+5: CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x00,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+ CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+ CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+ CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x60,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+10: EXT(5b, 10b, 20f,#) ! note for exception handling
+ sub %g1, 128, %g1 ! detract from length
+ addx %g0, %g7, %g7 ! add in last carry bit
+ andcc %g1, 0xffffff80, %g0 ! more to csum?
+ add %o0, 128, %o0 ! advance src ptr
+ bne 5b ! we did not go negative, continue looping
+ add %o1, 128, %o1 ! advance dest ptr
+3: andcc %g1, 0x70, %o2 ! can use table?
+ccmerge:be ccte ! nope, go and check for end cruft
+ andcc %g1, 0xf, %o3 ! get low bits of length (clears carry btw)
+ srl %o2, 1, %o4 ! begin negative offset computation
+ sethi %hi(12f), %o5 ! set up table ptr end
+ add %o0, %o2, %o0 ! advance src ptr
+ sub %o5, %o4, %o5 ! continue table calculation
+ sll %o2, 1, %g2 ! constant multiplies are fun...
+ sub %o5, %g2, %o5 ! some more adjustments
+ jmp %o5 + %lo(12f) ! jump into it, duff style, wheee...
+ add %o1, %o2, %o1 ! advance dest ptr (carry is clear btw)
+cctbl: CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x68,%g2,%g3,%g4,%g5)
+ CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x58,%g2,%g3,%g4,%g5)
+ CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x48,%g2,%g3,%g4,%g5)
+ CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x38,%g2,%g3,%g4,%g5)
+ CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x28,%g2,%g3,%g4,%g5)
+ CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x18,%g2,%g3,%g4,%g5)
+ CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x08,%g2,%g3,%g4,%g5)
+12: EXT(cctbl, 12b, 22f,#) ! note for exception table handling
+ addx %g0, %g7, %g7
+ andcc %o3, 0xf, %g0 ! check for low bits set
+ccte: bne cc_end_cruft ! something left, handle it out of band
+ andcc %o3, 8, %g0 ! begin checks for that code
+ retl ! return
+ mov %g7, %o0 ! give em the computed checksum
+ccdbl: CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x00,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+ CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+ CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+ CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x60,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
+11: EXT(ccdbl, 11b, 21f,#) ! note for exception table handling
+ sub %g1, 128, %g1 ! detract from length
+ addx %g0, %g7, %g7 ! add in last carry bit
+ andcc %g1, 0xffffff80, %g0 ! more to csum?
+ add %o0, 128, %o0 ! advance src ptr
+ bne ccdbl ! we did not go negative, continue looping
+ add %o1, 128, %o1 ! advance dest ptr
+ b ccmerge ! finish it off, above
+ andcc %g1, 0x70, %o2 ! can use table? (clears carry btw)
+
+ccslow: cmp %g1, 0
+ mov 0, %g5
+ bleu 4f
+ andcc %o0, 1, %o5
+ be,a 1f
+ srl %g1, 1, %g4
+ sub %g1, 1, %g1
+ EX(ldub [%o0], %g5, add %g1, 1,#)
+ add %o0, 1, %o0
+ EX2(stb %g5, [%o1],#)
+ srl %g1, 1, %g4
+ add %o1, 1, %o1
+1: cmp %g4, 0
+ be,a 3f
+ andcc %g1, 1, %g0
+ andcc %o0, 2, %g0
+ be,a 1f
+ srl %g4, 1, %g4
+ EX(lduh [%o0], %o4, add %g1, 0,#)
+ sub %g1, 2, %g1
+ srl %o4, 8, %g2
+ sub %g4, 1, %g4
+ EX2(stb %g2, [%o1],#)
+ add %o4, %g5, %g5
+ EX2(stb %o4, [%o1 + 1],#)
+ add %o0, 2, %o0
+ srl %g4, 1, %g4
+ add %o1, 2, %o1
+1: cmp %g4, 0
+ be,a 2f
+ andcc %g1, 2, %g0
+ EX3(ld [%o0], %o4,#)
+5: srl %o4, 24, %g2
+ srl %o4, 16, %g3
+ EX2(stb %g2, [%o1],#)
+ srl %o4, 8, %g2
+ EX2(stb %g3, [%o1 + 1],#)
+ add %o0, 4, %o0
+ EX2(stb %g2, [%o1 + 2],#)
+ addcc %o4, %g5, %g5
+ EX2(stb %o4, [%o1 + 3],#)
+ addx %g5, %g0, %g5 ! I am now to lazy to optimize this (question it
+ add %o1, 4, %o1 ! is worthy). Maybe some day - with the sll/srl
+ subcc %g4, 1, %g4 ! tricks
+ bne,a 5b
+ EX3(ld [%o0], %o4,#)
+ sll %g5, 16, %g2
+ srl %g5, 16, %g5
+ srl %g2, 16, %g2
+ andcc %g1, 2, %g0
+ add %g2, %g5, %g5
+2: be,a 3f
+ andcc %g1, 1, %g0
+ EX(lduh [%o0], %o4, and %g1, 3,#)
+ andcc %g1, 1, %g0
+ srl %o4, 8, %g2
+ add %o0, 2, %o0
+ EX2(stb %g2, [%o1],#)
+ add %g5, %o4, %g5
+ EX2(stb %o4, [%o1 + 1],#)
+ add %o1, 2, %o1
+3: be,a 1f
+ sll %g5, 16, %o4
+ EX(ldub [%o0], %g2, add %g0, 1,#)
+ sll %g2, 8, %o4
+ EX2(stb %g2, [%o1],#)
+ add %g5, %o4, %g5
+ sll %g5, 16, %o4
+1: addcc %o4, %g5, %g5
+ srl %g5, 16, %o4
+ addx %g0, %o4, %g5
+ orcc %o5, %g0, %g0
+ be 4f
+ srl %g5, 8, %o4
+ and %g5, 0xff, %g2
+ and %o4, 0xff, %o4
+ sll %g2, 8, %g2
+ or %g2, %o4, %g5
+4: addcc %g7, %g5, %g7
+ retl
+ addx %g0, %g7, %o0
+C_LABEL(__csum_partial_copy_end):
+
+/* We do these strange calculations for the csum_*_from_user case only, ie.
+ * we only bother with faults on loads... */
+
+/* o2 = ((g2%20)&3)*8
+ * o3 = g1 - (g2/20)*32 - o2 */
+20:
+ cmp %g2, 20
+ blu,a 1f
+ and %g2, 3, %o2
+ sub %g1, 32, %g1
+ b 20b
+ sub %g2, 20, %g2
+1:
+ sll %o2, 3, %o2
+ b 31f
+ sub %g1, %o2, %o3
+
+/* o2 = (!(g2 & 15) ? 0 : (((g2 & 15) + 1) & ~1)*8)
+ * o3 = g1 - (g2/16)*32 - o2 */
+21:
+ andcc %g2, 15, %o3
+ srl %g2, 4, %g2
+ be,a 1f
+ clr %o2
+ add %o3, 1, %o3
+ and %o3, 14, %o3
+ sll %o3, 3, %o2
+1:
+ sll %g2, 5, %g2
+ sub %g1, %g2, %o3
+ b 31f
+ sub %o3, %o2, %o3
+
+/* o0 += (g2/10)*16 - 0x70
+ * 01 += (g2/10)*16 - 0x70
+ * o2 = (g2 % 10) ? 8 : 0
+ * o3 += 0x70 - (g2/10)*16 - o2 */
+22:
+ cmp %g2, 10
+ blu,a 1f
+ sub %o0, 0x70, %o0
+ add %o0, 16, %o0
+ add %o1, 16, %o1
+ sub %o3, 16, %o3
+ b 22b
+ sub %g2, 10, %g2
+1:
+ sub %o1, 0x70, %o1
+ add %o3, 0x70, %o3
+ clr %o2
+ tst %g2
+ bne,a 1f
+ mov 8, %o2
+1:
+ b 31f
+ sub %o3, %o2, %o3
+96:
+ and %g1, 3, %g1
+ sll %g4, 2, %g4
+ add %g1, %g4, %o3
+30:
+/* %o1 is dst
+ * %o3 is # bytes to zero out
+ * %o4 is faulting address
+ * %o5 is %pc where fault occurred */
+ clr %o2
+31:
+/* %o0 is src
+ * %o1 is dst
+ * %o2 is # of bytes to copy from src to dst
+ * %o3 is # bytes to zero out
+ * %o4 is faulting address
+ * %o5 is %pc where fault occurred */
+ save %sp, -104, %sp
+ mov %i5, %o0
+ mov %i7, %o1
+ mov %i4, %o2
+ call C_LABEL(lookup_fault)
+ mov %g7, %i4
+ cmp %o0, 2
+ bne 1f
+ add %g0, -EFAULT, %i5
+ tst %i2
+ be 2f
+ mov %i0, %o1
+ mov %i1, %o0
+5:
+ call C_LABEL(__memcpy)
+ mov %i2, %o2
+ tst %o0
+ bne,a 2f
+ add %i3, %i2, %i3
+ add %i1, %i2, %i1
+2:
+ mov %i1, %o0
+6:
+ call C_LABEL(__bzero)
+ mov %i3, %o1
+1:
+ ld [%sp + 168], %o2 ! struct_ptr of parent
+ st %i5, [%o2]
+ ret
+ restore
+
+ .section __ex_table,#alloc
+ .align 4
+ .word 5b,2
+ .word 6b,2
diff --git a/pfinet/linux-src/arch/sparc64/lib/checksum.S b/pfinet/linux-src/arch/sparc64/lib/checksum.S
new file mode 100644
index 00000000..ea732b36
--- /dev/null
+++ b/pfinet/linux-src/arch/sparc64/lib/checksum.S
@@ -0,0 +1,278 @@
+/* checksum.S: Sparc V9 optimized checksum code.
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ * Linux/Alpha checksum c-code
+ * Linux/ix86 inline checksum assembly
+ * RFC1071 Computing the Internet Checksum (esp. Jacobsons m68k code)
+ * David Mosberger-Tang for optimized reference c-code
+ * BSD4.4 portable checksum routine
+ */
+
+#include <asm/errno.h>
+#include <asm/head.h>
+#include <asm/ptrace.h>
+#include <asm/asi.h>
+#include <asm/page.h>
+
+ /* The problem with the "add with carry" instructions on Ultra
+ * are two fold. Firstly, they cannot pair with jack shit,
+ * and also they only add in the 32-bit carry condition bit
+ * into the accumulated sum. The following is much better.
+ * For larger chunks we use VIS code, which is faster ;)
+ */
+
+#define src o0
+#define dst o1
+#define len o2
+#define sum o3
+
+ .text
+ /* I think I have an erection... Once _AGAIN_ the SunSoft
+ * engineers are caught asleep at the keyboard, tsk tsk...
+ */
+
+#define CSUMCOPY_LASTCHUNK(off, t0, t1) \
+ ldxa [%src - off - 0x08] %asi, t0; \
+ ldxa [%src - off - 0x00] %asi, t1; \
+ nop; nop; \
+ addcc t0, %sum, %sum; \
+ stw t0, [%dst - off - 0x04]; \
+ srlx t0, 32, t0; \
+ bcc,pt %xcc, 51f; \
+ stw t0, [%dst - off - 0x08]; \
+ add %sum, 1, %sum; \
+51: addcc t1, %sum, %sum; \
+ stw t1, [%dst - off + 0x04]; \
+ srlx t1, 32, t1; \
+ bcc,pt %xcc, 52f; \
+ stw t1, [%dst - off - 0x00]; \
+ add %sum, 1, %sum; \
+52:
+
+cpc_start:
+cc_end_cruft:
+ andcc %g7, 8, %g0 ! IEU1 Group
+ be,pn %icc, 1f ! CTI
+ and %g7, 4, %g5 ! IEU0
+ ldxa [%src + 0x00] %asi, %g2 ! Load Group
+ add %dst, 8, %dst ! IEU0
+ add %src, 8, %src ! IEU1
+ addcc %g2, %sum, %sum ! IEU1 Group + 2 bubbles
+ stw %g2, [%dst - 0x04] ! Store
+ srlx %g2, 32, %g2 ! IEU0
+ bcc,pt %xcc, 1f ! CTI Group
+ stw %g2, [%dst - 0x08] ! Store
+ add %sum, 1, %sum ! IEU0
+1: brz,pt %g5, 1f ! CTI Group
+ clr %g2 ! IEU0
+ lduwa [%src + 0x00] %asi, %g2 ! Load
+ add %dst, 4, %dst ! IEU0 Group
+ add %src, 4, %src ! IEU1
+ stw %g2, [%dst - 0x04] ! Store Group + 2 bubbles
+ sllx %g2, 32, %g2 ! IEU0
+1: andcc %g7, 2, %g0 ! IEU1
+ be,pn %icc, 1f ! CTI Group
+ clr %o4 ! IEU1
+ lduha [%src + 0x00] %asi, %o4 ! Load
+ add %src, 2, %src ! IEU0 Group
+ add %dst, 2, %dst ! IEU1
+ sth %o4, [%dst - 0x2] ! Store Group + 2 bubbles
+ sll %o4, 16, %o4 ! IEU0
+1: andcc %g7, 1, %g0 ! IEU1
+ be,pn %icc, 1f ! CTI Group
+ clr %o5 ! IEU0
+ lduba [%src + 0x00] %asi, %o5 ! Load
+ stb %o5, [%dst + 0x00] ! Store Group + 2 bubbles
+ sll %o5, 8, %o5 ! IEU0
+1: or %g2, %o4, %o4 ! IEU1
+ or %o5, %o4, %o4 ! IEU0 Group
+ addcc %o4, %sum, %sum ! IEU1
+ bcc,pt %xcc, ccfold ! CTI
+ sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 Group
+ b,pt %xcc, ccfold ! CTI
+ add %sum, 1, %sum ! IEU1
+
+cc_fixit:
+ cmp %len, 6 ! IEU1 Group
+ bl,a,pn %icc, ccte ! CTI
+ andcc %len, 0xf, %g7 ! IEU1 Group
+ andcc %src, 2, %g0 ! IEU1 Group
+ be,pn %icc, 1f ! CTI
+ andcc %src, 0x4, %g0 ! IEU1 Group
+ lduha [%src + 0x00] %asi, %g4 ! Load
+ sub %len, 2, %len ! IEU0
+ add %src, 2, %src ! IEU0 Group
+ add %dst, 2, %dst ! IEU1
+ sll %g4, 16, %g3 ! IEU0 Group + 1 bubble
+ addcc %g3, %sum, %sum ! IEU1
+ bcc,pt %xcc, 0f ! CTI
+ srl %sum, 16, %g3 ! IEU0 Group
+ add %g3, 1, %g3 ! IEU0 4 clocks (mispredict)
+0: andcc %src, 0x4, %g0 ! IEU1 Group
+ sth %g4, [%dst - 0x2] ! Store
+ sll %sum, 16, %sum ! IEU0
+ sll %g3, 16, %g3 ! IEU0 Group
+ srl %sum, 16, %sum ! IEU0 Group
+ or %g3, %sum, %sum ! IEU0 Group (regdep)
+1: be,pt %icc, ccmerge ! CTI
+ andcc %len, 0xf0, %g1 ! IEU1
+ lduwa [%src + 0x00] %asi, %g4 ! Load Group
+ sub %len, 4, %len ! IEU0
+ add %src, 4, %src ! IEU1
+ add %dst, 4, %dst ! IEU0 Group
+ addcc %g4, %sum, %sum ! IEU1 Group + 1 bubble
+ stw %g4, [%dst - 0x4] ! Store
+ bcc,pt %xcc, ccmerge ! CTI
+ andcc %len, 0xf0, %g1 ! IEU1 Group
+ b,pt %xcc, ccmerge ! CTI 4 clocks (mispredict)
+ add %sum, 1, %sum ! IEU0
+
+ .align 32
+ .globl csum_partial_copy_sparc64
+csum_partial_copy_sparc64: /* %o0=src, %o1=dest, %o2=len, %o3=sum */
+ xorcc %src, %dst, %o4 ! IEU1 Group
+ srl %sum, 0, %sum ! IEU0
+ andcc %o4, 3, %g0 ! IEU1 Group
+ srl %len, 0, %len ! IEU0
+ bne,pn %icc, ccslow ! CTI
+ andcc %src, 1, %g0 ! IEU1 Group
+ bne,pn %icc, ccslow ! CTI
+ cmp %len, 256 ! IEU1 Group
+ bgeu,pt %icc, csum_partial_copy_vis ! CTI
+ andcc %src, 7, %g0 ! IEU1 Group
+ bne,pn %icc, cc_fixit ! CTI
+ andcc %len, 0xf0, %g1 ! IEU1 Group
+ccmerge:be,pn %icc, ccte ! CTI
+ andcc %len, 0xf, %g7 ! IEU1 Group
+ sll %g1, 2, %o4 ! IEU0
+13: sethi %hi(12f), %o5 ! IEU0 Group
+ add %src, %g1, %src ! IEU1
+ sub %o5, %o4, %o5 ! IEU0 Group
+ jmpl %o5 + %lo(12f), %g0 ! CTI Group brk forced
+ add %dst, %g1, %dst ! IEU0 Group
+cctbl: CSUMCOPY_LASTCHUNK(0xe8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0xd8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0xc8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0xb8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0xa8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x98,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x88,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x78,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x68,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x58,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x48,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x38,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x28,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x18,%g2,%g3)
+ CSUMCOPY_LASTCHUNK(0x08,%g2,%g3)
+12:
+ andcc %len, 0xf, %g7 ! IEU1 Group
+ccte: bne,pn %icc, cc_end_cruft ! CTI
+ sethi %uhi(PAGE_OFFSET), %g4 ! IEU0
+ccfold: sllx %sum, 32, %o0 ! IEU0 Group
+ addcc %sum, %o0, %o0 ! IEU1 Group (regdep)
+ srlx %o0, 32, %o0 ! IEU0 Group (regdep)
+ bcs,a,pn %xcc, 1f ! CTI
+ add %o0, 1, %o0 ! IEU1 4 clocks (mispredict)
+1: retl ! CTI Group brk forced
+ sllx %g4, 32, %g4 ! IEU0 Group
+
+ccslow: mov 0, %g5
+ brlez,pn %len, 4f
+ andcc %src, 1, %o5
+ be,a,pt %icc, 1f
+ srl %len, 1, %g7
+ sub %len, 1, %len
+ lduba [%src] %asi, %g5
+ add %src, 1, %src
+ stb %g5, [%dst]
+ srl %len, 1, %g7
+ add %dst, 1, %dst
+1: brz,a,pn %g7, 3f
+ andcc %len, 1, %g0
+ andcc %src, 2, %g0
+ be,a,pt %icc, 1f
+ srl %g7, 1, %g7
+ lduha [%src] %asi, %o4
+ sub %len, 2, %len
+ srl %o4, 8, %g2
+ sub %g7, 1, %g7
+ stb %g2, [%dst]
+ add %o4, %g5, %g5
+ stb %o4, [%dst + 1]
+ add %src, 2, %src
+ srl %g7, 1, %g7
+ add %dst, 2, %dst
+1: brz,a,pn %g7, 2f
+ andcc %len, 2, %g0
+ lduwa [%src] %asi, %o4
+5: srl %o4, 24, %g2
+ srl %o4, 16, %g3
+ stb %g2, [%dst]
+ srl %o4, 8, %g2
+ stb %g3, [%dst + 1]
+ add %src, 4, %src
+ stb %g2, [%dst + 2]
+ addcc %o4, %g5, %g5
+ stb %o4, [%dst + 3]
+ addc %g5, %g0, %g5
+ add %dst, 4, %dst
+ subcc %g7, 1, %g7
+ bne,a,pt %icc, 5b
+ lduwa [%src] %asi, %o4
+ sll %g5, 16, %g2
+ srl %g5, 16, %g5
+ srl %g2, 16, %g2
+ andcc %len, 2, %g0
+ add %g2, %g5, %g5
+2: be,a,pt %icc, 3f
+ andcc %len, 1, %g0
+ lduha [%src] %asi, %o4
+ andcc %len, 1, %g0
+ srl %o4, 8, %g2
+ add %src, 2, %src
+ stb %g2, [%dst]
+ add %g5, %o4, %g5
+ stb %o4, [%dst + 1]
+ add %dst, 2, %dst
+3: be,a,pt %icc, 1f
+ sll %g5, 16, %o4
+ lduba [%src] %asi, %g2
+ sll %g2, 8, %o4
+ stb %g2, [%dst]
+ add %g5, %o4, %g5
+ sll %g5, 16, %o4
+1: addcc %o4, %g5, %g5
+ srl %g5, 16, %o4
+ addc %g0, %o4, %g5
+ brz,pt %o5, 4f
+ srl %g5, 8, %o4
+ and %g5, 0xff, %g2
+ and %o4, 0xff, %o4
+ sll %g2, 8, %g2
+ or %g2, %o4, %g5
+4: addcc %sum, %g5, %sum
+ addc %g0, %sum, %o0
+ retl
+ srl %o0, 0, %o0
+cpc_end:
+
+ .globl cpc_handler
+cpc_handler:
+ ldx [%sp + 0x7ff + 128], %g1
+ sub %g0, EFAULT, %g2
+ brnz,a,pt %g1, 1f
+ st %g2, [%g1]
+1: sethi %uhi(PAGE_OFFSET), %g4
+ retl
+ sllx %g4, 32, %g4
+
+ .section __ex_table
+ .align 4
+ .word cpc_start, 0, cpc_end, cpc_handler
+
diff --git a/pfinet/linux-src/include/asm-alpha/checksum.h b/pfinet/linux-src/include/asm-alpha/checksum.h
new file mode 100644
index 00000000..2f6b82e6
--- /dev/null
+++ b/pfinet/linux-src/include/asm-alpha/checksum.h
@@ -0,0 +1,90 @@
+#ifndef _ALPHA_CHECKSUM_H
+#define _ALPHA_CHECKSUM_H
+
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+extern unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum);
+
+unsigned int csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+ unsigned short len, unsigned short proto,
+ unsigned int sum);
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from user space (but on the alpha
+ * we have just one address space, so this is identical to the above)
+ *
+ * this is obsolete and will go away.
+ */
+#define csum_partial_copy_fromuser csum_partial_copy
+
+/*
+ * this is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
+
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum);
+
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+extern unsigned short ip_compute_csum(unsigned char * buff, int len);
+
+/*
+ * Fold a partial checksum without adding pseudo headers
+ */
+
+static inline unsigned short csum_fold(unsigned int sum)
+{
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = (sum & 0xffff) + (sum >> 16);
+ return ~sum;
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+extern unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u16 len,
+ unsigned short proto,
+ unsigned int sum);
+
+#endif
diff --git a/pfinet/linux-src/include/asm-arm/checksum.h b/pfinet/linux-src/include/asm-arm/checksum.h
new file mode 100644
index 00000000..2323bb5d
--- /dev/null
+++ b/pfinet/linux-src/include/asm-arm/checksum.h
@@ -0,0 +1,162 @@
+/*
+ * linux/include/asm-arm/checksum.h
+ *
+ * IP checksum routines
+ *
+ * Copyright (C) Original authors of ../asm-i386/checksum.h
+ * Copyright (C) 1996,1997,1998 Russell King
+ */
+#ifndef __ASM_ARM_CHECKSUM_H
+#define __ASM_ARM_CHECKSUM_H
+
+#ifndef __ASM_ARM_SEGMENT_H
+#include <asm/segment.h>
+#endif
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+unsigned int
+csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum);
+
+unsigned int
+csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr);
+
+#if 0
+/*
+ * This combination is currently not used, but possible:
+ */
+unsigned int
+csum_partial_copy_to_user(const char *src, char *dst, int len, int sum, int *err_ptr);
+#endif
+
+/*
+ * These are the old (and unsafe) way of doing checksums, a warning message will be
+ * printed if they are used and an exception occurs.
+ *
+ * these functions should go away after some time.
+ */
+#define csum_partial_copy_fromuser csum_partial_copy
+unsigned int
+csum_partial_copy(const char *src, char *dst, int len, int sum);
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ *
+ * Converted and optimised for ARM by R. M. King.
+ *
+ * Note: the order that the LDM registers are loaded with respect to
+ * the adc's doesn't matter.
+ */
+static inline unsigned short
+ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+ unsigned int sum, tmp1;
+
+ __asm__ __volatile__("
+ sub %2, %2, #5
+ ldr %0, [%1], #4
+ ldr %3, [%1], #4
+ adds %0, %0, %3
+ ldr %3, [%1], #4
+ adcs %0, %0, %3
+ ldr %3, [%1], #4
+ adcs %0, %0, %3
+1: ldr %3, [%1], #4
+ adcs %0, %0, %3
+ tst %2, #15
+ subne %2, %2, #1
+ bne 1b
+ adc %0, %0, #0
+ adds %0, %0, %0, lsl #16
+ addcs %0, %0, #0x10000
+ mvn %0, %0
+ mov %0, %0, lsr #16
+ "
+ : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (tmp1)
+ : "1" (iph), "2" (ihl));
+ return(sum);
+}
+
+/*
+ * Fold a partial checksum without adding pseudo headers
+ */
+static inline unsigned int
+csum_fold(unsigned int sum)
+{
+ __asm__("
+ adds %0, %0, %0, lsl #16
+ addcs %0, %0, #0x10000"
+ : "=r" (sum)
+ : "0" (sum));
+ return (~sum) >> 16;
+}
+
+static inline unsigned long
+csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
+ unsigned short proto, unsigned int sum)
+{
+ __asm__("
+ adds %0, %0, %1
+ adcs %0, %0, %2
+ adcs %0, %0, %3
+ adc %0, %0, #0"
+ : "=&r"(sum)
+ : "r" (daddr), "r" (saddr), "r" ((ntohs(len)<<16)+proto*256), "0" (sum));
+ return sum;
+}
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int
+csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
+ unsigned short proto, unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+}
+
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+static inline unsigned short
+ip_compute_csum(unsigned char * buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+extern unsigned long
+__csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
+ __u32 proto, unsigned int sum);
+
+extern __inline__ unsigned short int
+csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u16 len,
+ unsigned short proto, unsigned int sum)
+{
+ return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl((__u32)len),
+ htonl(proto), sum));
+}
+#endif
diff --git a/pfinet/linux-src/include/asm-i386/checksum.h b/pfinet/linux-src/include/asm-i386/checksum.h
new file mode 100644
index 00000000..addaea87
--- /dev/null
+++ b/pfinet/linux-src/include/asm-i386/checksum.h
@@ -0,0 +1,215 @@
+#ifndef _I386_CHECKSUM_H
+#define _I386_CHECKSUM_H
+
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
+ int *src_err_ptr, int *dst_err_ptr);
+
+/*
+ * Note: when you get a NULL pointer exception here this means someone
+ * passed in an incorrect kernel address to one of these functions.
+ *
+ * If you use these functions directly please don't forget the
+ * verify_area().
+ */
+extern __inline__
+unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
+ int len, int sum)
+{
+ return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+}
+
+extern __inline__
+unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
+}
+
+#if 0
+
+/* Not used at the moment. It is difficult to imagine for what purpose
+ it can be used :-) Please, do not forget to verify_area before it --ANK
+ */
+
+/*
+ * This combination is currently not used, but possible:
+ */
+
+extern __inline__
+unsigned int csum_partial_copy_to_user ( const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ return csum_partial_copy_generic ( src, dst, len, sum, NULL, err_ptr);
+}
+#endif
+
+/*
+ * These are the old (and unsafe) way of doing checksums, a warning message will be
+ * printed if they are used and an exeption occurs.
+ *
+ * these functions should go away after some time.
+ */
+
+#define csum_partial_copy_fromuser csum_partial_copy
+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ *
+ * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
+ * Arnt Gulbrandsen.
+ */
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+ unsigned int ihl) {
+ unsigned int sum;
+
+ __asm__ __volatile__("
+ movl (%1), %0
+ subl $4, %2
+ jbe 2f
+ addl 4(%1), %0
+ adcl 8(%1), %0
+ adcl 12(%1), %0
+1: adcl 16(%1), %0
+ lea 4(%1), %1
+ decl %2
+ jne 1b
+ adcl $0, %0
+ movl %0, %2
+ shrl $16, %0
+ addw %w2, %w0
+ adcl $0, %0
+ notl %0
+2:
+ "
+ /* Since the input registers which are loaded with iph and ipl
+ are modified, we must also specify them as outputs, or gcc
+ will assume they contain their original values. */
+ : "=r" (sum), "=r" (iph), "=r" (ihl)
+ : "1" (iph), "2" (ihl));
+ return(sum);
+}
+
+/*
+ * Fold a partial checksum
+ */
+
+static inline unsigned int csum_fold(unsigned int sum)
+{
+ __asm__("
+ addl %1, %0
+ adcl $0xffff, %0
+ "
+ : "=r" (sum)
+ : "r" (sum << 16), "0" (sum & 0xffff0000)
+ );
+ return (~sum) >> 16;
+}
+
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__("
+ addl %1, %0
+ adcl %2, %0
+ adcl %3, %0
+ adcl $0, %0
+ "
+ : "=r" (sum)
+ : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+ return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u16 len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__("
+ addl 0(%1), %0
+ adcl 4(%1), %0
+ adcl 8(%1), %0
+ adcl 12(%1), %0
+ adcl 0(%2), %0
+ adcl 4(%2), %0
+ adcl 8(%2), %0
+ adcl 12(%2), %0
+ adcl %3, %0
+ adcl %4, %0
+ adcl $0, %0
+ "
+ : "=&r" (sum)
+ : "r" (saddr), "r" (daddr),
+ "r"(htonl((__u32) (len))), "r"(htonl(proto)), "0"(sum));
+
+ return csum_fold(sum);
+}
+
+/*
+ * Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ if (access_ok(VERIFY_WRITE, dst, len))
+ return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
+
+ if (len)
+ *err_ptr = -EFAULT;
+
+ return -1; /* invalid checksum */
+}
+
+#endif
diff --git a/pfinet/linux-src/include/asm-m68k/checksum.h b/pfinet/linux-src/include/asm-m68k/checksum.h
new file mode 100644
index 00000000..f5236490
--- /dev/null
+++ b/pfinet/linux-src/include/asm-m68k/checksum.h
@@ -0,0 +1,154 @@
+#ifndef _M68K_CHECKSUM_H
+#define _M68K_CHECKSUM_H
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+
+
+/*
+ * the same as csum_partial_copy, but copies from user space.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
+ int len, int sum, int *csum_err);
+
+#define csum_partial_copy_nocheck(src, dst, len, sum) \
+ csum_partial_copy((src), (dst), (len), (sum))
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ *
+ */
+static inline unsigned short
+ip_fast_csum(unsigned char *iph, unsigned int ihl)
+{
+ unsigned int sum = 0;
+
+ __asm__ ("subqw #1,%2\n"
+ "1:\t"
+ "movel %1@+,%/d0\n\t"
+ "addxl %/d0,%0\n\t"
+ "dbra %2,1b\n\t"
+ "movel %0,%/d0\n\t"
+ "swap %/d0\n\t"
+ "addxw %/d0,%0\n\t"
+ "clrw %/d0\n\t"
+ "addxw %/d0,%0\n\t"
+ : "=d" (sum), "=a" (iph), "=d" (ihl)
+ : "0" (sum), "1" (iph), "2" (ihl)
+ : "d0");
+ return ~sum;
+}
+
+/*
+ * Fold a partial checksum
+ */
+
+static inline unsigned int csum_fold(unsigned int sum)
+{
+ unsigned int tmp = sum;
+ __asm__("swap %1\n\t"
+ "addw %1, %0\n\t"
+ "clrw %1\n\t"
+ "addxw %1, %0"
+ : "=&d" (sum), "=&d" (tmp)
+ : "0" (sum), "1" (sum));
+ return ~sum;
+}
+
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+
+static inline unsigned int
+csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
+ unsigned short proto, unsigned int sum)
+{
+ __asm__ ("addl %1,%0\n\t"
+ "addxl %4,%0\n\t"
+ "addxl %5,%0\n\t"
+ "clrl %1\n\t"
+ "addxl %1,%0"
+ : "=&d" (sum), "=&d" (saddr)
+ : "0" (daddr), "1" (saddr), "d" (len + proto),
+ "d"(sum));
+ return sum;
+}
+
+static inline unsigned short int
+csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
+ unsigned short proto, unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline unsigned short
+ip_compute_csum(unsigned char * buff, int len)
+{
+ return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ unsigned short int
+csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
+ __u16 len, unsigned short proto, unsigned int sum)
+{
+ register unsigned long tmp;
+ __asm__("addl %2@,%0\n\t"
+ "movel %2@(4),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %2@(8),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %2@(12),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %3@,%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %3@(4),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %3@(8),%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %3@(12),%1\n\t"
+ "addxl %1,%0\n\t"
+ "addxl %4,%0\n\t"
+ "clrl %1\n\t"
+ "addxl %1,%0"
+ : "=&d" (sum), "=&d" (tmp)
+ : "a" (saddr), "a" (daddr), "d" ((__u32) len + proto),
+ "0" (sum));
+
+ return csum_fold(sum);
+}
+
+#endif /* _M68K_CHECKSUM_H */
diff --git a/pfinet/linux-src/include/asm-mips/checksum.h b/pfinet/linux-src/include/asm-mips/checksum.h
new file mode 100644
index 00000000..6d3700f0
--- /dev/null
+++ b/pfinet/linux-src/include/asm-mips/checksum.h
@@ -0,0 +1,255 @@
+/* $Id: checksum.h,v 1.6 1998/09/19 19:19:36 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_CHECKSUM_H
+#define __ASM_MIPS_CHECKSUM_H
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * this is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros the rest of the buffer.
+ */
+#define csum_partial_copy_nocheck csum_partial_copy
+
+/*
+ * this is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len,
+ unsigned int sum, int *errp);
+
+#define HAVE_CSUM_COPY_USER
+unsigned int csum_and_copy_to_user (const char *src, char *dst,
+ int len, int sum, int *err_ptr);
+
+/*
+ * the same as csum_partial, but copies from user space (but on MIPS
+ * we have just one address space, so this is identical to the above)
+ *
+ * this is obsolete and will go away.
+ */
+#define csum_partial_copy_fromuser csum_partial_copy
+unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
+
+/*
+ * Fold a partial checksum without adding pseudo headers
+ */
+static inline unsigned short int csum_fold(unsigned int sum)
+{
+ __asm__("
+ .set noat
+ sll $1,%0,16
+ addu %0,$1
+ sltu $1,%0,$1
+ srl %0,%0,16
+ addu %0,$1
+ xori %0,0xffff
+ .set at"
+ : "=r" (sum)
+ : "0" (sum)
+ : "$1");
+
+ return sum;
+}
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ *
+ * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
+ * Arnt Gulbrandsen.
+ */
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+ unsigned int ihl)
+{
+ unsigned int sum;
+ unsigned long dummy;
+
+ /*
+ * This is for 32-bit MIPS processors.
+ */
+ __asm__ __volatile__("
+ .set noreorder
+ .set noat
+ lw %0,(%1)
+ subu %2,4
+ #blez %2,2f
+ sll %2,2 # delay slot
+
+ lw %3,4(%1)
+ addu %2,%1 # delay slot
+ addu %0,%3
+ sltu $1,%0,%3
+ lw %3,8(%1)
+ addu %0,$1
+ addu %0,%3
+ sltu $1,%0,%3
+ lw %3,12(%1)
+ addu %0,$1
+ addu %0,%3
+ sltu $1,%0,%3
+ addu %0,$1
+
+1: lw %3,16(%1)
+ addiu %1,4
+ addu %0,%3
+ sltu $1,%0,%3
+ bne %2,%1,1b
+ addu %0,$1 # delay slot
+
+2: .set at
+ .set reorder"
+ : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
+ : "1" (iph), "2" (ihl)
+ : "$1");
+
+ return csum_fold(sum);
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__("
+ .set noat
+ addu %0,%2
+ sltu $1,%0,%2
+ addu %0,$1
+
+ addu %0,%3
+ sltu $1,%0,%3
+ addu %0,$1
+
+ addu %0,%4
+ sltu $1,%0,%4
+ addu %0,$1
+ .set at"
+ : "=r" (sum)
+ : "0" (daddr), "r"(saddr),
+#ifdef __MIPSEL__
+ "r" ((ntohs(len)<<16)+proto*256),
+#else
+ "r" (((proto)<<16)+len),
+#endif
+ "r"(sum)
+ : "$1");
+
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u16 len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__("
+ .set noreorder
+ .set noat
+ addu %0,%5 # proto (long in network byte order)
+ sltu $1,%0,%5
+ addu %0,$1
+
+ addu %0,%6 # csum
+ sltu $1,%0,%6
+ lw %1,0(%2) # four words source address
+ addu %0,$1
+ addu %0,%1
+ sltu $1,%0,$1
+
+ lw %1,4(%2)
+ addu %0,$1
+ addu %0,%1
+ sltu $1,%0,$1
+
+ lw %1,8(%2)
+ addu %0,$1
+ addu %0,%1
+ sltu $1,%0,$1
+
+ lw %1,12(%2)
+ addu %0,$1
+ addu %0,%1
+ sltu $1,%0,$1
+
+ lw %1,0(%3)
+ addu %0,$1
+ addu %0,%1
+ sltu $1,%0,$1
+
+ lw %1,4(%3)
+ addu %0,$1
+ addu %0,%1
+ sltu $1,%0,$1
+
+ lw %1,8(%3)
+ addu %0,$1
+ addu %0,%1
+ sltu $1,%0,$1
+
+ lw %1,12(%3)
+ addu %0,$1
+ addu %0,%1
+ sltu $1,%0,$1
+ .set noat
+ .set noreorder"
+ : "=r" (sum),
+ "=r" (proto)
+ : "r" (saddr),
+ "r" (daddr),
+ "0" (htonl((__u32) (len))),
+ "1" (htonl(proto)),
+ "r"(sum)
+ : "$1");
+
+ return csum_fold(sum);
+}
+
+#endif /* __ASM_MIPS_CHECKSUM_H */
diff --git a/pfinet/linux-src/include/asm-ppc/checksum.h b/pfinet/linux-src/include/asm-ppc/checksum.h
new file mode 100644
index 00000000..e635ff59
--- /dev/null
+++ b/pfinet/linux-src/include/asm-ppc/checksum.h
@@ -0,0 +1,113 @@
+#ifndef _PPC_CHECKSUM_H
+#define _PPC_CHECKSUM_H
+
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern unsigned int csum_partial(const unsigned char * buff, int len,
+ unsigned int sum);
+
+/*
+ * Computes the checksum of a memory block at src, length len,
+ * and adds in "sum" (32-bit), while copying the block to dst.
+ * If an access exception occurs on src or dst, it stores -EFAULT
+ * to *src_err or *dst_err respectively (if that pointer is not
+ * NULL), and, for an error on src, zeroes the rest of dst.
+ *
+ * Like csum_partial, this must be called with even lengths,
+ * except for the last fragment.
+ */
+extern unsigned int csum_partial_copy_generic(const char *src, char *dst,
+ int len, unsigned int sum,
+ int *src_err, int *dst_err);
+
+#define csum_partial_copy_from_user(src, dst, len, sum, errp) \
+ csum_partial_copy_generic((src), (dst), (len), (sum), (errp), 0)
+
+/* FIXME: this needs to be written to really do no check -- Cort */
+#define csum_partial_copy_nocheck(src, dst, len, sum) \
+ csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)
+/*
+ * Old versions which ignore errors.
+ */
+#define csum_partial_copy(src, dst, len, sum) \
+ csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)
+#define csum_partial_copy_fromuser(src, dst, len, sum) \
+ csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)
+
+
+/*
+ * turns a 32-bit partial checksum (e.g. from csum_partial) into a
+ * 1's complement 16-bit checksum.
+ */
+static inline unsigned int csum_fold(unsigned int sum)
+{
+ unsigned int tmp;
+
+ /* swap the two 16-bit halves of sum */
+ __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum));
+ /* if there is a carry from adding the two 16-bit halves,
+ it will carry from the lower half into the upper half,
+ giving us the correct sum in the upper half. */
+ sum = ~(sum + tmp) >> 16;
+ return sum;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+/*
+ * FIXME: I swiped this one from the sparc and made minor modifications.
+ * It may not be correct. -- Cort
+ */
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__("
+ addc %0,%0,%1
+ adde %0,%0,%2
+ adde %0,%0,%3
+ addze %0,%0
+ "
+ : "=r" (sum)
+ : "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
+ return sum;
+}
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries. ihl is the number
+ * of 32-bit words and is always >= 5.
+ */
+extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+extern unsigned short csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum);
+
+#endif
diff --git a/pfinet/linux-src/include/asm-sparc/checksum.h b/pfinet/linux-src/include/asm-sparc/checksum.h
new file mode 100644
index 00000000..e552cfc6
--- /dev/null
+++ b/pfinet/linux-src/include/asm-sparc/checksum.h
@@ -0,0 +1,252 @@
+/* $Id: checksum.h,v 1.29 1999/03/21 05:22:07 davem Exp $ */
+#ifndef __SPARC_CHECKSUM_H
+#define __SPARC_CHECKSUM_H
+
+/* checksum.h: IP/UDP/TCP checksum routines on the Sparc.
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1996 Eddie C. Dost
+ * Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ * Alpha checksum c-code
+ * ix86 inline assembly
+ * RFC1071 Computing the Internet Checksum
+ */
+
+#include <asm/uaccess.h>
+#include <asm/cprefix.h>
+
+/* computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum);
+
+/* the same as csum_partial, but copies from fs:src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+/* FIXME: Remove these two macros ASAP */
+#define csum_partial_copy(src, dst, len, sum) \
+ csum_partial_copy_nocheck(src,dst,len,sum)
+#define csum_partial_copy_fromuser(s, d, l, w) \
+ csum_partial_copy((char *) (s), (d), (l), (w))
+
+extern unsigned int __csum_partial_copy_sparc_generic (const char *, char *);
+
+extern __inline__ unsigned int
+csum_partial_copy_nocheck (const char *src, char *dst, int len,
+ unsigned int sum)
+{
+ register unsigned int ret asm("o0") = (unsigned int)src;
+ register char *d asm("o1") = dst;
+ register int l asm("g1") = len;
+
+ __asm__ __volatile__ ("
+ call " C_LABEL_STR(__csum_partial_copy_sparc_generic) "
+ mov %4, %%g7
+ " : "=r" (ret) : "0" (ret), "r" (d), "r" (l), "r" (sum) :
+ "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g4", "g5", "g7");
+ return ret;
+}
+
+extern __inline__ unsigned int
+csum_partial_copy_from_user(const char *src, char *dst, int len,
+ unsigned int sum, int *err)
+ {
+ if (!access_ok (VERIFY_READ, src, len)) {
+ *err = -EFAULT;
+ memset (dst, 0, len);
+ return sum;
+ } else {
+ register unsigned int ret asm("o0") = (unsigned int)src;
+ register char *d asm("o1") = dst;
+ register int l asm("g1") = len;
+ register unsigned int s asm("g7") = sum;
+
+ __asm__ __volatile__ ("
+ .section __ex_table,#alloc
+ .align 4
+ .word 1f,2
+ .previous
+1:
+ call " C_LABEL_STR(__csum_partial_copy_sparc_generic) "
+ st %5, [%%sp + 64]
+ " : "=r" (ret) : "0" (ret), "r" (d), "r" (l), "r" (s), "r" (err) :
+ "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g4", "g5", "g7");
+ return ret;
+ }
+ }
+
+extern __inline__ unsigned int
+csum_partial_copy_to_user(const char *src, char *dst, int len,
+ unsigned int sum, int *err)
+{
+ if (!access_ok (VERIFY_WRITE, dst, len)) {
+ *err = -EFAULT;
+ return sum;
+ } else {
+ register unsigned int ret asm("o0") = (unsigned int)src;
+ register char *d asm("o1") = dst;
+ register int l asm("g1") = len;
+ register unsigned int s asm("g7") = sum;
+
+ __asm__ __volatile__ ("
+ .section __ex_table,#alloc
+ .align 4
+ .word 1f,1
+ .previous
+1:
+ call " C_LABEL_STR(__csum_partial_copy_sparc_generic) "
+ st %5, [%%sp + 64]
+ " : "=r" (ret) : "0" (ret), "r" (d), "r" (l), "r" (s), "r" (err) :
+ "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g4", "g5", "g7");
+ return ret;
+ }
+}
+
+#define HAVE_CSUM_COPY_USER
+#define csum_and_copy_to_user csum_partial_copy_to_user
+
+/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
+ * the majority of the time.
+ */
+extern __inline__ unsigned short ip_fast_csum(__const__ unsigned char *iph,
+ unsigned int ihl)
+{
+ unsigned short sum;
+
+ /* Note: We must read %2 before we touch %0 for the first time,
+ * because GCC can legitimately use the same register for
+ * both operands.
+ */
+ __asm__ __volatile__("sub\t%2, 4, %%g4\n\t"
+ "ld\t[%1 + 0x00], %0\n\t"
+ "ld\t[%1 + 0x04], %%g2\n\t"
+ "ld\t[%1 + 0x08], %%g3\n\t"
+ "addcc\t%%g2, %0, %0\n\t"
+ "addxcc\t%%g3, %0, %0\n\t"
+ "ld\t[%1 + 0x0c], %%g2\n\t"
+ "ld\t[%1 + 0x10], %%g3\n\t"
+ "addxcc\t%%g2, %0, %0\n\t"
+ "addx\t%0, %%g0, %0\n"
+ "1:\taddcc\t%%g3, %0, %0\n\t"
+ "add\t%1, 4, %1\n\t"
+ "addxcc\t%0, %%g0, %0\n\t"
+ "subcc\t%%g4, 1, %%g4\n\t"
+ "be,a\t2f\n\t"
+ "sll\t%0, 16, %%g2\n\t"
+ "b\t1b\n\t"
+ "ld\t[%1 + 0x10], %%g3\n"
+ "2:\taddcc\t%0, %%g2, %%g2\n\t"
+ "srl\t%%g2, 16, %0\n\t"
+ "addx\t%0, %%g0, %0\n\t"
+ "xnor\t%%g0, %0, %0"
+ : "=r" (sum), "=&r" (iph)
+ : "r" (ihl), "1" (iph)
+ : "g2", "g3", "g4", "cc");
+ return sum;
+}
+
+/* Fold a partial checksum without adding pseudo headers. */
+extern __inline__ unsigned int csum_fold(unsigned int sum)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__("addcc\t%0, %1, %1\n\t"
+ "srl\t%1, 16, %1\n\t"
+ "addx\t%1, %%g0, %1\n\t"
+ "xnor\t%%g0, %1, %0"
+ : "=&r" (sum), "=r" (tmp)
+ : "0" (sum), "1" (sum<<16)
+ : "cc");
+ return sum;
+}
+
+extern __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned int len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__ __volatile__("addcc\t%1, %0, %0\n\t"
+ "addxcc\t%2, %0, %0\n\t"
+ "addxcc\t%3, %0, %0\n\t"
+ "addx\t%0, %%g0, %0\n\t"
+ : "=r" (sum), "=r" (saddr)
+ : "r" (daddr), "r" ((proto<<16)+len), "0" (sum),
+ "1" (saddr)
+ : "cc");
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u16 len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__ __volatile__ ("
+ addcc %3, %4, %%g4
+ addxcc %5, %%g4, %%g4
+ ld [%2 + 0x0c], %%g2
+ ld [%2 + 0x08], %%g3
+ addxcc %%g2, %%g4, %%g4
+ ld [%2 + 0x04], %%g2
+ addxcc %%g3, %%g4, %%g4
+ ld [%2 + 0x00], %%g3
+ addxcc %%g2, %%g4, %%g4
+ ld [%1 + 0x0c], %%g2
+ addxcc %%g3, %%g4, %%g4
+ ld [%1 + 0x08], %%g3
+ addxcc %%g2, %%g4, %%g4
+ ld [%1 + 0x04], %%g2
+ addxcc %%g3, %%g4, %%g4
+ ld [%1 + 0x00], %%g3
+ addxcc %%g2, %%g4, %%g4
+ addxcc %%g3, %%g4, %0
+ addx 0, %0, %0
+ "
+ : "=&r" (sum)
+ : "r" (saddr), "r" (daddr),
+ "r"(htonl((__u32) (len))), "r"(htonl(proto)), "r"(sum)
+ : "g2", "g3", "g4", "cc");
+
+ return csum_fold(sum);
+}
+
+/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
+extern __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+#endif /* !(__SPARC_CHECKSUM_H) */
diff --git a/pfinet/linux-src/include/asm-sparc64/checksum.h b/pfinet/linux-src/include/asm-sparc64/checksum.h
new file mode 100644
index 00000000..e3da2651
--- /dev/null
+++ b/pfinet/linux-src/include/asm-sparc64/checksum.h
@@ -0,0 +1,207 @@
+/* $Id: checksum.h,v 1.11 1998/04/17 02:37:22 davem Exp $ */
+#ifndef __SPARC64_CHECKSUM_H
+#define __SPARC64_CHECKSUM_H
+
+/* checksum.h: IP/UDP/TCP checksum routines on the V9.
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1996 Eddie C. Dost
+ * Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ * Alpha checksum c-code
+ * ix86 inline assembly
+ * RFC1071 Computing the Internet Checksum
+ */
+
+#include <asm/uaccess.h>
+
+/* computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum);
+
+/* the same as csum_partial, but copies from user space while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+/* FIXME: Remove these macros ASAP */
+#define csum_partial_copy(src, dst, len, sum) \
+ csum_partial_copy_nocheck(src,dst,len,sum)
+#define csum_partial_copy_fromuser(s, d, l, w) \
+ csum_partial_copy_from_user((char *) (s), (d), (l), (w), NULL)
+
+extern unsigned int csum_partial_copy_sparc64(const char *src, char *dst, int len, unsigned int sum);
+
+extern __inline__ unsigned int
+csum_partial_copy_nocheck (const char *src, char *dst, int len,
+ unsigned int sum)
+{
+ __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "i" (ASI_P));
+ return csum_partial_copy_sparc64(src, dst, len, sum);
+}
+
+extern __inline__ unsigned int
+csum_partial_copy_from_user(const char *src, char *dst, int len,
+ unsigned int sum, int *err)
+{
+ __asm__ __volatile__ ("wr %%g0, %0, %%asi
+ stx %1, [%%sp + 0x7ff + 128]
+ " : : "i" (ASI_S), "r" (err));
+ return csum_partial_copy_sparc64(src, dst, len, sum);
+}
+
+#if 0
+/* Not implemented, but nobody uses it yet... */
+extern __inline__ unsigned int
+csum_partial_copy_to_user(const char *src, char *dst, int len,
+ unsigned int sum, int *err)
+{
+ return 0;
+}
+#endif
+
+/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
+ * the majority of the time.
+ */
+extern __inline__ unsigned short ip_fast_csum(__const__ unsigned char *iph,
+ unsigned int ihl)
+{
+ unsigned short sum;
+
+ /* Note: We must read %2 before we touch %0 for the first time,
+ * because GCC can legitimately use the same register for
+ * both operands.
+ */
+ __asm__ __volatile__("
+ sub %2, 4, %%g7 ! IEU0
+ lduw [%1 + 0x00], %0 ! Load Group
+ lduw [%1 + 0x04], %%g2 ! Load Group
+ lduw [%1 + 0x08], %%g3 ! Load Group
+ addcc %%g2, %0, %0 ! IEU1 1 Load Bubble + Group
+ lduw [%1 + 0x0c], %%g2 ! Load
+ addccc %%g3, %0, %0 ! Sngle Group no Bubble
+ lduw [%1 + 0x10], %%g3 ! Load Group
+ addccc %%g2, %0, %0 ! Sngle Group no Bubble
+ addc %0, %%g0, %0 ! Sngle Group
+1: addcc %%g3, %0, %0 ! IEU1 Group no Bubble
+ add %1, 4, %1 ! IEU0
+ addccc %0, %%g0, %0 ! Sngle Group no Bubble
+ subcc %%g7, 1, %%g7 ! IEU1 Group
+ be,a,pt %%icc, 2f ! CTI
+ sll %0, 16, %%g2 ! IEU0
+ lduw [%1 + 0x10], %%g3 ! Load Group
+ ba,pt %%xcc, 1b ! CTI
+ nop ! IEU0
+2: addcc %0, %%g2, %%g2 ! IEU1 Group
+ srl %%g2, 16, %0 ! IEU0 Group regdep XXX Scheisse!
+ addc %0, %%g0, %0 ! Sngle Group
+ xnor %%g0, %0, %0 ! IEU0 Group
+ srl %0, 0, %0 ! IEU0 Group XXX Scheisse!
+" : "=r" (sum), "=&r" (iph)
+ : "r" (ihl), "1" (iph)
+ : "g2", "g3", "g7", "cc");
+ return sum;
+}
+
+/* Fold a partial checksum without adding pseudo headers. */
+extern __inline__ unsigned short csum_fold(unsigned int sum)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__("
+ addcc %0, %1, %1
+ srl %1, 16, %1
+ addc %1, %%g0, %1
+ xnor %%g0, %1, %0
+" : "=&r" (sum), "=r" (tmp)
+ : "0" (sum), "1" (sum<<16)
+ : "cc");
+ return (sum & 0xffff);
+}
+
+extern __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned int len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__ __volatile__("
+ addcc %1, %0, %0
+ addccc %2, %0, %0
+ addccc %3, %0, %0
+ addc %0, %%g0, %0
+" : "=r" (sum), "=r" (saddr)
+ : "r" (daddr), "r" ((proto<<16)+len), "0" (sum), "1" (saddr)
+ : "cc");
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u16 len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__ __volatile__ ("
+ addcc %3, %4, %%g7
+ addccc %5, %%g7, %%g7
+ lduw [%2 + 0x0c], %%g2
+ lduw [%2 + 0x08], %%g3
+ addccc %%g2, %%g7, %%g7
+ lduw [%2 + 0x04], %%g2
+ addccc %%g3, %%g7, %%g7
+ lduw [%2 + 0x00], %%g3
+ addccc %%g2, %%g7, %%g7
+ lduw [%1 + 0x0c], %%g2
+ addccc %%g3, %%g7, %%g7
+ lduw [%1 + 0x08], %%g3
+ addccc %%g2, %%g7, %%g7
+ lduw [%1 + 0x04], %%g2
+ addccc %%g3, %%g7, %%g7
+ lduw [%1 + 0x00], %%g3
+ addccc %%g2, %%g7, %%g7
+ addccc %%g3, %%g7, %0
+ addc 0, %0, %0
+" : "=&r" (sum)
+ : "r" (saddr), "r" (daddr), "r"(htonl((__u32) (len))),
+ "r"(htonl(proto)), "r"(sum)
+ : "g2", "g3", "g7", "cc");
+
+ return csum_fold(sum);
+}
+
+/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
+extern __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+#endif /* !(__SPARC64_CHECKSUM_H) */
diff --git a/pfinet/linux-src/include/linux/a.out.h b/pfinet/linux-src/include/linux/a.out.h
new file mode 100644
index 00000000..af8a1dfa
--- /dev/null
+++ b/pfinet/linux-src/include/linux/a.out.h
@@ -0,0 +1,268 @@
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+#include <asm/a.out.h>
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+enum machine_type {
+#if defined (M_OLDSUN2)
+ M__OLDSUN2 = M_OLDSUN2,
+#else
+ M_OLDSUN2 = 0,
+#endif
+#if defined (M_68010)
+ M__68010 = M_68010,
+#else
+ M_68010 = 1,
+#endif
+#if defined (M_68020)
+ M__68020 = M_68020,
+#else
+ M_68020 = 2,
+#endif
+#if defined (M_SPARC)
+ M__SPARC = M_SPARC,
+#else
+ M_SPARC = 3,
+#endif
+ /* skip a bunch so we don't run into any of sun's numbers */
+ M_386 = 100,
+ M_MIPS1 = 151, /* MIPS R3000/R3000 binary */
+ M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
+};
+
+#if !defined (N_MAGIC)
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#endif
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+/* Code indicating object file or impure executable. */
+#define OMAGIC 0407
+/* Code indicating pure executable. */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable. */
+#define ZMAGIC 0413
+/* This indicates a demand-paged executable with the header in the text.
+ The first page is unmapped to help trap NULL pointer references */
+#define QMAGIC 0314
+
+/* Code indicating core file. */
+#define CMAGIC 0421
+
+#if !defined (N_BADMAG)
+#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC \
+ && N_MAGIC(x) != QMAGIC)
+#endif
+
+#define _N_HDROFF(x) (1024 - sizeof (struct exec))
+
+#if !defined (N_TXTOFF)
+#define N_TXTOFF(x) \
+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
+ (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
+#endif
+
+#if !defined (N_DATOFF)
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+#endif
+
+#if !defined (N_TRELOFF)
+#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+#endif
+
+#if !defined (N_DRELOFF)
+#define N_DRELOFF(x) (N_TRELOFF(x) + N_TRSIZE(x))
+#endif
+
+#if !defined (N_SYMOFF)
+#define N_SYMOFF(x) (N_DRELOFF(x) + N_DRSIZE(x))
+#endif
+
+#if !defined (N_STROFF)
+#define N_STROFF(x) (N_SYMOFF(x) + N_SYMSIZE(x))
+#endif
+
+/* Address of text segment in memory after it is loaded. */
+#if !defined (N_TXTADDR)
+#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
+#endif
+
+/* Address of data segment in memory after it is loaded.
+ Note that it is up to you to define SEGMENT_SIZE
+ on machines not listed here. */
+#if defined(vax) || defined(hp300) || defined(pyr)
+#define SEGMENT_SIZE page_size
+#endif
+#ifdef sony
+#define SEGMENT_SIZE 0x2000
+#endif /* Sony. */
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+#if defined(m68k) && defined(PORTAR)
+#define PAGE_SIZE 0x400
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+
+#ifdef linux
+#include <asm/page.h>
+#if defined(__i386__) || defined(__mc68000__)
+#define SEGMENT_SIZE 1024
+#else
+#ifndef SEGMENT_SIZE
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+#endif
+#endif
+
+#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+
+#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
+ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+#endif
+
+/* Address of bss segment in memory after it is loaded. */
+#if !defined (N_BSSADDR)
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+#endif
+
+#if !defined (N_NLIST_DECLARED)
+struct nlist {
+ union {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx;
+ } n_un;
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ unsigned long n_value;
+};
+#endif /* no N_NLIST_DECLARED. */
+
+#if !defined (N_UNDF)
+#define N_UNDF 0
+#endif
+#if !defined (N_ABS)
+#define N_ABS 2
+#endif
+#if !defined (N_TEXT)
+#define N_TEXT 4
+#endif
+#if !defined (N_DATA)
+#define N_DATA 6
+#endif
+#if !defined (N_BSS)
+#define N_BSS 8
+#endif
+#if !defined (N_FN)
+#define N_FN 15
+#endif
+
+#if !defined (N_EXT)
+#define N_EXT 1
+#endif
+#if !defined (N_TYPE)
+#define N_TYPE 036
+#endif
+#if !defined (N_STAB)
+#define N_STAB 0340
+#endif
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition. */
+#define N_INDR 0xa
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ element's value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+#if !defined (N_RELOCATION_INFO_DECLARED)
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+struct relocation_info
+{
+ /* Address (within segment) to be relocated. */
+ int r_address;
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in file's the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* Four bits that aren't used, but when writing an object file
+ it is desirable to clear them. */
+#ifdef NS32K
+ unsigned r_bsr:1;
+ unsigned r_disp:1;
+ unsigned r_pad:2;
+#else
+ unsigned int r_pad:4;
+#endif
+};
+#endif /* no N_RELOCATION_INFO_DECLARED. */
+
+
+#endif /* __A_OUT_GNU_H__ */
diff --git a/pfinet/linux-src/include/linux/acct.h b/pfinet/linux-src/include/linux/acct.h
new file mode 100644
index 00000000..e20b1839
--- /dev/null
+++ b/pfinet/linux-src/include/linux/acct.h
@@ -0,0 +1,88 @@
+/*
+ * BSD Process Accounting for Linux - Definitions
+ *
+ * Author: Marco van Wieringen (mvw@planets.elm.net)
+ *
+ * This header file contains the definitions needed to implement
+ * BSD-style process accounting. The kernel accounting code and all
+ * user-level programs that try to do something useful with the
+ * process accounting log must include this file.
+ *
+ * Copyright (C) 1995 - 1997 Marco van Wieringen - ELM Consultancy B.V.
+ *
+ */
+
+#ifndef _LINUX_ACCT_H
+#define _LINUX_ACCT_H
+
+#include <linux/types.h>
+
+/*
+ * comp_t is a 16-bit "floating" point number with a 3-bit base 8
+ * exponent and a 13-bit fraction. See linux/kernel/acct.c for the
+ * specific encoding system used.
+ */
+
+typedef __u16 comp_t;
+
+/*
+ * accounting file record
+ *
+ * This structure contains all of the information written out to the
+ * process accounting file whenever a process exits.
+ */
+
+#define ACCT_COMM 16
+
+struct acct
+{
+ char ac_flag; /* Accounting Flags */
+/*
+ * No binary format break with 2.0 - but when we hit 32bit uid we'll
+ * have to bite one
+ */
+ __u16 ac_uid; /* Accounting Real User ID */
+ __u16 ac_gid; /* Accounting Real Group ID */
+ __u16 ac_tty; /* Accounting Control Terminal */
+ __u32 ac_btime; /* Accounting Process Creation Time */
+ comp_t ac_utime; /* Accounting User Time */
+ comp_t ac_stime; /* Accounting System Time */
+ comp_t ac_etime; /* Accounting Elapsed Time */
+ comp_t ac_mem; /* Accounting Average Memory Usage */
+ comp_t ac_io; /* Accounting Chars Transferred */
+ comp_t ac_rw; /* Accounting Blocks Read or Written */
+ comp_t ac_minflt; /* Accounting Minor Pagefaults */
+ comp_t ac_majflt; /* Accounting Major Pagefaults */
+ comp_t ac_swaps; /* Accounting Number of Swaps */
+ __u32 ac_exitcode; /* Accounting Exitcode */
+ char ac_comm[ACCT_COMM + 1]; /* Accounting Command Name */
+ char ac_pad[10]; /* Accounting Padding Bytes */
+};
+
+/*
+ * accounting flags
+ */
+ /* bit set when the process ... */
+#define AFORK 0x01 /* ... executed fork, but did not exec */
+#define ASU 0x02 /* ... used super-user privileges */
+#define ACOMPAT 0x04 /* ... used compatibility mode (VAX only not used) */
+#define ACORE 0x08 /* ... dumped core */
+#define AXSIG 0x10 /* ... was killed by a signal */
+
+#define AHZ 100
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#ifdef CONFIG_BSD_PROCESS_ACCT
+extern void acct_auto_close(kdev_t dev);
+extern int acct_process(long exitcode);
+#else
+#define acct_auto_close(x) do { } while (0)
+#define acct_process(x) do { } while (0)
+#endif
+
+#endif /* __KERNEL */
+
+#endif /* _LINUX_ACCT_H */
diff --git a/pfinet/linux-src/include/linux/adfs_fs.h b/pfinet/linux-src/include/linux/adfs_fs.h
new file mode 100644
index 00000000..f6ed2d3b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/adfs_fs.h
@@ -0,0 +1,175 @@
+#ifndef _ADFS_FS_H
+#define _ADFS_FS_H
+
+#include <linux/types.h>
+/*
+ * Structures of data on the disk
+ */
+
+/*
+ * Disc Record at disc address 0xc00
+ */
+struct adfs_discrecord {
+ unsigned char log2secsize;
+ unsigned char secspertrack;
+ unsigned char heads;
+ unsigned char density;
+ unsigned char idlen;
+ unsigned char log2bpmb;
+ unsigned char skew;
+ unsigned char bootoption;
+ unsigned char lowsector;
+ unsigned char nzones;
+ unsigned short zone_spare;
+ unsigned long root;
+ unsigned long disc_size;
+ unsigned short disc_id;
+ unsigned char disc_name[10];
+ unsigned long disc_type;
+ unsigned long disc_size_high;
+ unsigned char log2sharesize:4;
+ unsigned char unused:4;
+ unsigned char big_flag:1;
+};
+
+#define ADFS_DISCRECORD (0xc00)
+#define ADFS_DR_OFFSET (0x1c0)
+#define ADFS_DR_SIZE 60
+#define ADFS_SUPER_MAGIC 0xadf5
+#define ADFS_FREE_FRAG 0
+#define ADFS_BAD_FRAG 1
+#define ADFS_ROOT_FRAG 2
+
+/*
+ * Directory header
+ */
+struct adfs_dirheader {
+ unsigned char startmasseq;
+ unsigned char startname[4];
+};
+
+#define ADFS_NEWDIR_SIZE 2048
+#define ADFS_OLDDIR_SIZE 1024
+#define ADFS_NUM_DIR_ENTRIES 77
+
+/*
+ * Directory entries
+ */
+struct adfs_direntry {
+ char dirobname[10];
+#define ADFS_NAME_LEN 10
+ __u8 dirload[4];
+ __u8 direxec[4];
+ __u8 dirlen[4];
+ __u8 dirinddiscadd[3];
+ __u8 newdiratts;
+#define ADFS_NDA_OWNER_READ (1 << 0)
+#define ADFS_NDA_OWNER_WRITE (1 << 1)
+#define ADFS_NDA_LOCKED (1 << 2)
+#define ADFS_NDA_DIRECTORY (1 << 3)
+#define ADFS_NDA_EXECUTE (1 << 4)
+#define ADFS_NDA_PUBLIC_READ (1 << 5)
+#define ADFS_NDA_PUBLIC_WRITE (1 << 6)
+};
+
+#define ADFS_MAX_NAME_LEN 255
+struct adfs_idir_entry {
+ __u32 inode_no; /* Address */
+ __u32 file_id; /* file id */
+ __u32 name_len; /* name length */
+ __u32 size; /* size */
+ __u32 mtime; /* modification time */
+ __u32 filetype; /* RiscOS file type */
+ __u8 mode; /* internal mode */
+ char name[ADFS_MAX_NAME_LEN]; /* file name */
+};
+
+/*
+ * Directory tail
+ */
+union adfs_dirtail {
+ struct {
+ unsigned char dirlastmask;
+ char dirname[10];
+ unsigned char dirparent[3];
+ char dirtitle[19];
+ unsigned char reserved[14];
+ unsigned char endmasseq;
+ unsigned char endname[4];
+ unsigned char dircheckbyte;
+ } old;
+ struct {
+ unsigned char dirlastmask;
+ unsigned char reserved[2];
+ unsigned char dirparent[3];
+ char dirtitle[19];
+ char dirname[10];
+ unsigned char endmasseq;
+ unsigned char endname[4];
+ unsigned char dircheckbyte;
+ } new;
+};
+
+#ifdef __KERNEL__
+/*
+ * Calculate the boot block checksum on an ADFS drive. Note that this will
+ * appear to be correct if the sector contains all zeros, so also check that
+ * the disk size is non-zero!!!
+ */
+extern inline int adfs_checkbblk(unsigned char *ptr)
+{
+ unsigned int result = 0;
+ unsigned char *p = ptr + 511;
+
+ do {
+ result = (result & 0xff) + (result >> 8);
+ result = result + *--p;
+ } while (p != ptr);
+
+ return (result & 0xff) != ptr[511];
+}
+
+/* dir.c */
+extern unsigned int adfs_val (unsigned char *p, int len);
+extern int adfs_dir_read_parent (struct inode *inode, struct buffer_head **bhp);
+extern int adfs_dir_read (struct inode *inode, struct buffer_head **bhp);
+extern int adfs_dir_check (struct inode *inode, struct buffer_head **bhp,
+ int buffers, union adfs_dirtail *dtp);
+extern void adfs_dir_free (struct buffer_head **bhp, int buffers);
+extern int adfs_dir_get (struct super_block *sb, struct buffer_head **bhp,
+ int buffers, int pos, unsigned long parent_object_id,
+ struct adfs_idir_entry *ide);
+extern int adfs_dir_find_entry (struct super_block *sb, struct buffer_head **bhp,
+ int buffers, unsigned int index,
+ struct adfs_idir_entry *ide);
+
+/* inode.c */
+extern int adfs_inode_validate (struct inode *inode);
+extern unsigned long adfs_inode_generate (unsigned long parent_id, int diridx);
+extern unsigned long adfs_inode_objid (struct inode *inode);
+extern unsigned int adfs_parent_bmap (struct inode *inode, int block);
+extern int adfs_bmap (struct inode *inode, int block);
+extern void adfs_read_inode (struct inode *inode);
+
+/* map.c */
+extern int adfs_map_lookup (struct super_block *sb, int frag_id, int offset);
+
+/* namei.c */
+extern struct dentry *adfs_lookup (struct inode *dir, struct dentry *dentry);
+
+/* super.c */
+extern int init_adfs_fs (void);
+extern void adfs_error (struct super_block *, const char *, const char *, ...);
+
+/*
+ * Inodes and file operations
+ */
+
+/* dir.c */
+extern struct inode_operations adfs_dir_inode_operations;
+
+/* file.c */
+extern struct inode_operations adfs_file_inode_operations;
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/adfs_fs_i.h b/pfinet/linux-src/include/linux/adfs_fs_i.h
new file mode 100644
index 00000000..83157516
--- /dev/null
+++ b/pfinet/linux-src/include/linux/adfs_fs_i.h
@@ -0,0 +1,17 @@
+/*
+ * linux/include/linux/adfs_fs_i.h
+ *
+ * Copyright (C) 1997 Russell King
+ */
+
+#ifndef _ADFS_FS_I
+#define _ADFS_FS_I
+
+/*
+ * adfs file system inode data in memory
+ */
+struct adfs_inode_info {
+ unsigned long file_id; /* id of fragments containing actual data */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/adfs_fs_sb.h b/pfinet/linux-src/include/linux/adfs_fs_sb.h
new file mode 100644
index 00000000..649b61e4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/adfs_fs_sb.h
@@ -0,0 +1,33 @@
+/*
+ * linux/include/linux/adfs_fs_sb.h
+ *
+ * Copyright (C) 1997 Russell King
+ */
+
+#ifndef _ADFS_FS_SB
+#define _ADFS_FS_SB
+
+#include <linux/adfs_fs.h>
+
+/*
+ * adfs file system superblock data in memory
+ */
+struct adfs_sb_info {
+ struct buffer_head *s_sbh; /* buffer head containing disc record */
+ struct adfs_discrecord *s_dr; /* pointer to disc record in s_sbh */
+ uid_t s_uid; /* owner uid */
+ gid_t s_gid; /* owner gid */
+ int s_owner_mask; /* ADFS Owner perm -> unix perm */
+ int s_other_mask; /* ADFS Other perm -> unix perm */
+ __u16 s_zone_size; /* size of a map zone in bits */
+ __u16 s_ids_per_zone; /* max. no ids in one zone */
+ __u32 s_idlen; /* length of ID in map */
+ __u32 s_map_size; /* size of a map */
+ __u32 s_zonesize; /* zone size (in map bits) */
+ __u32 s_map_block; /* block address of map */
+ struct buffer_head **s_map; /* bh list containing map */
+ __u32 s_root; /* root disc address */
+ __s8 s_map2blk; /* shift left by this for map->sector */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/affs_fs.h b/pfinet/linux-src/include/linux/affs_fs.h
new file mode 100644
index 00000000..342ac264
--- /dev/null
+++ b/pfinet/linux-src/include/linux/affs_fs.h
@@ -0,0 +1,115 @@
+#ifndef _AFFS_FS_H
+#define _AFFS_FS_H
+/*
+ * The affs filesystem constants/structures
+ */
+
+#include <linux/types.h>
+
+#define AFFS_SUPER_MAGIC 0xadff
+
+/* Get the filesystem block size given an inode. */
+#define AFFS_I2BSIZE(inode) ((inode)->i_sb->s_blocksize)
+
+/* Get the filesystem hash table size given an inode. */
+#define AFFS_I2HSIZE(inode) ((inode)->i_sb->u.affs_sb.s_hashsize)
+
+/* Get the block number bits given an inode */
+#define AFFS_I2BITS(inode) ((inode)->i_sb->s_blocksize_bits)
+
+/* Get the fs type given an inode */
+#define AFFS_I2FSTYPE(inode) ((inode)->i_sb->u.affs_sb.s_flags & SF_INTL)
+
+struct DateStamp
+{
+ u32 ds_Days;
+ u32 ds_Minute;
+ u32 ds_Tick;
+};
+
+/* --- Prototypes ----------------------------------------------------------------------------- */
+
+/* amigaffs.c */
+
+extern int affs_get_key_entry(int bsize, void *data, int entry_pos);
+extern int affs_get_file_name(int bsize, void *fh_data, unsigned char **name);
+extern u32 affs_checksum_block(int bsize, void *data, s32 *ptype, s32 *stype);
+extern void affs_fix_checksum(int bsize, void *data, int cspos);
+extern void secs_to_datestamp(time_t secs, struct DateStamp *ds);
+extern int prot_to_mode(unsigned int prot);
+extern u32 mode_to_prot(int mode);
+extern int affs_insert_hash(unsigned long dir_ino, struct buffer_head *header,
+ struct inode *inode);
+extern int affs_remove_hash(struct buffer_head *bh, struct inode *inode);
+extern int affs_remove_link(struct buffer_head *bh, struct inode *inode);
+extern int affs_remove_header(struct buffer_head *bh, struct inode *inode);
+extern void affs_error(struct super_block *sb, const char *function, const char *fmt, ...);
+extern void affs_warning(struct super_block *sb, const char *function, const char *fmt, ...);
+extern int affs_check_name(const unsigned char *name, int len);
+extern int affs_copy_name(unsigned char *bstr, const unsigned char *name);
+
+/* bitmap. c */
+
+extern int affs_count_free_blocks(struct super_block *s);
+extern int affs_count_free_bits(int blocksize, const char *data);
+extern void affs_free_block(struct super_block *sb, s32 block);
+extern s32 affs_new_header(struct inode *inode);
+extern s32 affs_new_data(struct inode *inode);
+extern void affs_make_zones(struct super_block *sb);
+
+/* namei.c */
+
+extern int affs_hash_name(const unsigned char *name, int len, int intl, int hashsize);
+extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry);
+extern int affs_unlink(struct inode *dir, struct dentry *dentry);
+extern int affs_create(struct inode *dir, struct dentry *dentry, int mode);
+extern int affs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+extern int affs_rmdir(struct inode *dir, struct dentry *dentry);
+extern int affs_link(struct dentry *olddentry, struct inode *dir,
+ struct dentry *dentry);
+extern int affs_symlink(struct inode *dir, struct dentry *dentry,
+ const char *symname);
+extern int affs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry);
+
+/* inode.c */
+
+extern struct buffer_head *affs_bread(kdev_t dev, int block, int size);
+extern void affs_brelse(struct buffer_head *buf);
+extern unsigned long affs_parent_ino(struct inode *dir);
+extern struct inode *affs_new_inode(const struct inode *dir);
+extern int affs_notify_change(struct dentry *dentry, struct iattr *attr);
+extern int affs_add_entry(struct inode *dir, struct inode *link,
+ struct inode *inode, struct dentry *dentry, s32 type);
+extern void affs_put_inode(struct inode *inode);
+extern void affs_delete_inode(struct inode *inode);
+extern void affs_read_inode(struct inode *inode);
+extern void affs_write_inode(struct inode *inode);
+
+/* super.c */
+
+extern int affs_fs(void);
+extern int init_affs_fs(void);
+
+/* file.c */
+
+void affs_free_prealloc(struct inode *inode);
+extern void affs_truncate(struct inode *);
+
+/* dir.c */
+
+extern void affs_dir_truncate(struct inode *);
+
+/* jump tables */
+
+extern struct inode_operations affs_file_inode_operations;
+extern struct inode_operations affs_file_inode_operations_ofs;
+extern struct inode_operations affs_dir_inode_operations;
+extern struct inode_operations affs_symlink_inode_operations;
+extern struct inode_operations affs_chrdev_inode_operations;
+extern struct inode_operations affs_blkdev_inode_operations;
+
+extern struct dentry_operations affs_dentry_operations;
+extern struct dentry_operations affs_dentry_operations_intl;
+
+#endif
diff --git a/pfinet/linux-src/include/linux/affs_fs_i.h b/pfinet/linux-src/include/linux/affs_fs_i.h
new file mode 100644
index 00000000..beeabb0d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/affs_fs_i.h
@@ -0,0 +1,47 @@
+#ifndef _AFFS_FS_I
+#define _AFFS_FS_I
+
+#include <linux/a.out.h>
+#include <linux/time.h>
+
+#define AFFS_MAX_PREALLOC 16 /* MUST be a power of 2 */
+#define AFFS_KCSIZE 73 /* Allows for 1 extension block at 512 byte-blocks */
+
+struct key_cache {
+ struct timeval kc_lru_time; /* Last time this cache was used */
+ s32 kc_first; /* First cached key */
+ s32 kc_last; /* Last cached key */
+ s32 kc_this_key; /* Key of extension block this data block keys are from */
+ int kc_this_seq; /* Sequence number of this extension block */
+ s32 kc_next_key; /* Key of next extension block */
+ s32 kc_keys[AFFS_KCSIZE]; /* Key cache */
+};
+
+#define EC_SIZE (PAGE_SIZE - 4 * sizeof(struct key_cache) - 4) / 4
+
+struct ext_cache {
+ struct key_cache kc[4]; /* The 4 key caches */
+ s32 ec[EC_SIZE]; /* Keys of assorted extension blocks */
+ int max_ext; /* Index of last known extension block */
+};
+
+/*
+ * affs fs inode data in memory
+ */
+struct affs_inode_info {
+ u32 i_protect; /* unused attribute bits */
+ s32 i_parent; /* parent ino */
+ s32 i_original; /* if != 0, this is the key of the original */
+ s32 i_data[AFFS_MAX_PREALLOC]; /* preallocated blocks */
+ struct ext_cache *i_ec; /* Cache gets allocated dynamically */
+ int i_cache_users; /* Cache cannot be freed while > 0 */
+ int i_lastblock; /* last allocated block */
+ short i_pa_cnt; /* number of preallocated blocks */
+ short i_pa_next; /* Index of next block in i_data[] */
+ short i_pa_last; /* Index of next free slot in i_data[] */
+ short i_zone; /* write zone */
+ unsigned char i_hlink; /* This is a fake */
+ unsigned char i_pad;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/affs_fs_sb.h b/pfinet/linux-src/include/linux/affs_fs_sb.h
new file mode 100644
index 00000000..a066aee7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/affs_fs_sb.h
@@ -0,0 +1,74 @@
+#ifndef _AFFS_FS_SB
+#define _AFFS_FS_SB
+
+/*
+ * super-block data in memory
+ *
+ * Block numbers are adjusted for their actual size
+ *
+ */
+
+#define MAX_ZONES 8
+#define AFFS_DATA_MIN_FREE 512 /* Number of free blocks in zone for data blocks */
+#define AFFS_HDR_MIN_FREE 128 /* Same for header blocks */
+#define AFFS_ZONE_SIZE 1024 /* Blocks per alloc zone, must be multiple of 32 */
+
+struct affs_bm_info {
+ struct buffer_head *bm_bh; /* Buffer head if loaded (bm_count > 0) */
+ s32 bm_firstblk; /* Block number of first bit in this map */
+ s32 bm_key; /* Disk block number */
+ int bm_count; /* Usage counter */
+};
+
+struct affs_alloc_zone {
+ short az_size; /* Size of this allocation zone in double words */
+ short az_count; /* Number of users */
+ int az_free; /* Free blocks in here (no. of bits) */
+};
+
+struct affs_zone {
+ unsigned long z_ino; /* Associated inode number */
+ struct affs_bm_info *z_bm; /* Zone lies in this bitmap */
+ int z_start; /* Index of first word in bitmap */
+ int z_end; /* Index of last word in zone + 1 */
+ int z_az_no; /* Zone number */
+ unsigned long z_lru_time; /* Time of last usage */
+};
+
+struct affs_sb_info {
+ int s_partition_size; /* Partition size in blocks. */
+ int s_blksize; /* Initial device blksize */
+ s32 s_root_block; /* FFS root block number. */
+ int s_hashsize; /* Size of hash table. */
+ unsigned long s_flags; /* See below. */
+ s16 s_uid; /* uid to override */
+ s16 s_gid; /* gid to override */
+ umode_t s_mode; /* mode to override */
+ int s_reserved; /* Number of reserved blocks. */
+ struct buffer_head *s_root_bh; /* Cached root block. */
+ struct affs_bm_info *s_bitmap; /* Bitmap infos. */
+ int s_bm_count; /* Number of bitmap blocks. */
+ int s_nextzone; /* Next zone to look for free blocks. */
+ int s_num_az; /* Total number of alloc zones. */
+ struct affs_zone *s_zones; /* The zones themselves. */
+ struct affs_alloc_zone *s_alloc;/* The allocation zones. */
+ char *s_zonemap; /* Bitmap for allocation zones. */
+ char *s_prefix; /* Prefix for volumes and assigns. */
+ int s_prefix_len; /* Length of prefix. */
+ char s_volume[32]; /* Volume prefix for absolute symlinks. */
+};
+
+#define SF_INTL 0x0001 /* International filesystem. */
+#define SF_BM_VALID 0x0002 /* Bitmap is valid. */
+#define SF_IMMUTABLE 0x0004 /* Protection bits cannot be changed */
+#define SF_QUIET 0x0008 /* chmod errors will be not reported */
+#define SF_SETUID 0x0010 /* Ignore Amiga uid */
+#define SF_SETGID 0x0020 /* Ignore Amiga gid */
+#define SF_SETMODE 0x0040 /* Ignore Amiga protection bits */
+#define SF_MUFS 0x0100 /* Use MUFS uid/gid mapping */
+#define SF_OFS 0x0200 /* Old filesystem */
+#define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */
+#define SF_VERBOSE 0x0800 /* Talk about fs when mounting */
+#define SF_READONLY 0x1000 /* Don't allow to remount rw */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/affs_hardblocks.h b/pfinet/linux-src/include/linux/affs_hardblocks.h
new file mode 100644
index 00000000..ae893e02
--- /dev/null
+++ b/pfinet/linux-src/include/linux/affs_hardblocks.h
@@ -0,0 +1,66 @@
+#ifndef AFFS_HARDBLOCKS_H
+#define AFFS_HARDBLOCKS_H
+
+/* Just the needed definitions for the RDB of an Amiga HD. */
+
+struct RigidDiskBlock {
+ u32 rdb_ID;
+ u32 rdb_SummedLongs;
+ s32 rdb_ChkSum;
+ u32 rdb_HostID;
+ u32 rdb_BlockBytes;
+ u32 rdb_Flags;
+ u32 rdb_BadBlockList;
+ u32 rdb_PartitionList;
+ u32 rdb_FileSysHeaderList;
+ u32 rdb_DriveInit;
+ u32 rdb_Reserved1[6];
+ u32 rdb_Cylinders;
+ u32 rdb_Sectors;
+ u32 rdb_Heads;
+ u32 rdb_Interleave;
+ u32 rdb_Park;
+ u32 rdb_Reserved2[3];
+ u32 rdb_WritePreComp;
+ u32 rdb_ReducedWrite;
+ u32 rdb_StepRate;
+ u32 rdb_Reserved3[5];
+ u32 rdb_RDBBlocksLo;
+ u32 rdb_RDBBlocksHi;
+ u32 rdb_LoCylinder;
+ u32 rdb_HiCylinder;
+ u32 rdb_CylBlocks;
+ u32 rdb_AutoParkSeconds;
+ u32 rdb_HighRDSKBlock;
+ u32 rdb_Reserved4;
+ char rdb_DiskVendor[8];
+ char rdb_DiskProduct[16];
+ char rdb_DiskRevision[4];
+ char rdb_ControllerVendor[8];
+ char rdb_ControllerProduct[16];
+ char rdb_ControllerRevision[4];
+ u32 rdb_Reserved5[10];
+};
+
+#define IDNAME_RIGIDDISK 0x5244534B /* "RDSK" */
+
+struct PartitionBlock {
+ u32 pb_ID;
+ u32 pb_SummedLongs;
+ s32 pb_ChkSum;
+ u32 pb_HostID;
+ u32 pb_Next;
+ u32 pb_Flags;
+ u32 pb_Reserved1[2];
+ u32 pb_DevFlags;
+ u8 pb_DriveName[32];
+ u32 pb_Reserved2[15];
+ u32 pb_Environment[17];
+ u32 pb_EReserved[15];
+};
+
+#define IDNAME_PARTITION 0x50415254 /* "PART" */
+
+#define RDB_ALLOCATION_LIMIT 16
+
+#endif /* AFFS_HARDBLOCKS_H */
diff --git a/pfinet/linux-src/include/linux/amifd.h b/pfinet/linux-src/include/linux/amifd.h
new file mode 100644
index 00000000..491bdd86
--- /dev/null
+++ b/pfinet/linux-src/include/linux/amifd.h
@@ -0,0 +1,61 @@
+#ifndef _AMIFD_H
+#define _AMIFD_H
+
+/* Definitions for the Amiga floppy driver */
+
+#include <linux/fd.h>
+
+#define FD_MAX_UNITS 4 /* Max. Number of drives */
+#define FLOPPY_MAX_SECTORS 22 /* Max. Number of sectors per track */
+
+#ifndef ASSEMBLER
+
+struct fd_data_type {
+ char *name; /* description of data type */
+ int sects; /* sectors per track */
+#ifdef __STDC__
+ int (*read_fkt)(int);
+ void (*write_fkt)(int);
+#else
+ int (*read_fkt)(); /* read whole track */
+ void (*write_fkt)(); /* write whole track */
+#endif
+};
+
+/*
+** Floppy type descriptions
+*/
+
+struct fd_drive_type {
+ unsigned long code; /* code returned from drive */
+ char *name; /* description of drive */
+ unsigned int tracks; /* number of tracks */
+ unsigned int heads; /* number of heads */
+ unsigned int read_size; /* raw read size for one track */
+ unsigned int write_size; /* raw write size for one track */
+ unsigned int sect_mult; /* sectors and gap multiplier (HD = 2) */
+ unsigned int precomp1; /* start track for precomp 1 */
+ unsigned int precomp2; /* start track for precomp 2 */
+ unsigned int step_delay; /* time (in ms) for delay after step */
+ unsigned int settle_time; /* time to settle after dir change */
+ unsigned int side_time; /* time needed to change sides */
+};
+
+struct amiga_floppy_struct {
+ struct fd_drive_type *type; /* type of floppy for this unit */
+ struct fd_data_type *dtype; /* type of floppy for this unit */
+ int track; /* current track (-1 == unknown) */
+ unsigned char *trackbuf; /* current track (kmaloc()'d */
+
+ int blocks; /* total # blocks on disk */
+
+ int changed; /* true when not known */
+ int disk; /* disk in drive (-1 == unknown) */
+ int motor; /* true when motor is at speed */
+ int busy; /* true when drive is active */
+ int dirty; /* true when trackbuf is not on disk */
+ int status; /* current error code for unit */
+};
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/amifdreg.h b/pfinet/linux-src/include/linux/amifdreg.h
new file mode 100644
index 00000000..76188bf4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/amifdreg.h
@@ -0,0 +1,81 @@
+#ifndef _LINUX_AMIFDREG_H
+#define _LINUX_AMIFDREG_H
+
+/*
+** CIAAPRA bits (read only)
+*/
+
+#define DSKRDY (0x1<<5) /* disk ready when low */
+#define DSKTRACK0 (0x1<<4) /* head at track zero when low */
+#define DSKPROT (0x1<<3) /* disk protected when low */
+#define DSKCHANGE (0x1<<2) /* low when disk removed */
+
+/*
+** CIAAPRB bits (read/write)
+*/
+
+#define DSKMOTOR (0x1<<7) /* motor on when low */
+#define DSKSEL3 (0x1<<6) /* select drive 3 when low */
+#define DSKSEL2 (0x1<<5) /* select drive 2 when low */
+#define DSKSEL1 (0x1<<4) /* select drive 1 when low */
+#define DSKSEL0 (0x1<<3) /* select drive 0 when low */
+#define DSKSIDE (0x1<<2) /* side selection: 0 = upper, 1 = lower */
+#define DSKDIREC (0x1<<1) /* step direction: 0=in, 1=out (to trk 0) */
+#define DSKSTEP (0x1) /* pulse low to step head 1 track */
+
+/*
+** DSKBYTR bits (read only)
+*/
+
+#define DSKBYT (1<<15) /* register contains valid byte when set */
+#define DMAON (1<<14) /* disk DMA enabled */
+#define DISKWRITE (1<<13) /* disk write bit in DSKLEN enabled */
+#define WORDEQUAL (1<<12) /* DSKSYNC register match when true */
+/* bits 7-0 are data */
+
+/*
+** ADKCON/ADKCONR bits
+*/
+
+#ifndef SETCLR
+#define ADK_SETCLR (1<<15) /* control bit */
+#endif
+#define ADK_PRECOMP1 (1<<14) /* precompensation selection */
+#define ADK_PRECOMP0 (1<<13) /* 00=none, 01=140ns, 10=280ns, 11=500ns */
+#define ADK_MFMPREC (1<<12) /* 0=GCR precomp., 1=MFM precomp. */
+#define ADK_WORDSYNC (1<<10) /* enable DSKSYNC auto DMA */
+#define ADK_MSBSYNC (1<<9) /* when 1, enable sync on MSbit (for GCR) */
+#define ADK_FAST (1<<8) /* bit cell: 0=2us (GCR), 1=1us (MFM) */
+
+/*
+** DSKLEN bits
+*/
+
+#define DSKLEN_DMAEN (1<<15)
+#define DSKLEN_WRITE (1<<14)
+
+/*
+** INTENA/INTREQ bits
+*/
+
+#define DSKINDEX (0x1<<4) /* DSKINDEX bit */
+
+/*
+** Misc
+*/
+
+#define MFM_SYNC 0x4489 /* standard MFM sync value */
+
+/* Values for FD_COMMAND */
+#define FD_RECALIBRATE 0x07 /* move to track 0 */
+#define FD_SEEK 0x0F /* seek track */
+#define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */
+#define FD_WRITE 0xC5 /* write with MT, MFM */
+#define FD_SENSEI 0x08 /* Sense Interrupt Status */
+#define FD_SPECIFY 0x03 /* specify HUT etc */
+#define FD_FORMAT 0x4D /* format one track */
+#define FD_VERSION 0x10 /* get version code */
+#define FD_CONFIGURE 0x13 /* configure FIFO operation */
+#define FD_PERPENDICULAR 0x12 /* perpendicular r/w mode */
+
+#endif /* _LINUX_AMIFDREG_H */
diff --git a/pfinet/linux-src/include/linux/amigaffs.h b/pfinet/linux-src/include/linux/amigaffs.h
new file mode 100644
index 00000000..a6b16e06
--- /dev/null
+++ b/pfinet/linux-src/include/linux/amigaffs.h
@@ -0,0 +1,228 @@
+#ifndef AMIGAFFS_H
+#define AMIGAFFS_H
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+
+/* AmigaOS allows file names with up to 30 characters length.
+ * Names longer than that will be silently truncated. If you
+ * want to disallow this, comment out the following #define.
+ * Creating filesystem objects with longer names will then
+ * result in an error (ENAMETOOLONG).
+ */
+/*#define AFFS_NO_TRUNCATE */
+
+/* Ugly macros make the code more pretty. */
+
+#define GET_END_PTR(st,p,sz) ((st *)((char *)(p)+((sz)-sizeof(st))))
+#define AFFS_GET_HASHENTRY(data,hashkey) be32_to_cpu(((struct dir_front *)data)->hashtable[hashkey])
+#define AFFS_BLOCK(data,ino,blk) ((struct file_front *)data)->blocks[AFFS_I2HSIZE(ino)-1-(blk)]
+
+#define FILE_END(p,i) GET_END_PTR(struct file_end,p,AFFS_I2BSIZE(i))
+#define ROOT_END(p,i) GET_END_PTR(struct root_end,p,AFFS_I2BSIZE(i))
+#define DIR_END(p,i) GET_END_PTR(struct dir_end,p,AFFS_I2BSIZE(i))
+#define LINK_END(p,i) GET_END_PTR(struct hlink_end,p,AFFS_I2BSIZE(i))
+#define ROOT_END_S(p,s) GET_END_PTR(struct root_end,p,(s)->s_blocksize)
+#define DATA_FRONT(bh) ((struct data_front *)(bh)->b_data)
+#define DIR_FRONT(bh) ((struct dir_front *)(bh)->b_data)
+
+/* Only for easier debugging if need be */
+#define affs_bread bread
+#define affs_brelse brelse
+
+#ifdef __LITTLE_ENDIAN
+#define BO_EXBITS 0x18UL
+#elif defined(__BIG_ENDIAN)
+#define BO_EXBITS 0x00UL
+#else
+#error Endianness must be known for affs to work.
+#endif
+
+#define FS_OFS 0x444F5300
+#define FS_FFS 0x444F5301
+#define FS_INTLOFS 0x444F5302
+#define FS_INTLFFS 0x444F5303
+#define FS_DCOFS 0x444F5304
+#define FS_DCFFS 0x444F5305
+#define MUFS_FS 0x6d754653 /* 'muFS' */
+#define MUFS_OFS 0x6d754600 /* 'muF\0' */
+#define MUFS_FFS 0x6d754601 /* 'muF\1' */
+#define MUFS_INTLOFS 0x6d754602 /* 'muF\2' */
+#define MUFS_INTLFFS 0x6d754603 /* 'muF\3' */
+#define MUFS_DCOFS 0x6d754604 /* 'muF\4' */
+#define MUFS_DCFFS 0x6d754605 /* 'muF\5' */
+
+#define T_SHORT 2
+#define T_LIST 16
+#define T_DATA 8
+
+#define ST_LINKFILE -4
+#define ST_FILE -3
+#define ST_ROOT 1
+#define ST_USERDIR 2
+#define ST_SOFTLINK 3
+#define ST_LINKDIR 4
+
+struct root_front
+{
+ s32 primary_type;
+ s32 spare1[2];
+ s32 hash_size;
+ s32 spare2;
+ u32 checksum;
+ s32 hashtable[0];
+};
+
+struct root_end
+{
+ s32 bm_flag;
+ s32 bm_keys[25];
+ s32 bm_extend;
+ struct DateStamp dir_altered;
+ u8 disk_name[40];
+ struct DateStamp disk_altered;
+ struct DateStamp disk_made;
+ s32 spare1[3];
+ s32 secondary_type;
+};
+
+struct dir_front
+{
+ s32 primary_type;
+ s32 own_key;
+ s32 spare1[3];
+ u32 checksum;
+ s32 hashtable[0];
+};
+
+struct dir_end
+{
+ s32 spare1;
+ s16 owner_uid;
+ s16 owner_gid;
+ u32 protect;
+ s32 spare2;
+ u8 comment[92];
+ struct DateStamp created;
+ u8 dir_name[32];
+ s32 spare3[2];
+ s32 link_chain;
+ s32 spare4[5];
+ s32 hash_chain;
+ s32 parent;
+ s32 spare5;
+ s32 secondary_type;
+};
+
+struct file_front
+{
+ s32 primary_type;
+ s32 own_key;
+ s32 block_count;
+ s32 unknown1;
+ s32 first_data;
+ u32 checksum;
+ s32 blocks[0];
+};
+
+struct file_end
+{
+ s32 spare1;
+ s16 owner_uid;
+ s16 owner_gid;
+ u32 protect;
+ s32 byte_size;
+ u8 comment[92];
+ struct DateStamp created;
+ u8 file_name[32];
+ s32 spare2;
+ s32 original; /* not really in file_end */
+ s32 link_chain;
+ s32 spare3[5];
+ s32 hash_chain;
+ s32 parent;
+ s32 extension;
+ s32 secondary_type;
+};
+
+struct hlink_front
+{
+ s32 primary_type;
+ s32 own_key;
+ s32 spare1[3];
+ u32 checksum;
+};
+
+struct hlink_end
+{
+ s32 spare1;
+ s16 owner_uid;
+ s16 owner_gid;
+ u32 protect;
+ u8 comment[92];
+ struct DateStamp created;
+ u8 link_name[32];
+ s32 spare2;
+ s32 original;
+ s32 link_chain;
+ s32 spare3[5];
+ s32 hash_chain;
+ s32 parent;
+ s32 spare4;
+ s32 secondary_type;
+};
+
+struct slink_front
+{
+ s32 primary_type;
+ s32 own_key;
+ s32 spare1[3];
+ s32 checksum;
+ u8 symname[288]; /* depends on block size */
+};
+
+struct data_front
+{
+ s32 primary_type;
+ s32 header_key;
+ s32 sequence_number;
+ s32 data_size;
+ s32 next_data;
+ s32 checksum;
+ u8 data[488]; /* depends on block size */
+};
+
+/* Permission bits */
+
+#define FIBF_OTR_READ 0x8000
+#define FIBF_OTR_WRITE 0x4000
+#define FIBF_OTR_EXECUTE 0x2000
+#define FIBF_OTR_DELETE 0x1000
+#define FIBF_GRP_READ 0x0800
+#define FIBF_GRP_WRITE 0x0400
+#define FIBF_GRP_EXECUTE 0x0200
+#define FIBF_GRP_DELETE 0x0100
+
+#define FIBF_SCRIPT 0x0040
+#define FIBF_PURE 0x0020 /* no use under linux */
+#define FIBF_ARCHIVE 0x0010 /* never set, always cleared on write */
+#define FIBF_READ 0x0008 /* 0 means allowed */
+#define FIBF_WRITE 0x0004 /* 0 means allowed */
+#define FIBF_EXECUTE 0x0002 /* 0 means allowed, ignored under linux */
+#define FIBF_DELETE 0x0001 /* 0 means allowed */
+
+#define FIBF_OWNER 0x000F /* Bits pertaining to owner */
+
+#define AFFS_UMAYWRITE(prot) (((prot) & (FIBF_WRITE|FIBF_DELETE)) == (FIBF_WRITE|FIBF_DELETE))
+#define AFFS_UMAYREAD(prot) ((prot) & FIBF_READ)
+#define AFFS_UMAYEXECUTE(prot) ((prot) & FIBF_EXECUTE)
+#define AFFS_GMAYWRITE(prot) (((prot)&(FIBF_GRP_WRITE|FIBF_GRP_DELETE))==\
+ (FIBF_GRP_WRITE|FIBF_GRP_DELETE))
+#define AFFS_GMAYREAD(prot) ((prot) & FIBF_GRP_READ)
+#define AFFS_GMAYEXECUTE(prot) ((prot) & FIBF_EXECUTE)
+#define AFFS_OMAYWRITE(prot) (((prot)&(FIBF_OTR_WRITE|FIBF_OTR_DELETE))==\
+ (FIBF_OTR_WRITE|FIBF_OTR_DELETE))
+#define AFFS_OMAYREAD(prot) ((prot) & FIBF_OTR_READ)
+#define AFFS_OMAYEXECUTE(prot) ((prot) & FIBF_EXECUTE)
+
+#endif
diff --git a/pfinet/linux-src/include/linux/apm_bios.h b/pfinet/linux-src/include/linux/apm_bios.h
new file mode 100644
index 00000000..a478c0c6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/apm_bios.h
@@ -0,0 +1,143 @@
+#ifndef _LINUX_APM_H
+#define _LINUX_APM_H
+
+/*
+ * Include file for the interface to an APM BIOS
+ * Copyright 1994-1998 Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+typedef unsigned short apm_event_t;
+typedef unsigned short apm_eventinfo_t;
+
+#ifdef __KERNEL__
+
+#define APM_40 0x40
+#define APM_CS (APM_40 + 8)
+#define APM_CS_16 (APM_CS + 8)
+#define APM_DS (APM_CS_16 + 8)
+
+struct apm_bios_info {
+ unsigned short version;
+ unsigned short cseg;
+ unsigned long offset;
+ unsigned short cseg_16;
+ unsigned short dseg;
+ unsigned short flags;
+ unsigned short cseg_len;
+ unsigned short cseg_16_len;
+ unsigned short dseg_len;
+};
+
+ /* Results of APM Installation Check */
+#define APM_16_BIT_SUPPORT 0x0001
+#define APM_32_BIT_SUPPORT 0x0002
+#define APM_IDLE_SLOWS_CLOCK 0x0004
+#define APM_BIOS_DISABLED 0x0008
+#define APM_BIOS_DISENGAGED 0x0010
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS 20
+
+/*
+ * The per-file APM data
+ */
+struct apm_bios_struct {
+ int magic;
+ struct apm_bios_struct * next;
+ int suser;
+ int suspends_pending;
+ int standbys_pending;
+ int suspends_read;
+ int standbys_read;
+ int event_head;
+ int event_tail;
+ apm_event_t events[APM_MAX_EVENTS];
+};
+
+/*
+ * The magic number in apm_bios_struct
+ */
+#define APM_BIOS_MAGIC 0x4101
+
+/*
+ * in init/main.c
+ */
+extern struct apm_bios_info apm_bios_info;
+
+extern void apm_bios_init(void);
+extern void apm_setup(char *, int *);
+
+extern int apm_register_callback(int (*callback)(apm_event_t));
+extern void apm_unregister_callback(int (*callback)(apm_event_t));
+
+extern void apm_power_off(void);
+extern int apm_display_blank(void);
+extern int apm_display_unblank(void);
+
+#endif /* __KERNEL__ */
+
+/*
+ * Power states
+ */
+#define APM_STATE_READY 0x0000
+#define APM_STATE_STANDBY 0x0001
+#define APM_STATE_SUSPEND 0x0002
+#define APM_STATE_OFF 0x0003
+#define APM_STATE_BUSY 0x0004
+#define APM_STATE_REJECT 0x0005
+
+/*
+ * Events (results of Get PM Event)
+ */
+#define APM_SYS_STANDBY 0x0001
+#define APM_SYS_SUSPEND 0x0002
+#define APM_NORMAL_RESUME 0x0003
+#define APM_CRITICAL_RESUME 0x0004
+#define APM_LOW_BATTERY 0x0005
+#define APM_POWER_STATUS_CHANGE 0x0006
+#define APM_UPDATE_TIME 0x0007
+#define APM_CRITICAL_SUSPEND 0x0008
+#define APM_USER_STANDBY 0x0009
+#define APM_USER_SUSPEND 0x000a
+#define APM_STANDBY_RESUME 0x000b
+#define APM_CAPABILITY_CHANGE 0x000c
+
+/*
+ * Error codes
+ */
+#define APM_SUCCESS 0x00
+#define APM_DISABLED 0x01
+#define APM_CONNECTED 0x02
+#define APM_NOT_CONNECTED 0x03
+#define APM_16_CONNECTED 0x05
+#define APM_16_UNSUPPORTED 0x06
+#define APM_32_CONNECTED 0x07
+#define APM_32_UNSUPPORTED 0x08
+#define APM_BAD_DEVICE 0x09
+#define APM_BAD_PARAM 0x0a
+#define APM_NOT_ENGAGED 0x0b
+#define APM_BAD_FUNCTION 0x0c
+#define APM_RESUME_DISABLED 0x0d
+#define APM_BAD_STATE 0x60
+#define APM_NO_EVENTS 0x80
+#define APM_NOT_PRESENT 0x86
+
+/* ioctl operations */
+#include <linux/ioctl.h>
+
+#define APM_IOC_STANDBY _IO('A', 1)
+#define APM_IOC_SUSPEND _IO('A', 2)
+
+#endif /* LINUX_APM_H */
diff --git a/pfinet/linux-src/include/linux/arcdevice.h b/pfinet/linux-src/include/linux/arcdevice.h
new file mode 100644
index 00000000..b4df083e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/arcdevice.h
@@ -0,0 +1,354 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. NET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the ARCnet handlers.
+ *
+ * Version: $Id: arcdevice.h,v 1.3 1997/11/09 11:05:05 mj Exp $
+ *
+ * Authors: Avery Pennarun <apenwarr@bond.net>
+ * David Woodhouse <dwmw2@cam.ac.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#ifndef _LINUX_ARCDEVICE_H
+#define _LINUX_ARCDEVICE_H
+
+#include <linux/config.h>
+#include <linux/if_arcnet.h>
+
+#ifdef __KERNEL__
+
+#define ARC_20020 1
+#define ARC_RIM_I 2
+#define ARC_90xx 3
+#define ARC_90xx_IO 4
+
+#define MAX_ARCNET_DEVS 8
+
+
+/* The card sends the reconfiguration signal when it loses the connection to
+ * the rest of its network. It is a 'Hello, is anybody there?' cry. This
+ * usually happens when a new computer on the network is powered on or when
+ * the cable is broken.
+ *
+ * Define DETECT_RECONFIGS if you want to detect network reconfigurations.
+ * Recons may be a real nuisance on a larger ARCnet network; if you are a
+ * network administrator you probably would like to count them.
+ * Reconfigurations will be recorded in stats.tx_carrier_errors (the last
+ * field of the /proc/net/dev file).
+ *
+ * Define SHOW_RECONFIGS if you really want to see a log message whenever
+ * a RECON occurs.
+ */
+#define DETECT_RECONFIGS
+#undef SHOW_RECONFIGS
+
+
+/* RECON_THRESHOLD is the maximum number of RECON messages to receive within
+ * one minute before printing a "cabling problem" warning. You must have
+ * DETECT_RECONFIGS enabled if you want to use this. The default value
+ * should be fine.
+ *
+ * After that, a "cabling restored" message will be printed on the next IRQ
+ * if no RECON messages have been received for 10 seconds.
+ *
+ * Do not define RECON_THRESHOLD at all if you want to disable this feature.
+ */
+#define RECON_THRESHOLD 30
+
+
+/* Define this to the minimum "timeout" value. If a transmit takes longer
+ * than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large
+ * network, or one with heavy network traffic, this timeout may need to be
+ * increased. The larger it is, though, the longer it will be between
+ * necessary transmits - don't set this too large.
+ */
+#define TX_TIMEOUT (20*HZ/100)
+
+
+/* Display warnings about the driver being an ALPHA version.
+ */
+#undef ALPHA_WARNING
+
+
+/* New debugging bitflags: each option can be enabled individually.
+ *
+ * These can be set while the driver is running by typing:
+ * ifconfig arc0 down metric 1xxx HOSTNAME
+ * where 1xxx is 1000 + the debug level you want
+ * and HOSTNAME is your hostname/ip address
+ * and then resetting your routes.
+ *
+ * An ioctl() should be used for this instead, someday.
+ *
+ * Note: only debug flags included in the ARCNET_DEBUG_MAX define will
+ * actually be available. GCC will (at least, GCC 2.7.0 will) notice
+ * lines using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize
+ * them out.
+ */
+#define D_NORMAL 1 /* important operational info */
+#define D_EXTRA 2 /* useful, but non-vital information */
+#define D_INIT 4 /* show init/probe messages */
+#define D_INIT_REASONS 8 /* show reasons for discarding probes */
+/* debug levels below give LOTS of output during normal operation! */
+#define D_DURING 16 /* trace operations (including irq's) */
+#define D_TX 32 /* show tx packets */
+#define D_RX 64 /* show rx packets */
+#define D_SKB 128 /* show skb's */
+
+#ifndef ARCNET_DEBUG_MAX
+#define ARCNET_DEBUG_MAX (~0) /* enable ALL debug messages */
+#endif
+
+#ifndef ARCNET_DEBUG
+#define ARCNET_DEBUG (D_NORMAL|D_EXTRA)
+#endif
+extern int arcnet_debug;
+
+/* macros to simplify debug checking */
+#define BUGLVL(x) if ((ARCNET_DEBUG_MAX)&arcnet_debug&(x))
+#define BUGMSG2(x,msg,args...) do { BUGLVL(x) printk(msg, ## args); } while (0)
+#define BUGMSG(x,msg,args...) \
+ BUGMSG2(x,"%s%6s: " msg, \
+ x==D_NORMAL ? KERN_WARNING : \
+ x<=D_INIT_REASONS ? KERN_INFO : KERN_DEBUG , \
+ dev->name , ## args)
+
+
+#define SETMASK AINTMASK(lp->intmask)
+
+ /* Time needed to resetthe card - in jiffies. This works on my SMC
+ * PC100. I can't find a reference that tells me just how long I
+ * should wait.
+ */
+#define RESETtime (HZ * 3 / 10) /* reset */
+
+ /* these are the max/min lengths of packet data. (including
+ * ClientData header)
+ * note: packet sizes 250, 251, 252 are impossible (God knows why)
+ * so exception packets become necessary.
+ *
+ * These numbers are compared with the length of the full packet,
+ * including ClientData header.
+ */
+#define MTU 253 /* normal packet max size */
+#define MinTU 257 /* extended packet min size */
+#define XMTU 508 /* extended packet max size */
+
+ /* status/interrupt mask bit fields */
+#define TXFREEflag 0x01 /* transmitter available */
+#define TXACKflag 0x02 /* transmitted msg. ackd */
+#define RECONflag 0x04 /* system reconfigured */
+#define TESTflag 0x08 /* test flag */
+#define RESETflag 0x10 /* power-on-reset */
+#define RES1flag 0x20 /* reserved - usually set by jumper */
+#define RES2flag 0x40 /* reserved - usually set by jumper */
+#define NORXflag 0x80 /* receiver inhibited */
+
+ /* Flags used for IO-mapped memory operations */
+#define AUTOINCflag 0x40 /* Increase location with each access */
+#define IOMAPflag 0x02 /* (for 90xx) Use IO mapped memory, not mmap */
+#define ENABLE16flag 0x80 /* (for 90xx) Enable 16-bit mode */
+
+ /* in the command register, the following bits have these meanings:
+ * 0-2 command
+ * 3-4 page number (for enable rcv/xmt command)
+ * 7 receive broadcasts
+ */
+#define NOTXcmd 0x01 /* disable transmitter */
+#define NORXcmd 0x02 /* disable receiver */
+#define TXcmd 0x03 /* enable transmitter */
+#define RXcmd 0x04 /* enable receiver */
+#define CONFIGcmd 0x05 /* define configuration */
+#define CFLAGScmd 0x06 /* clear flags */
+#define TESTcmd 0x07 /* load test flags */
+
+ /* flags for "clear flags" command */
+#define RESETclear 0x08 /* power-on-reset */
+#define CONFIGclear 0x10 /* system reconfigured */
+
+ /* flags for "load test flags" command */
+#define TESTload 0x08 /* test flag (diagnostic) */
+
+ /* byte deposited into first address of buffers on reset */
+#define TESTvalue 0321 /* that's octal for 0xD1 :) */
+
+ /* for "enable receiver" command */
+#define RXbcasts 0x80 /* receive broadcasts */
+
+ /* flags for "define configuration" command */
+#define NORMALconf 0x00 /* 1-249 byte packets */
+#define EXTconf 0x08 /* 250-504 byte packets */
+
+ /* Starts receiving packets into recbuf.
+ */
+#define EnableReceiver() ACOMMAND(RXcmd|(recbuf<<3)|RXbcasts)
+
+
+
+#define JIFFER(time) for (delayval=jiffies+time; time_before(jiffies,delayval);) ;
+
+ /* a complete ARCnet packet */
+union ArcPacket
+{
+ struct archdr hardheader; /* the hardware header */
+ u_char raw[512]; /* raw packet info, incl ClientData */
+};
+
+
+ /* the "client data" header - RFC1201 information
+ * notice that this screws up if it's not an even number of bytes
+ * <sigh>
+ */
+struct ClientData
+{
+ /* data that's NOT part of real packet - we MUST get rid of it before
+ * actually sending!!
+ */
+ u_char saddr, /* Source address - needed for IPX */
+ daddr; /* Destination address */
+
+ /* data that IS part of real packet */
+ u_char protocol_id, /* ARC_P_IP, ARC_P_ARP, etc */
+ split_flag; /* for use with split packets */
+ u_short sequence; /* sequence number */
+};
+#define EXTRA_CLIENTDATA (sizeof(struct ClientData)-4)
+
+
+ /* the "client data" header - RFC1051 information
+ * this also screws up if it's not an even number of bytes
+ * <sigh again>
+ */
+struct S_ClientData
+{
+ /* data that's NOT part of real packet - we MUST get rid of it before
+ * actually sending!!
+ */
+ u_char saddr, /* Source address - needed for IPX */
+ daddr, /* Destination address */
+ junk; /* padding to make an even length */
+
+ /* data that IS part of real packet */
+ u_char protocol_id; /* ARC_P_IP, ARC_P_ARP, etc */
+};
+#define S_EXTRA_CLIENTDATA (sizeof(struct S_ClientData)-1)
+
+
+/* "Incoming" is information needed for each address that could be sending
+ * to us. Mostly for partially-received split packets.
+ */
+struct Incoming
+{
+ struct sk_buff *skb; /* packet data buffer */
+ unsigned char lastpacket, /* number of last packet (from 1) */
+ numpackets; /* number of packets in split */
+ u_short sequence; /* sequence number of assembly */
+};
+
+struct Outgoing
+{
+ struct sk_buff *skb; /* buffer from upper levels */
+ struct ClientData *hdr; /* clientdata of last packet */
+ u_char *data; /* pointer to data in packet */
+ short length, /* bytes total */
+ dataleft, /* bytes left */
+ segnum, /* segment being sent */
+ numsegs, /* number of segments */
+ seglen; /* length of segment */
+};
+
+
+struct arcnet_local {
+ struct net_device_stats stats;
+ u_short sequence; /* sequence number (incs with each packet) */
+ u_short aborted_seq;
+ u_char stationid, /* our 8-bit station address */
+ recbuf, /* receive buffer # (0 or 1) */
+ txbuf, /* transmit buffer # (2 or 3) */
+ txready, /* buffer where a packet is ready to send */
+ config, /* current value of CONFIG register */
+ timeout, /* Extended timeout for COM20020 */
+ backplane, /* Backplane flag for COM20020 */
+ setup, /* Contents of setup register */
+ intmask; /* current value of INTMASK register */
+ short intx, /* in TX routine? */
+ in_txhandler, /* in TX_IRQ handler? */
+ sending, /* transmit in progress? */
+ lastload_dest, /* can last loaded packet be acked? */
+ lasttrans_dest; /* can last TX'd packet be acked? */
+
+#if defined(DETECT_RECONFIGS) && defined(RECON_THRESHOLD)
+ time_t first_recon, /* time of "first" RECON message to count */
+ last_recon; /* time of most recent RECON */
+ int num_recons, /* number of RECONs between first and last. */
+ network_down; /* do we think the network is down? */
+#endif
+
+ struct timer_list timer; /* the timer interrupt struct */
+ struct Incoming incoming[256]; /* one from each address */
+ struct Outgoing outgoing; /* packet currently being sent */
+
+ int card_type;
+ char *card_type_str;
+
+ void (*inthandler) (struct device *dev);
+ int (*arcnet_reset) (struct device *dev, int reset_delay);
+ void (*asetmask) (struct device *dev, u_char mask);
+ void (*acommand) (struct device *dev, u_char command);
+ u_char (*astatus) (struct device *dev);
+ void (*en_dis_able_TX) (struct device *dev, int enable);
+ void (*prepare_tx)(struct device *dev,u_char *hdr,int hdrlen,
+ char *data,int length,int daddr,int exceptA, int offset);
+ void (*openclose_device)(int open);
+
+ struct device *adev; /* RFC1201 protocol device */
+
+ /* These are last to ensure that the chipset drivers don't depend on the
+ * CONFIG_ARCNET_ETH and CONFIG_ARCNET_1051 options.
+ */
+
+#ifdef CONFIG_ARCNET_ETH
+ struct device *edev; /* Ethernet-Encap device */
+#endif
+
+#ifdef CONFIG_ARCNET_1051
+ struct device *sdev; /* RFC1051 protocol device */
+#endif
+};
+
+/* Functions exported by arcnet.c
+ */
+
+#if ARCNET_DEBUG_MAX & D_SKB
+extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
+ char *desc);
+#else
+#define arcnet_dump_skb(dev,skb,desc) ;
+#endif
+
+#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
+extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
+ char *desc);
+#else
+#define arcnet_dump_packet(dev,buffer,ext,desc) ;
+#endif
+
+extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
+extern void arcnet_makename(char *device);
+extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
+extern void arcnet_setup(struct device *dev);
+extern int arcnet_go_tx(struct device *dev,int enable_irq);
+extern void arcnetA_continue_tx(struct device *dev);
+extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
+extern void arcnet_use_count(int open);
+
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_ARCDEVICE_H */
diff --git a/pfinet/linux-src/include/linux/atalk.h b/pfinet/linux-src/include/linux/atalk.h
new file mode 100644
index 00000000..e9d20979
--- /dev/null
+++ b/pfinet/linux-src/include/linux/atalk.h
@@ -0,0 +1,180 @@
+/*
+ * AppleTalk networking structures
+ *
+ * The following are directly referenced from the University Of Michigan
+ * netatalk for compatibility reasons.
+ */
+
+#ifndef __LINUX_ATALK_H__
+#define __LINUX_ATALK_H__
+
+#define ATPORT_FIRST 1
+#define ATPORT_RESERVED 128
+#define ATPORT_LAST 254 /* 254 is only legal on localtalk */
+#define ATADDR_ANYNET (__u16)0
+#define ATADDR_ANYNODE (__u8)0
+#define ATADDR_ANYPORT (__u8)0
+#define ATADDR_BCAST (__u8)255
+#define DDP_MAXSZ 587
+#define DDP_MAXHOPS 15 /* 4 bits of hop counter */
+
+#define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0)
+
+struct at_addr
+{
+ __u16 s_net;
+ __u8 s_node;
+};
+
+struct sockaddr_at
+{
+ sa_family_t sat_family;
+ __u8 sat_port;
+ struct at_addr sat_addr;
+ char sat_zero[ 8 ];
+};
+
+struct netrange
+{
+ __u8 nr_phase;
+ __u16 nr_firstnet;
+ __u16 nr_lastnet;
+};
+
+struct atalk_route
+{
+ struct device *dev;
+ struct at_addr target;
+ struct at_addr gateway;
+ int flags;
+ struct atalk_route *next;
+};
+
+struct atalk_iface
+{
+ struct device *dev;
+ struct at_addr address; /* Our address */
+ int status; /* What are we doing? */
+#define ATIF_PROBE 1 /* Probing for an address */
+#define ATIF_PROBE_FAIL 2 /* Probe collided */
+ struct netrange nets; /* Associated direct netrange */
+ struct atalk_iface *next;
+};
+
+struct atalk_sock
+{
+ unsigned short dest_net;
+ unsigned short src_net;
+ unsigned char dest_node;
+ unsigned char src_node;
+ unsigned char dest_port;
+ unsigned char src_port;
+};
+
+#ifdef __KERNEL__
+
+#include <asm/byteorder.h>
+
+struct ddpehdr
+{
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ __u16 deh_len:10, deh_hops:4, deh_pad:2;
+#else
+ __u16 deh_pad:2, deh_hops:4, deh_len:10;
+#endif
+ __u16 deh_sum;
+ __u16 deh_dnet;
+ __u16 deh_snet;
+ __u8 deh_dnode;
+ __u8 deh_snode;
+ __u8 deh_dport;
+ __u8 deh_sport;
+ /* And netatalk apps expect to stick the type in themselves */
+};
+
+/*
+ * Don't drop the struct into the struct above. You'll get some
+ * surprise padding.
+ */
+
+struct ddpebits
+{
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ __u16 deh_len:10, deh_hops:4, deh_pad:2;
+#else
+ __u16 deh_pad:2, deh_hops:4, deh_len:10;
+#endif
+};
+
+/*
+ * Short form header
+ */
+
+struct ddpshdr
+{
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ __u16 dsh_len:10, dsh_pad:6;
+#else
+ __u16 dsh_pad:6, dsh_len:10;
+#endif
+ __u8 dsh_dport;
+ __u8 dsh_sport;
+ /* And netatalk apps expect to stick the type in themselves */
+};
+
+/* AppleTalk AARP headers */
+
+struct elapaarp
+{
+ __u16 hw_type;
+#define AARP_HW_TYPE_ETHERNET 1
+#define AARP_HW_TYPE_TOKENRING 2
+ __u16 pa_type;
+ __u8 hw_len;
+ __u8 pa_len;
+#define AARP_PA_ALEN 4
+ __u16 function;
+#define AARP_REQUEST 1
+#define AARP_REPLY 2
+#define AARP_PROBE 3
+ __u8 hw_src[ETH_ALEN] __attribute__ ((packed));
+ __u8 pa_src_zero __attribute__ ((packed));
+ __u16 pa_src_net __attribute__ ((packed));
+ __u8 pa_src_node __attribute__ ((packed));
+ __u8 hw_dst[ETH_ALEN] __attribute__ ((packed));
+ __u8 pa_dst_zero __attribute__ ((packed));
+ __u16 pa_dst_net __attribute__ ((packed));
+ __u8 pa_dst_node __attribute__ ((packed));
+};
+
+#define AARP_EXPIRY_TIME (5*60*HZ) /* Not specified - how long till we drop a resolved entry */
+#define AARP_HASH_SIZE 16 /* Size of hash table */
+#define AARP_TICK_TIME (HZ/5) /* Fast retransmission timer when resolving */
+#define AARP_RETRANSMIT_LIMIT 10 /* Send 10 requests then give up (2 seconds) */
+#define AARP_RESOLVE_TIME (10*HZ) /* Some value bigger than total retransmit time + a bit for last reply to appear and to stop continual requests */
+
+extern struct datalink_proto *ddp_dl, *aarp_dl;
+extern void aarp_proto_init(void);
+/* Inter module exports */
+
+/*
+ * Give a device find its atif control structure
+ */
+
+extern __inline__ struct atalk_iface *atalk_find_dev(struct device *dev)
+{
+ return dev->atalk_ptr;
+}
+
+extern struct at_addr *atalk_find_dev_addr(struct device *dev);
+extern struct device *atrtr_get_dev(struct at_addr *sa);
+extern int aarp_send_ddp(struct device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr);
+extern void aarp_send_probe(struct device *dev, struct at_addr *addr);
+extern void aarp_device_down(struct device *dev);
+
+#ifdef MODULE
+extern void aarp_cleanup_module(void);
+#endif /* MODULE */
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_ATALK_H__ */
diff --git a/pfinet/linux-src/include/linux/atari_rootsec.h b/pfinet/linux-src/include/linux/atari_rootsec.h
new file mode 100644
index 00000000..09745f7a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/atari_rootsec.h
@@ -0,0 +1,34 @@
+#ifndef _LINUX_ATARI_ROOTSEC_H
+#define _LINUX_ATARI_ROOTSEC_H
+
+/*
+ * linux/include/linux/atari_rootsec.h
+ * definitions for Atari Rootsector layout
+ * by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de)
+ *
+ * modified for ICD/Supra partitioning scheme restricted to at most 12
+ * partitions
+ * by Guenther Kelleter (guenther@pool.informatik.rwth-aachen.de)
+ */
+
+struct partition_info
+{
+ u_char flg; /* bit 0: active; bit 7: bootable */
+ char id[3]; /* "GEM", "BGM", "XGM", or other */
+ u32 st; /* start of partition */
+ u32 siz; /* length of partition */
+};
+
+struct rootsector
+{
+ char unused[0x156]; /* room for boot code */
+ struct partition_info icdpart[8]; /* info for ICD-partitions 5..12 */
+ char unused2[0xc];
+ u32 hd_siz; /* size of disk in blocks */
+ struct partition_info part[4];
+ u32 bsl_st; /* start of bad sector list */
+ u32 bsl_cnt; /* length of bad sector list */
+ u16 checksum; /* checksum for bootable disks */
+} __attribute__ ((__packed__));
+
+#endif /* _LINUX_ATARI_ROOTSEC_H */
diff --git a/pfinet/linux-src/include/linux/auto_fs.h b/pfinet/linux-src/include/linux/auto_fs.h
new file mode 100644
index 00000000..9a0ddd6c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/auto_fs.h
@@ -0,0 +1,83 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * linux/include/linux/auto_fs.h
+ *
+ * Copyright 1997 Transmeta Corporation - All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+
+#ifndef _LINUX_AUTO_FS_H
+#define _LINUX_AUTO_FS_H
+
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/limits.h>
+#include <linux/ioctl.h>
+#include <asm/types.h>
+
+#define AUTOFS_PROTO_VERSION 3
+
+/*
+ * Architectures where both 32- and 64-bit binaries can be executed
+ * on 64-bit kernels need this. This keeps the structure format
+ * uniform, and makes sure the wait_queue_token isn't too big to be
+ * passed back down to the kernel.
+ *
+ * This assumes that on these architectures:
+ * mode 32 bit 64 bit
+ * -------------------------
+ * int 32 bit 32 bit
+ * long 32 bit 64 bit
+ *
+ * If so, 32-bit user-space code should be backwards compatible.
+ */
+
+#if defined(__sparc__) || defined(__mips__)
+typedef unsigned int autofs_wqt_t;
+#else
+typedef unsigned long autofs_wqt_t;
+#endif
+
+enum autofs_packet_type {
+ autofs_ptype_missing, /* Missing entry (mount request) */
+ autofs_ptype_expire, /* Expire entry (umount request) */
+};
+
+struct autofs_packet_hdr {
+ int proto_version; /* Protocol version */
+ enum autofs_packet_type type; /* Type of packet */
+};
+
+struct autofs_packet_missing {
+ struct autofs_packet_hdr hdr;
+ autofs_wqt_t wait_queue_token;
+ int len;
+ char name[NAME_MAX+1];
+};
+
+struct autofs_packet_expire {
+ struct autofs_packet_hdr hdr;
+ int len;
+ char name[NAME_MAX+1];
+};
+
+#define AUTOFS_IOC_READY _IO(0x93,0x60)
+#define AUTOFS_IOC_FAIL _IO(0x93,0x61)
+#define AUTOFS_IOC_CATATONIC _IO(0x93,0x62)
+#define AUTOFS_IOC_PROTOVER _IOR(0x93,0x63,int)
+#define AUTOFS_IOC_SETTIMEOUT _IOWR(0x93,0x64,unsigned long)
+#define AUTOFS_IOC_EXPIRE _IOR(0x93,0x65,struct autofs_packet_expire)
+
+#ifdef __KERNEL__
+
+/* Init function */
+int init_autofs_fs(void);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_AUTO_FS_H */
diff --git a/pfinet/linux-src/include/linux/awe_voice.h b/pfinet/linux-src/include/linux/awe_voice.h
new file mode 100644
index 00000000..aed60f5c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/awe_voice.h
@@ -0,0 +1,524 @@
+/*
+ * sound/awe_voice.h
+ *
+ * Voice information definitions for the low level driver for the
+ * AWE32/SB32/AWE64 wave table synth.
+ * version 0.4.3; Feb. 1, 1999
+ *
+ * Copyright (C) 1996-1999 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef AWE_VOICE_H
+#define AWE_VOICE_H
+
+#ifndef SAMPLE_TYPE_AWE32
+#define SAMPLE_TYPE_AWE32 0x20
+#endif
+
+#ifndef _PATCHKEY
+#define _PATCHKEY(id) ((id<<8)|0xfd)
+#endif
+
+/*----------------------------------------------------------------
+ * patch information record
+ *----------------------------------------------------------------*/
+
+/* patch interface header: 16 bytes */
+typedef struct awe_patch_info {
+ short key; /* use AWE_PATCH here */
+#define AWE_PATCH _PATCHKEY(0x07)
+
+ short device_no; /* synthesizer number */
+ unsigned short sf_id; /* file id (should be zero) */
+ short optarg; /* optional argument */
+ int len; /* data length (without this header) */
+
+ short type; /* patch operation type */
+#define AWE_LOAD_INFO 0 /* awe_voice_rec */
+#define AWE_LOAD_DATA 1 /* awe_sample_info */
+#define AWE_OPEN_PATCH 2 /* awe_open_parm */
+#define AWE_CLOSE_PATCH 3 /* none */
+#define AWE_UNLOAD_PATCH 4 /* none */
+#define AWE_REPLACE_DATA 5 /* awe_sample_info (optarg=#channels)*/
+#define AWE_MAP_PRESET 6 /* awe_voice_map */
+/*#define AWE_PROBE_INFO 7*/ /* awe_voice_map (pat only) */
+#define AWE_PROBE_DATA 8 /* optarg=sample */
+#define AWE_LOAD_CHORUS_FX 0x10 /* awe_chorus_fx_rec (optarg=mode) */
+#define AWE_LOAD_REVERB_FX 0x11 /* awe_reverb_fx_rec (optarg=mode) */
+
+ short reserved; /* word alignment data */
+
+ /* the actual patch data begins after this */
+#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
+ char data[0];
+#endif
+} awe_patch_info;
+
+/*#define AWE_PATCH_INFO_SIZE 16*/
+#define AWE_PATCH_INFO_SIZE sizeof(awe_patch_info)
+
+
+/*----------------------------------------------------------------
+ * open patch
+ *----------------------------------------------------------------*/
+
+#define AWE_PATCH_NAME_LEN 32
+
+typedef struct _awe_open_parm {
+ unsigned short type; /* sample type */
+#define AWE_PAT_TYPE_MISC 0
+#define AWE_PAT_TYPE_GM 1
+#define AWE_PAT_TYPE_GS 2
+#define AWE_PAT_TYPE_MT32 3
+#define AWE_PAT_TYPE_XG 4
+#define AWE_PAT_TYPE_SFX 5
+#define AWE_PAT_TYPE_GUS 6
+#define AWE_PAT_TYPE_MAP 7
+
+#define AWE_PAT_LOCKED 0x100 /* lock the samples */
+#define AWE_PAT_SHARED 0x200 /* sample is shared */
+
+ short reserved;
+ char name[AWE_PATCH_NAME_LEN];
+} awe_open_parm;
+
+/*#define AWE_OPEN_PARM_SIZE 28*/
+#define AWE_OPEN_PARM_SIZE sizeof(awe_open_parm)
+
+
+/*----------------------------------------------------------------
+ * raw voice information record
+ *----------------------------------------------------------------*/
+
+/* wave table envelope & effect parameters to control EMU8000 */
+typedef struct _awe_voice_parm {
+ unsigned short moddelay; /* modulation delay (0x8000) */
+ unsigned short modatkhld; /* modulation attack & hold time (0x7f7f) */
+ unsigned short moddcysus; /* modulation decay & sustain (0x7f7f) */
+ unsigned short modrelease; /* modulation release time (0x807f) */
+ short modkeyhold, modkeydecay; /* envelope change per key (not used) */
+ unsigned short voldelay; /* volume delay (0x8000) */
+ unsigned short volatkhld; /* volume attack & hold time (0x7f7f) */
+ unsigned short voldcysus; /* volume decay & sustain (0x7f7f) */
+ unsigned short volrelease; /* volume release time (0x807f) */
+ short volkeyhold, volkeydecay; /* envelope change per key (not used) */
+ unsigned short lfo1delay; /* LFO1 delay (0x8000) */
+ unsigned short lfo2delay; /* LFO2 delay (0x8000) */
+ unsigned short pefe; /* modulation pitch & cutoff (0x0000) */
+ unsigned short fmmod; /* LFO1 pitch & cutoff (0x0000) */
+ unsigned short tremfrq; /* LFO1 volume & freq (0x0000) */
+ unsigned short fm2frq2; /* LFO2 pitch & freq (0x0000) */
+ unsigned char cutoff; /* initial cutoff (0xff) */
+ unsigned char filterQ; /* initial filter Q [0-15] (0x0) */
+ unsigned char chorus; /* chorus send (0x00) */
+ unsigned char reverb; /* reverb send (0x00) */
+ unsigned short reserved[4]; /* not used */
+} awe_voice_parm;
+
+typedef struct _awe_voice_parm_block {
+ unsigned short moddelay; /* modulation delay (0x8000) */
+ unsigned char modatk, modhld;
+ unsigned char moddcy, modsus;
+ unsigned char modrel, moddummy;
+ short modkeyhold, modkeydecay; /* envelope change per key (not used) */
+ unsigned short voldelay; /* volume delay (0x8000) */
+ unsigned char volatk, volhld;
+ unsigned char voldcy, volsus;
+ unsigned char volrel, voldummy;
+ short volkeyhold, volkeydecay; /* envelope change per key (not used) */
+ unsigned short lfo1delay; /* LFO1 delay (0x8000) */
+ unsigned short lfo2delay; /* LFO2 delay (0x8000) */
+ unsigned char env1fc, env1pit;
+ unsigned char lfo1fc, lfo1pit;
+ unsigned char lfo1freq, lfo1vol;
+ unsigned char lfo2freq, lfo2pit;
+ unsigned char cutoff; /* initial cutoff (0xff) */
+ unsigned char filterQ; /* initial filter Q [0-15] (0x0) */
+ unsigned char chorus; /* chorus send (0x00) */
+ unsigned char reverb; /* reverb send (0x00) */
+ unsigned short reserved[4]; /* not used */
+} awe_voice_parm_block;
+
+#define AWE_VOICE_PARM_SIZE 48
+
+
+/* wave table parameters: 92 bytes */
+typedef struct _awe_voice_info {
+ unsigned short sf_id; /* file id (should be zero) */
+ unsigned short sample; /* sample id */
+ int start, end; /* sample offset correction */
+ int loopstart, loopend; /* loop offset correction */
+ short rate_offset; /* sample rate pitch offset */
+ unsigned short mode; /* sample mode */
+#define AWE_MODE_ROMSOUND 0x8000
+#define AWE_MODE_STEREO 1
+#define AWE_MODE_LOOPING 2
+#define AWE_MODE_NORELEASE 4 /* obsolete */
+#define AWE_MODE_INIT_PARM 8
+
+ short root; /* midi root key */
+ short tune; /* pitch tuning (in cents) */
+ char low, high; /* key note range */
+ char vellow, velhigh; /* velocity range */
+ char fixkey, fixvel; /* fixed key, velocity */
+ char pan, fixpan; /* panning, fixed panning */
+ short exclusiveClass; /* exclusive class (0 = none) */
+ unsigned char amplitude; /* sample volume (127 max) */
+ unsigned char attenuation; /* attenuation (0.375dB) */
+ short scaleTuning; /* pitch scale tuning(%), normally 100 */
+ awe_voice_parm parm; /* voice envelope parameters */
+ short index; /* internal index (set by driver) */
+} awe_voice_info;
+
+/*#define AWE_VOICE_INFO_SIZE 92*/
+#define AWE_VOICE_INFO_SIZE sizeof(awe_voice_info)
+
+/*----------------------------------------------------------------*/
+
+/* The info entry of awe_voice_rec is changed from 0 to 1
+ * for some compilers refusing zero size array.
+ * Due to this change, sizeof(awe_voice_rec) becomes different
+ * from older versions.
+ * Use AWE_VOICE_REC_SIZE instead.
+ */
+
+/* instrument info header: 4 bytes */
+typedef struct _awe_voice_rec_hdr {
+ unsigned char bank; /* midi bank number */
+ unsigned char instr; /* midi preset number */
+ char nvoices; /* number of voices */
+ char write_mode; /* write mode; normally 0 */
+#define AWE_WR_APPEND 0 /* append anyway */
+#define AWE_WR_EXCLUSIVE 1 /* skip if already exists */
+#define AWE_WR_REPLACE 2 /* replace if already exists */
+} awe_voice_rec_hdr;
+
+/*#define AWE_VOICE_REC_SIZE 4*/
+#define AWE_VOICE_REC_SIZE sizeof(awe_voice_rec_hdr)
+
+/* the standard patch structure for one sample */
+typedef struct _awe_voice_rec_patch {
+ awe_patch_info patch;
+ awe_voice_rec_hdr hdr;
+ awe_voice_info info;
+} awe_voice_rec_patch;
+
+
+/* obsolete data type */
+#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
+#define AWE_INFOARRAY_SIZE 0
+#else
+#define AWE_INFOARRAY_SIZE 1
+#endif
+
+typedef struct _awe_voice_rec {
+ unsigned char bank; /* midi bank number */
+ unsigned char instr; /* midi preset number */
+ short nvoices; /* number of voices */
+ /* voice information follows here */
+ awe_voice_info info[AWE_INFOARRAY_SIZE];
+} awe_voice_rec;
+
+
+/*----------------------------------------------------------------
+ * sample wave information
+ *----------------------------------------------------------------*/
+
+/* wave table sample header: 32 bytes */
+typedef struct awe_sample_info {
+ unsigned short sf_id; /* file id (should be zero) */
+ unsigned short sample; /* sample id */
+ int start, end; /* start & end offset */
+ int loopstart, loopend; /* loop start & end offset */
+ int size; /* size (0 = ROM) */
+ short checksum_flag; /* use check sum = 1 */
+ unsigned short mode_flags; /* mode flags */
+#define AWE_SAMPLE_8BITS 1 /* wave data is 8bits */
+#define AWE_SAMPLE_UNSIGNED 2 /* wave data is unsigned */
+#define AWE_SAMPLE_NO_BLANK 4 /* no blank loop is attached */
+#define AWE_SAMPLE_SINGLESHOT 8 /* single-shot w/o loop */
+#define AWE_SAMPLE_BIDIR_LOOP 16 /* bidirectional looping */
+#define AWE_SAMPLE_STEREO_LEFT 32 /* stereo left sound */
+#define AWE_SAMPLE_STEREO_RIGHT 64 /* stereo right sound */
+#define AWE_SAMPLE_REVERSE_LOOP 128 /* reverse looping */
+ unsigned int checksum; /* check sum */
+#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
+ unsigned short data[0]; /* sample data follows here */
+#endif
+} awe_sample_info;
+
+/*#define AWE_SAMPLE_INFO_SIZE 32*/
+#define AWE_SAMPLE_INFO_SIZE sizeof(awe_sample_info)
+
+
+/*----------------------------------------------------------------
+ * voice preset mapping
+ *----------------------------------------------------------------*/
+
+typedef struct awe_voice_map {
+ int map_bank, map_instr, map_key; /* key = -1 means all keys */
+ int src_bank, src_instr, src_key;
+} awe_voice_map;
+
+#define AWE_VOICE_MAP_SIZE sizeof(awe_voice_map)
+
+
+/*----------------------------------------------------------------
+ * awe hardware controls
+ *----------------------------------------------------------------*/
+
+#define _AWE_DEBUG_MODE 0x00
+#define _AWE_REVERB_MODE 0x01
+#define _AWE_CHORUS_MODE 0x02
+#define _AWE_REMOVE_LAST_SAMPLES 0x03
+#define _AWE_INITIALIZE_CHIP 0x04
+#define _AWE_SEND_EFFECT 0x05
+#define _AWE_TERMINATE_CHANNEL 0x06
+#define _AWE_TERMINATE_ALL 0x07
+#define _AWE_INITIAL_VOLUME 0x08
+#define _AWE_INITIAL_ATTEN _AWE_INITIAL_VOLUME
+#define _AWE_RESET_CHANNEL 0x09
+#define _AWE_CHANNEL_MODE 0x0a
+#define _AWE_DRUM_CHANNELS 0x0b
+#define _AWE_MISC_MODE 0x0c
+#define _AWE_RELEASE_ALL 0x0d
+#define _AWE_NOTEOFF_ALL 0x0e
+#define _AWE_CHN_PRESSURE 0x0f
+/*#define _AWE_GET_CURRENT_MODE 0x10*/
+#define _AWE_EQUALIZER 0x11
+/*#define _AWE_GET_MISC_MODE 0x12*/
+/*#define _AWE_GET_FONTINFO 0x13*/
+
+#define _AWE_MODE_FLAG 0x80
+#define _AWE_COOKED_FLAG 0x40 /* not supported */
+#define _AWE_MODE_VALUE_MASK 0x3F
+
+/*----------------------------------------------------------------*/
+
+#define _AWE_SET_CMD(p,dev,voice,cmd,p1,p2) \
+{((char*)(p))[0] = SEQ_PRIVATE;\
+ ((char*)(p))[1] = dev;\
+ ((char*)(p))[2] = _AWE_MODE_FLAG|(cmd);\
+ ((char*)(p))[3] = voice;\
+ ((unsigned short*)(p))[2] = p1;\
+ ((unsigned short*)(p))[3] = p2;}
+
+/* buffered access */
+#define _AWE_CMD(dev, voice, cmd, p1, p2) \
+{_SEQ_NEEDBUF(8);\
+ _AWE_SET_CMD(_seqbuf + _seqbufptr, dev, voice, cmd, p1, p2);\
+ _SEQ_ADVBUF(8);}
+
+/* direct access */
+#define _AWE_CMD_NOW(seqfd,dev,voice,cmd,p1,p2) \
+{struct seq_event_rec tmp;\
+ _AWE_SET_CMD(&tmp, dev, voice, cmd, p1, p2);\
+ ioctl(seqfd, SNDCTL_SEQ_OUTOFBAND, &tmp);}
+
+/*----------------------------------------------------------------*/
+
+/* set debugging mode */
+#define AWE_DEBUG_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0)
+/* set reverb mode; from 0 to 7 */
+#define AWE_REVERB_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0)
+/* set chorus mode; from 0 to 7 */
+#define AWE_CHORUS_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0)
+
+/* reset channel */
+#define AWE_RESET_CHANNEL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 0, 0)
+#define AWE_RESET_CONTROL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 1, 0)
+
+/* send an effect to all layers */
+#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value)
+#define AWE_ADD_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x80),value)
+#define AWE_UNSET_EFFECT(dev,voice,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x40),0)
+/* send an effect to a layer */
+#define AWE_SEND_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)),value)
+#define AWE_ADD_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x80),value)
+#define AWE_UNSET_LAYER_EFFECT(dev,voice,layer,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x40),0)
+
+/* terminate sound on the channel/voice */
+#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0)
+/* terminate all sounds */
+#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0)
+/* release all sounds (w/o sustain effect) */
+#define AWE_RELEASE_ALL(dev) _AWE_CMD(dev, 0, _AWE_RELEASE_ALL, 0, 0)
+/* note off all sounds (w sustain effect) */
+#define AWE_NOTEOFF_ALL(dev) _AWE_CMD(dev, 0, _AWE_NOTEOFF_ALL, 0, 0)
+
+/* set initial attenuation */
+#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0)
+#define AWE_INITIAL_ATTEN AWE_INITIAL_VOLUME
+/* relative attenuation */
+#define AWE_SET_ATTEN(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 1)
+
+/* set channel playing mode; mode=0/1/2 */
+#define AWE_SET_CHANNEL_MODE(dev,mode) _AWE_CMD(dev, 0, _AWE_CHANNEL_MODE, mode, 0)
+#define AWE_PLAY_INDIRECT 0 /* indirect voice mode (default) */
+#define AWE_PLAY_MULTI 1 /* multi note voice mode */
+#define AWE_PLAY_DIRECT 2 /* direct single voice mode */
+#define AWE_PLAY_MULTI2 3 /* sequencer2 mode; used internally */
+
+/* set drum channel mask; channels is 32bit long value */
+#define AWE_DRUM_CHANNELS(dev,channels) _AWE_CMD(dev, 0, _AWE_DRUM_CHANNELS, ((channels) & 0xffff), ((channels) >> 16))
+
+/* set bass and treble control; values are from 0 to 11 */
+#define AWE_EQUALIZER(dev,bass,treble) _AWE_CMD(dev, 0, _AWE_EQUALIZER, bass, treble)
+
+/* remove last loaded samples */
+#define AWE_REMOVE_LAST_SAMPLES(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0)
+/* initialize emu8000 chip */
+#define AWE_INITIALIZE_CHIP(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_INITIALIZE_CHIP, 0, 0)
+
+/* set miscellaneous modes; meta command */
+#define AWE_MISC_MODE(dev,mode,value) _AWE_CMD(dev, 0, _AWE_MISC_MODE, mode, value)
+/* exclusive sound off; 1=off */
+#define AWE_EXCLUSIVE_SOUND(dev,mode) AWE_MISC_MODE(dev,AWE_MD_EXCLUSIVE_SOUND,mode)
+/* default GUS bank number */
+#define AWE_SET_GUS_BANK(dev,bank) AWE_MISC_MODE(dev,AWE_MD_GUS_BANK,bank)
+/* change panning position in realtime; 0=don't 1=do */
+#define AWE_REALTIME_PAN(dev,mode) AWE_MISC_MODE(dev,AWE_MD_REALTIME_PAN,mode)
+
+/* extended pressure controls; not portable with other sound drivers */
+#define AWE_KEY_PRESSURE(dev,ch,note,vel) SEQ_START_NOTE(dev,ch,(note)+128,vel)
+#define AWE_CHN_PRESSURE(dev,ch,vel) _AWE_CMD(dev,ch,_AWE_CHN_PRESSURE,vel,0)
+
+/*----------------------------------------------------------------*/
+
+/* reverb mode parameters */
+#define AWE_REVERB_ROOM1 0
+#define AWE_REVERB_ROOM2 1
+#define AWE_REVERB_ROOM3 2
+#define AWE_REVERB_HALL1 3
+#define AWE_REVERB_HALL2 4
+#define AWE_REVERB_PLATE 5
+#define AWE_REVERB_DELAY 6
+#define AWE_REVERB_PANNINGDELAY 7
+#define AWE_REVERB_PREDEFINED 8
+/* user can define reverb modes up to 32 */
+#define AWE_REVERB_NUMBERS 32
+
+typedef struct awe_reverb_fx_rec {
+ unsigned short parms[28];
+} awe_reverb_fx_rec;
+
+/*----------------------------------------------------------------*/
+
+/* chorus mode parameters */
+#define AWE_CHORUS_1 0
+#define AWE_CHORUS_2 1
+#define AWE_CHORUS_3 2
+#define AWE_CHORUS_4 3
+#define AWE_CHORUS_FEEDBACK 4
+#define AWE_CHORUS_FLANGER 5
+#define AWE_CHORUS_SHORTDELAY 6
+#define AWE_CHORUS_SHORTDELAY2 7
+#define AWE_CHORUS_PREDEFINED 8
+/* user can define chorus modes up to 32 */
+#define AWE_CHORUS_NUMBERS 32
+
+typedef struct awe_chorus_fx_rec {
+ unsigned short feedback; /* feedback level (0xE600-0xE6FF) */
+ unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */
+ unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */
+ unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
+ unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */
+} awe_chorus_fx_rec;
+
+/*----------------------------------------------------------------*/
+
+/* misc mode types */
+enum {
+/* 0*/ AWE_MD_EXCLUSIVE_OFF, /* obsolete */
+/* 1*/ AWE_MD_EXCLUSIVE_ON, /* obsolete */
+/* 2*/ AWE_MD_VERSION, /* read only */
+/* 3*/ AWE_MD_EXCLUSIVE_SOUND, /* 0/1: exclusive note on (default=1) */
+/* 4*/ AWE_MD_REALTIME_PAN, /* 0/1: do realtime pan change (default=1) */
+/* 5*/ AWE_MD_GUS_BANK, /* bank number for GUS patches (default=0) */
+/* 6*/ AWE_MD_KEEP_EFFECT, /* 0/1: keep effect values, (default=0) */
+/* 7*/ AWE_MD_ZERO_ATTEN, /* attenuation of max volume (default=32) */
+/* 8*/ AWE_MD_CHN_PRIOR, /* 0/1: set MIDI channel priority mode (default=1) */
+/* 9*/ AWE_MD_MOD_SENSE, /* integer: modwheel sensitivity (def=18) */
+/*10*/ AWE_MD_DEF_PRESET, /* integer: default preset number (def=0) */
+/*11*/ AWE_MD_DEF_BANK, /* integer: default bank number (def=0) */
+/*12*/ AWE_MD_DEF_DRUM, /* integer: default drumset number (def=0) */
+/*13*/ AWE_MD_TOGGLE_DRUM_BANK, /* 0/1: toggle drum flag with bank# (def=0) */
+/*14*/ AWE_MD_NEW_VOLUME_CALC, /* 0/1: volume calculation mode (def=1) */
+/*15*/ AWE_MD_CHORUS_MODE, /* integer: chorus mode (def=2) */
+/*16*/ AWE_MD_REVERB_MODE, /* integer: chorus mode (def=4) */
+/*17*/ AWE_MD_BASS_LEVEL, /* integer: bass level (def=5) */
+/*18*/ AWE_MD_TREBLE_LEVEL, /* integer: treble level (def=9) */
+/*19*/ AWE_MD_DEBUG_MODE, /* integer: debug level (def=0) */
+/*20*/ AWE_MD_PAN_EXCHANGE, /* 0/1: exchange panning direction (def=0) */
+ AWE_MD_END,
+};
+
+/*----------------------------------------------------------------*/
+
+/* effect parameters */
+enum {
+
+/* modulation envelope parameters */
+/* 0*/ AWE_FX_ENV1_DELAY, /* WORD: ENVVAL */
+/* 1*/ AWE_FX_ENV1_ATTACK, /* BYTE: up ATKHLD */
+/* 2*/ AWE_FX_ENV1_HOLD, /* BYTE: lw ATKHLD */
+/* 3*/ AWE_FX_ENV1_DECAY, /* BYTE: lw DCYSUS */
+/* 4*/ AWE_FX_ENV1_RELEASE, /* BYTE: lw DCYSUS */
+/* 5*/ AWE_FX_ENV1_SUSTAIN, /* BYTE: up DCYSUS */
+/* 6*/ AWE_FX_ENV1_PITCH, /* BYTE: up PEFE */
+/* 7*/ AWE_FX_ENV1_CUTOFF, /* BYTE: lw PEFE */
+
+/* volume envelope parameters */
+/* 8*/ AWE_FX_ENV2_DELAY, /* WORD: ENVVOL */
+/* 9*/ AWE_FX_ENV2_ATTACK, /* BYTE: up ATKHLDV */
+/*10*/ AWE_FX_ENV2_HOLD, /* BYTE: lw ATKHLDV */
+/*11*/ AWE_FX_ENV2_DECAY, /* BYTE: lw DCYSUSV */
+/*12*/ AWE_FX_ENV2_RELEASE, /* BYTE: lw DCYSUSV */
+/*13*/ AWE_FX_ENV2_SUSTAIN, /* BYTE: up DCYSUSV */
+
+/* LFO1 (tremolo & vibrato) parameters */
+/*14*/ AWE_FX_LFO1_DELAY, /* WORD: LFO1VAL */
+/*15*/ AWE_FX_LFO1_FREQ, /* BYTE: lo TREMFRQ */
+/*16*/ AWE_FX_LFO1_VOLUME, /* BYTE: up TREMFRQ */
+/*17*/ AWE_FX_LFO1_PITCH, /* BYTE: up FMMOD */
+/*18*/ AWE_FX_LFO1_CUTOFF, /* BYTE: lo FMMOD */
+
+/* LFO2 (vibrato) parameters */
+/*19*/ AWE_FX_LFO2_DELAY, /* WORD: LFO2VAL */
+/*20*/ AWE_FX_LFO2_FREQ, /* BYTE: lo FM2FRQ2 */
+/*21*/ AWE_FX_LFO2_PITCH, /* BYTE: up FM2FRQ2 */
+
+/* Other overall effect parameters */
+/*22*/ AWE_FX_INIT_PITCH, /* SHORT: pitch offset */
+/*23*/ AWE_FX_CHORUS, /* BYTE: chorus effects send (0-255) */
+/*24*/ AWE_FX_REVERB, /* BYTE: reverb effects send (0-255) */
+/*25*/ AWE_FX_CUTOFF, /* BYTE: up IFATN */
+/*26*/ AWE_FX_FILTERQ, /* BYTE: up CCCA */
+
+/* Sample / loop offset changes */
+/*27*/ AWE_FX_SAMPLE_START, /* SHORT: offset */
+/*28*/ AWE_FX_LOOP_START, /* SHORT: offset */
+/*29*/ AWE_FX_LOOP_END, /* SHORT: offset */
+/*30*/ AWE_FX_COARSE_SAMPLE_START, /* SHORT: upper word offset */
+/*31*/ AWE_FX_COARSE_LOOP_START, /* SHORT: upper word offset */
+/*32*/ AWE_FX_COARSE_LOOP_END, /* SHORT: upper word offset */
+/*33*/ AWE_FX_ATTEN, /* BYTE: lo IFATN */
+
+ AWE_FX_END,
+};
+
+#endif /* AWE_VOICE_H */
diff --git a/pfinet/linux-src/include/linux/ax25.h b/pfinet/linux-src/include/linux/ax25.h
new file mode 100644
index 00000000..1e492c8f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ax25.h
@@ -0,0 +1,98 @@
+/*
+ * These are the public elements of the Linux kernel AX.25 code. A similar
+ * file netrom.h exists for the NET/ROM protocol.
+ */
+
+#ifndef AX25_KERNEL_H
+#define AX25_KERNEL_H
+
+#define AX25_MTU 256
+#define AX25_MAX_DIGIS 8
+
+#define AX25_WINDOW 1
+#define AX25_T1 2
+#define AX25_N2 3
+#define AX25_T3 4
+#define AX25_T2 5
+#define AX25_BACKOFF 6
+#define AX25_EXTSEQ 7
+#define AX25_PIDINCL 8
+#define AX25_IDLE 9
+#define AX25_PACLEN 10
+#define AX25_IAMDIGI 12
+
+#define AX25_KILL 99
+
+#define SIOCAX25GETUID (SIOCPROTOPRIVATE+0)
+#define SIOCAX25ADDUID (SIOCPROTOPRIVATE+1)
+#define SIOCAX25DELUID (SIOCPROTOPRIVATE+2)
+#define SIOCAX25NOUID (SIOCPROTOPRIVATE+3)
+#define SIOCAX25OPTRT (SIOCPROTOPRIVATE+7)
+#define SIOCAX25CTLCON (SIOCPROTOPRIVATE+8)
+#define SIOCAX25GETINFO (SIOCPROTOPRIVATE+9)
+#define SIOCAX25ADDFWD (SIOCPROTOPRIVATE+10)
+#define SIOCAX25DELFWD (SIOCPROTOPRIVATE+11)
+
+#define AX25_SET_RT_IPMODE 2
+
+#define AX25_NOUID_DEFAULT 0
+#define AX25_NOUID_BLOCK 1
+
+typedef struct {
+ char ax25_call[7]; /* 6 call + SSID (shifted ascii!) */
+} ax25_address;
+
+struct sockaddr_ax25 {
+ sa_family_t sax25_family;
+ ax25_address sax25_call;
+ int sax25_ndigis;
+ /* Digipeater ax25_address sets follow */
+};
+
+#define sax25_uid sax25_ndigis
+
+struct full_sockaddr_ax25 {
+ struct sockaddr_ax25 fsa_ax25;
+ ax25_address fsa_digipeater[AX25_MAX_DIGIS];
+};
+
+struct ax25_routes_struct {
+ ax25_address port_addr;
+ ax25_address dest_addr;
+ unsigned char digi_count;
+ ax25_address digi_addr[AX25_MAX_DIGIS];
+};
+
+struct ax25_route_opt_struct {
+ ax25_address port_addr;
+ ax25_address dest_addr;
+ int cmd;
+ int arg;
+};
+
+struct ax25_ctl_struct {
+ ax25_address port_addr;
+ ax25_address source_addr;
+ ax25_address dest_addr;
+ unsigned int cmd;
+ unsigned long arg;
+ unsigned char digi_count;
+ ax25_address digi_addr[AX25_MAX_DIGIS];
+};
+
+struct ax25_info_struct {
+ unsigned int n2, n2count;
+ unsigned int t1, t1timer;
+ unsigned int t2, t2timer;
+ unsigned int t3, t3timer;
+ unsigned int idle, idletimer;
+ unsigned int state;
+ unsigned int rcv_q, snd_q;
+};
+
+struct ax25_fwd_struct {
+ ax25_address port_from;
+ ax25_address port_to;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/b1lli.h b/pfinet/linux-src/include/linux/b1lli.h
new file mode 100644
index 00000000..72cae4d2
--- /dev/null
+++ b/pfinet/linux-src/include/linux/b1lli.h
@@ -0,0 +1,136 @@
+/*
+ * $Id: b1lli.h,v 1.8 1999/07/01 15:26:54 calle Exp $
+ *
+ * ISDN lowlevel-module for AVM B1-card.
+ *
+ * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: b1lli.h,v $
+ * Revision 1.8 1999/07/01 15:26:54 calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ * - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ * - write a CAPI-2.0 for the passive cards
+ * - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ * make menuconfig, in the past all supported cards where included
+ * at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ * using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.7 1999/06/21 15:24:25 calle
+ * extend information in /proc.
+ *
+ * Revision 1.6 1999/04/15 19:49:36 calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.5 1998/10/25 14:50:28 fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.4 1998/03/29 16:05:02 calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.1.2.9 1998/03/20 14:30:02 calle
+ * added cardnr to detect if you try to add same T1 to different io address.
+ * change number of nccis depending on number of channels.
+ *
+ * Revision 1.1.2.8 1998/03/04 17:32:33 calle
+ * Changes for T1.
+ *
+ * Revision 1.1.2.7 1998/02/27 15:38:29 calle
+ * T1 running with slow link.
+ *
+ * Revision 1.1.2.6 1998/02/24 17:57:36 calle
+ * changes for T1.
+ *
+ * Revision 1.3 1998/01/31 10:54:37 calle
+ * include changes for PCMCIA cards from 2.0 version
+ *
+ * Revision 1.2 1997/12/10 19:38:42 calle
+ * get changes from 2.0 tree
+ *
+ * Revision 1.1.2.2 1997/11/26 16:57:26 calle
+ * more changes for B1/M1/T1.
+ *
+ * Revision 1.1.2.1 1997/11/26 10:47:01 calle
+ * prepared for M1 (Mobile) and T1 (PMX) cards.
+ * prepared to set configuration after load to support other D-channel
+ * protocols, point-to-point and leased lines.
+ *
+ * Revision 1.1 1997/03/04 21:27:32 calle
+ * First version in isdn4linux
+ *
+ * Revision 2.2 1997/02/12 09:31:39 calle
+ * new version
+ *
+ * Revision 1.1 1997/01/31 10:32:20 calle
+ * Initial revision
+ *
+ */
+
+#ifndef _B1LLI_H_
+#define _B1LLI_H_
+/*
+ * struct for loading t4 file
+ */
+typedef struct avmb1_t4file {
+ int len;
+ unsigned char *data;
+} avmb1_t4file;
+
+typedef struct avmb1_loaddef {
+ int contr;
+ avmb1_t4file t4file;
+} avmb1_loaddef;
+
+typedef struct avmb1_loadandconfigdef {
+ int contr;
+ avmb1_t4file t4file;
+ avmb1_t4file t4config;
+} avmb1_loadandconfigdef;
+
+typedef struct avmb1_resetdef {
+ int contr;
+} avmb1_resetdef;
+
+typedef struct avmb1_getdef {
+ int contr;
+ int cardtype;
+ int cardstate;
+} avmb1_getdef;
+
+/*
+ * struct for adding new cards
+ */
+typedef struct avmb1_carddef {
+ int port;
+ int irq;
+} avmb1_carddef;
+
+#define AVM_CARDTYPE_B1 0
+#define AVM_CARDTYPE_T1 1
+#define AVM_CARDTYPE_M1 2
+#define AVM_CARDTYPE_M2 3
+
+typedef struct avmb1_extcarddef {
+ int port;
+ int irq;
+ int cardtype;
+ int cardnr; /* for HEMA/T1 */
+} avmb1_extcarddef;
+
+#define AVMB1_LOAD 0 /* load image to card */
+#define AVMB1_ADDCARD 1 /* add a new card */
+#define AVMB1_RESETCARD 2 /* reset a card */
+#define AVMB1_LOAD_AND_CONFIG 3 /* load image and config to card */
+#define AVMB1_ADDCARD_WITH_TYPE 4 /* add a new card, with cardtype */
+#define AVMB1_GET_CARDINFO 5 /* get cardtype */
+#define AVMB1_REMOVECARD 6 /* remove a card (usefull for T1) */
+
+#define AVMB1_REGISTERCARD_IS_OBSOLETE
+
+#endif /* _B1LLI_H_ */
diff --git a/pfinet/linux-src/include/linux/b1pcmcia.h b/pfinet/linux-src/include/linux/b1pcmcia.h
new file mode 100644
index 00000000..e13307ba
--- /dev/null
+++ b/pfinet/linux-src/include/linux/b1pcmcia.h
@@ -0,0 +1,36 @@
+/*
+ * $Id: b1pcmcia.h,v 1.1 1999/07/01 15:26:56 calle Exp $
+ *
+ * Exported functions of module b1pcmcia to be called by
+ * avm_cs card services module.
+ *
+ * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: b1pcmcia.h,v $
+ * Revision 1.1 1999/07/01 15:26:56 calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ * - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ * - write a CAPI-2.0 for the passive cards
+ * - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ * make menuconfig, in the past all supported cards where included
+ * at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ * using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ */
+
+#ifndef _B1PCMCIA_H_
+#define _B1PCMCIA_H_
+
+int b1pcmcia_addcard_b1(unsigned int port, unsigned irq);
+int b1pcmcia_addcard_m1(unsigned int port, unsigned irq);
+int b1pcmcia_addcard_m2(unsigned int port, unsigned irq);
+int b1pcmcia_delcard(unsigned int port, unsigned irq);
+
+#endif /* _B1PCMCIA_H_ */
diff --git a/pfinet/linux-src/include/linux/baycom.h b/pfinet/linux-src/include/linux/baycom.h
new file mode 100644
index 00000000..81249e02
--- /dev/null
+++ b/pfinet/linux-src/include/linux/baycom.h
@@ -0,0 +1,39 @@
+/*
+ * The Linux BAYCOM driver for the Baycom serial 1200 baud modem
+ * and the parallel 9600 baud modem
+ * (C) 1997-1998 by Thomas Sailer, HB9JNX/AE4WA
+ */
+
+#ifndef _BAYCOM_H
+#define _BAYCOM_H
+
+/* -------------------------------------------------------------------- */
+/*
+ * structs for the IOCTL commands
+ */
+
+struct baycom_debug_data {
+ unsigned long debug1;
+ unsigned long debug2;
+ long debug3;
+};
+
+struct baycom_ioctl {
+ int cmd;
+ union {
+ struct baycom_debug_data dbg;
+ } data;
+};
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * ioctl values change for baycom
+ */
+#define BAYCOMCTL_GETDEBUG 0x92
+
+/* -------------------------------------------------------------------- */
+
+#endif /* _BAYCOM_H */
+
+/* --------------------------------------------------------------------- */
diff --git a/pfinet/linux-src/include/linux/binfmts.h b/pfinet/linux-src/include/linux/binfmts.h
new file mode 100644
index 00000000..0d34d35b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/binfmts.h
@@ -0,0 +1,77 @@
+#ifndef _LINUX_BINFMTS_H
+#define _LINUX_BINFMTS_H
+
+#include <linux/ptrace.h>
+#include <linux/capability.h>
+
+/*
+ * MAX_ARG_PAGES defines the number of pages allocated for arguments
+ * and envelope for the new program. 32 should suffice, this gives
+ * a maximum env+arg of 128kB w/4KB pages!
+ */
+#define MAX_ARG_PAGES 32
+
+#ifdef __KERNEL__
+
+/*
+ * This structure is used to hold the arguments that are used when loading binaries.
+ */
+struct linux_binprm{
+ char buf[128];
+ unsigned long page[MAX_ARG_PAGES];
+ unsigned long p;
+ int sh_bang;
+ int java; /* Java binary, prevent recursive invocation */
+ struct dentry * dentry;
+ int e_uid, e_gid;
+ kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
+ int argc, envc;
+ char * filename; /* Name of binary */
+ unsigned long loader, exec;
+};
+
+/*
+ * This structure defines the functions that are used to load the binary formats that
+ * linux accepts.
+ */
+struct linux_binfmt {
+ struct linux_binfmt * next;
+ struct module *module;
+ int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
+ int (*load_shlib)(int fd);
+ int (*core_dump)(long signr, struct pt_regs * regs);
+};
+
+extern int register_binfmt(struct linux_binfmt *);
+extern int unregister_binfmt(struct linux_binfmt *);
+
+extern int read_exec(struct dentry *, unsigned long offset,
+ char * addr, unsigned long count, int to_kmem);
+
+extern int open_dentry(struct dentry *, int mode);
+
+extern int init_elf_binfmt(void);
+extern int init_elf32_binfmt(void);
+extern int init_irix_binfmt(void);
+extern int init_aout_binfmt(void);
+extern int init_aout32_binfmt(void);
+extern int init_script_binfmt(void);
+extern int init_java_binfmt(void);
+extern int init_em86_binfmt(void);
+extern int init_misc_binfmt(void);
+
+extern int prepare_binprm(struct linux_binprm *);
+extern void remove_arg_zero(struct linux_binprm *);
+extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
+extern int flush_old_exec(struct linux_binprm * bprm);
+extern unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm);
+extern unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
+ unsigned long p, int from_kmem);
+
+extern void compute_creds(struct linux_binprm *binprm);
+
+/* this eventually goes away */
+#define change_ldt(a,b) setup_arg_pages(a,b)
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_BINFMTS_H */
diff --git a/pfinet/linux-src/include/linux/bios32.h b/pfinet/linux-src/include/linux/bios32.h
new file mode 100644
index 00000000..2f2c14b7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/bios32.h
@@ -0,0 +1,34 @@
+/*
+ * This is only a stub file to make drivers not yet converted to the new
+ * PCI probing mechanism work. [mj]
+ */
+
+#ifndef BIOS32_H
+#define BIOS32_H
+
+#include <linux/pci.h>
+
+#warning This driver uses the old PCI interface, please fix it (see Documentation/pci.txt)
+
+extern inline int __pcibios_read_irq(unsigned char bus, unsigned char dev_fn, unsigned char *to)
+{
+ struct pci_dev *pdev = pci_find_slot(bus, dev_fn);
+ if (!pdev) {
+ *to = 0;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ } else {
+ *to = pdev->irq;
+ return PCIBIOS_SUCCESSFUL;
+ }
+}
+
+extern inline int __pcibios_read_config_byte(unsigned char bus,
+ unsigned char dev_fn, unsigned char where, unsigned char *to)
+{
+ return pcibios_read_config_byte(bus, dev_fn, where, to);
+}
+
+#define pcibios_read_config_byte(b,d,w,p) \
+ (((w) == PCI_INTERRUPT_LINE) ? __pcibios_read_irq(b,d,p) : __pcibios_read_config_byte(b,d,w,p))
+
+#endif
diff --git a/pfinet/linux-src/include/linux/bitops.h b/pfinet/linux-src/include/linux/bitops.h
new file mode 100644
index 00000000..ddb84dd6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/bitops.h
@@ -0,0 +1,72 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+extern __inline__ int generic_ffs(int x)
+{
+ int r = 1;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff)) {
+ x >>= 16;
+ r += 16;
+ }
+ if (!(x & 0xff)) {
+ x >>= 8;
+ r += 8;
+ }
+ if (!(x & 0xf)) {
+ x >>= 4;
+ r += 4;
+ }
+ if (!(x & 3)) {
+ x >>= 2;
+ r += 2;
+ }
+ if (!(x & 1)) {
+ x >>= 1;
+ r += 1;
+ }
+ return r;
+}
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+extern __inline__ unsigned int generic_hweight32(unsigned int w)
+{
+ unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
+ res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+ res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+ res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+ return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+extern __inline__ unsigned int generic_hweight16(unsigned int w)
+{
+ unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
+ res = (res & 0x3333) + ((res >> 2) & 0x3333);
+ res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
+ return (res & 0x00FF) + ((res >> 8) & 0x00FF);
+}
+
+extern __inline__ unsigned int generic_hweight8(unsigned int w)
+{
+ unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
+ res = (res & 0x33) + ((res >> 2) & 0x33);
+ return (res & 0x0F) + ((res >> 4) & 0x0F);
+}
+
+#include <asm/bitops.h>
+
+
+#endif
diff --git a/pfinet/linux-src/include/linux/blk.h b/pfinet/linux-src/include/linux/blk.h
new file mode 100644
index 00000000..53db6024
--- /dev/null
+++ b/pfinet/linux-src/include/linux/blk.h
@@ -0,0 +1,467 @@
+#ifndef _BLK_H
+#define _BLK_H
+
+#include <linux/blkdev.h>
+#include <linux/locks.h>
+#include <linux/config.h>
+
+#include <asm/spinlock.h>
+
+/*
+ * Spinlock for protecting the request queue which
+ * is mucked around with in interrupts on potentially
+ * multiple CPU's..
+ */
+extern spinlock_t io_request_lock;
+
+/*
+ * NR_REQUEST is the number of entries in the request-queue.
+ * NOTE that writes may use only the low 2/3 of these: reads
+ * take precedence.
+ */
+#define NR_REQUEST 128
+
+/*
+ * This is used in the elevator algorithm. We don't prioritise reads
+ * over writes any more --- although reads are more time-critical than
+ * writes, by treating them equally we increase filesystem throughput.
+ * This turns out to give better overall performance. -- sct
+ */
+#define IN_ORDER(s1,s2) \
+((s1)->rq_dev < (s2)->rq_dev || (((s1)->rq_dev == (s2)->rq_dev && \
+(s1)->sector < (s2)->sector)))
+
+/*
+ * Initialization functions.
+ */
+extern int isp16_init(void);
+extern int cdu31a_init(void);
+extern int acsi_init(void);
+extern int mcd_init(void);
+extern int mcdx_init(void);
+extern int sbpcd_init(void);
+extern int aztcd_init(void);
+extern int sony535_init(void);
+extern int gscd_init(void);
+extern int cm206_init(void);
+extern int optcd_init(void);
+extern int sjcd_init(void);
+extern int cdi_init(void);
+extern int hd_init(void);
+extern int ide_init(void);
+extern int xd_init(void);
+extern int mfm_init(void);
+extern int loop_init(void);
+extern int md_init(void);
+extern int ap_init(void);
+extern int ddv_init(void);
+extern int z2_init(void);
+extern int swim3_init(void);
+extern int amiga_floppy_init(void);
+extern int atari_floppy_init(void);
+extern int nbd_init(void);
+extern int ez_init(void);
+extern int bpcd_init(void);
+extern int ps2esdi_init(void);
+
+extern void set_device_ro(kdev_t dev,int flag);
+void add_blkdev_randomness(int major);
+
+extern int floppy_init(void);
+extern void rd_load(void);
+extern int rd_init(void);
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start; /* starting block # of image */
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+#define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */
+
+extern unsigned long initrd_start,initrd_end;
+extern int mount_initrd; /* zero if initrd should not be mounted */
+extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */
+void initrd_init(void);
+
+#endif
+
+#define RO_IOCTLS(dev,where) \
+ case BLKROSET: { int __val; if (!capable(CAP_SYS_ADMIN)) return -EACCES; \
+ if (get_user(__val, (int *)(where))) return -EFAULT; \
+ set_device_ro((dev),__val); return 0; } \
+ case BLKROGET: { int __val = (is_read_only(dev) != 0) ; \
+ return put_user(__val,(int *) (where)); }
+
+/*
+ * end_request() and friends. Must be called with the request queue spinlock
+ * acquired. All functions called within end_request() _must_be_ atomic.
+ *
+ * Several drivers define their own end_request and call
+ * end_that_request_first() and end_that_request_last()
+ * for parts of the original function. This prevents
+ * code duplication in drivers.
+ */
+
+int end_that_request_first(struct request *req, int uptodate, char *name);
+void end_that_request_last(struct request *req);
+
+#if defined(MAJOR_NR) || defined(IDE_DRIVER)
+
+/*
+ * Add entries as needed.
+ */
+
+#ifdef IDE_DRIVER
+
+#define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS)
+#define DEVICE_ON(device) /* nothing */
+#define DEVICE_OFF(device) /* nothing */
+#define DEVICE_NAME "ide"
+
+#elif (MAJOR_NR == RAMDISK_MAJOR)
+
+/* ram disk */
+#define DEVICE_NAME "ramdisk"
+#define DEVICE_REQUEST rd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+#define DEVICE_NO_RANDOM
+
+#elif (MAJOR_NR == Z2RAM_MAJOR)
+
+/* Zorro II Ram */
+#define DEVICE_NAME "Z2RAM"
+#define DEVICE_REQUEST do_z2_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == FLOPPY_MAJOR)
+
+static void floppy_off(unsigned int nr);
+
+#define DEVICE_NAME "floppy"
+#define DEVICE_INTR do_floppy
+#define DEVICE_REQUEST do_fd_request
+#define DEVICE_NR(device) ( (MINOR(device) & 3) | ((MINOR(device) & 0x80 ) >> 5 ))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
+
+#elif (MAJOR_NR == HD_MAJOR)
+
+/* Hard disk: timeout is 6 seconds. */
+#define DEVICE_NAME "hard disk"
+#define DEVICE_INTR do_hd
+#define DEVICE_TIMEOUT HD_TIMER
+#define TIMEOUT_VALUE (6*HZ)
+#define DEVICE_REQUEST do_hd_request
+#define DEVICE_NR(device) (MINOR(device)>>6)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (SCSI_DISK_MAJOR(MAJOR_NR))
+
+#define DEVICE_NAME "scsidisk"
+#define DEVICE_INTR do_sd
+#define TIMEOUT_VALUE (2*HZ)
+#define DEVICE_REQUEST do_sd_request
+#define DEVICE_NR(device) (((MAJOR(device) & SD_MAJOR_MASK) << (8 - 4)) + (MINOR(device) >> 4))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+/* Kludge to use the same number for both char and block major numbers */
+#elif (MAJOR_NR == MD_MAJOR) && defined(MD_DRIVER)
+
+#define DEVICE_NAME "Multiple devices driver"
+#define DEVICE_REQUEST do_md_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == SCSI_TAPE_MAJOR)
+
+#define DEVICE_NAME "scsitape"
+#define DEVICE_INTR do_st
+#define DEVICE_NR(device) (MINOR(device) & 0x7f)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == SCSI_CDROM_MAJOR)
+
+#define DEVICE_NAME "CD-ROM"
+#define DEVICE_INTR do_sr
+#define DEVICE_REQUEST do_sr_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == XT_DISK_MAJOR)
+
+#define DEVICE_NAME "xt disk"
+#define DEVICE_REQUEST do_xd_request
+#define DEVICE_NR(device) (MINOR(device) >> 6)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == PS2ESDI_MAJOR)
+
+#define DEVICE_NAME "PS/2 ESDI"
+#define DEVICE_REQUEST do_ps2esdi_request
+#define DEVICE_NR(device) (MINOR(device) >> 6)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == CDU31A_CDROM_MAJOR)
+
+#define DEVICE_NAME "CDU31A"
+#define DEVICE_REQUEST do_cdu31a_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == ACSI_MAJOR) && (defined(CONFIG_ATARI_ACSI) || defined(CONFIG_ATARI_ACSI_MODULE))
+
+#define DEVICE_NAME "ACSI"
+#define DEVICE_INTR do_acsi
+#define DEVICE_REQUEST do_acsi_request
+#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == MITSUMI_CDROM_MAJOR)
+
+#define DEVICE_NAME "Mitsumi CD-ROM"
+/* #define DEVICE_INTR do_mcd */
+#define DEVICE_REQUEST do_mcd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == MITSUMI_X_CDROM_MAJOR)
+
+#define DEVICE_NAME "Mitsumi CD-ROM"
+/* #define DEVICE_INTR do_mcdx */
+#define DEVICE_REQUEST do_mcdx_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == MATSUSHITA_CDROM_MAJOR)
+
+#define DEVICE_NAME "Matsushita CD-ROM controller #1"
+#define DEVICE_REQUEST do_sbpcd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == MATSUSHITA_CDROM2_MAJOR)
+
+#define DEVICE_NAME "Matsushita CD-ROM controller #2"
+#define DEVICE_REQUEST do_sbpcd2_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == MATSUSHITA_CDROM3_MAJOR)
+
+#define DEVICE_NAME "Matsushita CD-ROM controller #3"
+#define DEVICE_REQUEST do_sbpcd3_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == MATSUSHITA_CDROM4_MAJOR)
+
+#define DEVICE_NAME "Matsushita CD-ROM controller #4"
+#define DEVICE_REQUEST do_sbpcd4_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == AZTECH_CDROM_MAJOR)
+
+#define DEVICE_NAME "Aztech CD-ROM"
+#define DEVICE_REQUEST do_aztcd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == CDU535_CDROM_MAJOR)
+
+#define DEVICE_NAME "SONY-CDU535"
+#define DEVICE_INTR do_cdu535
+#define DEVICE_REQUEST do_cdu535_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == GOLDSTAR_CDROM_MAJOR)
+
+#define DEVICE_NAME "Goldstar R420"
+#define DEVICE_REQUEST do_gscd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == CM206_CDROM_MAJOR)
+#define DEVICE_NAME "Philips/LMS CD-ROM cm206"
+#define DEVICE_REQUEST do_cm206_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == OPTICS_CDROM_MAJOR)
+
+#define DEVICE_NAME "DOLPHIN 8000AT CD-ROM"
+#define DEVICE_REQUEST do_optcd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == SANYO_CDROM_MAJOR)
+
+#define DEVICE_NAME "Sanyo H94A CD-ROM"
+#define DEVICE_REQUEST do_sjcd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == APBLOCK_MAJOR)
+
+#define DEVICE_NAME "apblock"
+#define DEVICE_REQUEST ap_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == DDV_MAJOR)
+
+#define DEVICE_NAME "ddv"
+#define DEVICE_REQUEST ddv_request
+#define DEVICE_NR(device) (MINOR(device)>>PARTN_BITS)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == MFM_ACORN_MAJOR)
+
+#define DEVICE_NAME "mfm disk"
+#define DEVICE_INTR do_mfm
+#define DEVICE_REQUEST do_mfm_request
+#define DEVICE_NR(device) (MINOR(device) >> 6)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == MFM_ACORN_MAJOR)
+
+#define DEVICE_NAME "mfm disk"
+#define DEVICE_INTR do_mfm
+#define DEVICE_REQUEST do_mfm_request
+#define DEVICE_NR(device) (MINOR(device) >> 6)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == NBD_MAJOR)
+
+#define DEVICE_NAME "nbd"
+#define DEVICE_REQUEST do_nbd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
+
+#define DEVICE_NAME "ida"
+#define TIMEOUT_VALUE (25*HZ)
+#define DEVICE_REQUEST do_ida_request0
+#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#endif /* MAJOR_NR == whatever */
+
+#if (MAJOR_NR != SCSI_TAPE_MAJOR)
+#if !defined(IDE_DRIVER)
+
+#ifndef CURRENT
+#define CURRENT (blk_dev[MAJOR_NR].current_request)
+#endif
+
+#ifndef DEVICE_NAME
+#define DEVICE_NAME "unknown"
+#endif
+
+#define CURRENT_DEV DEVICE_NR(CURRENT->rq_dev)
+
+#ifdef DEVICE_INTR
+static void (*DEVICE_INTR)(void) = NULL;
+#endif
+
+#ifdef DEVICE_TIMEOUT
+
+#define SET_TIMER \
+((timer_table[DEVICE_TIMEOUT].expires = jiffies + TIMEOUT_VALUE), \
+(timer_active |= 1<<DEVICE_TIMEOUT))
+
+#define CLEAR_TIMER \
+timer_active &= ~(1<<DEVICE_TIMEOUT)
+
+#define SET_INTR(x) \
+if ((DEVICE_INTR = (x)) != NULL) \
+ SET_TIMER; \
+else \
+ CLEAR_TIMER;
+
+#else
+
+#define SET_INTR(x) (DEVICE_INTR = (x))
+
+#endif /* DEVICE_TIMEOUT */
+
+static void (DEVICE_REQUEST)(void);
+
+#ifdef DEVICE_INTR
+#define CLEAR_INTR SET_INTR(NULL)
+#else
+#define CLEAR_INTR
+#endif
+
+#define INIT_REQUEST \
+ if (!CURRENT) {\
+ CLEAR_INTR; \
+ return; \
+ } \
+ if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \
+ panic(DEVICE_NAME ": request list destroyed"); \
+ if (CURRENT->bh) { \
+ if (!buffer_locked(CURRENT->bh)) \
+ panic(DEVICE_NAME ": block not locked"); \
+ }
+
+#endif /* !defined(IDE_DRIVER) */
+
+#ifndef LOCAL_END_REQUEST /* If we have our own end_request, we do not want to include this mess */
+
+#if ! SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR)
+
+static void end_request(int uptodate) {
+ struct request *req = CURRENT;
+
+ if (end_that_request_first(req, uptodate, DEVICE_NAME))
+ return;
+
+#ifndef DEVICE_NO_RANDOM
+ add_blkdev_randomness(MAJOR(req->rq_dev));
+#endif
+ DEVICE_OFF(req->rq_dev);
+ CURRENT = req->next;
+ end_that_request_last(req);
+}
+
+#endif /* ! SCSI_BLK_MAJOR(MAJOR_NR) */
+#endif /* LOCAL_END_REQUEST */
+
+#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) */
+#endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */
+
+#endif /* _BLK_H */
diff --git a/pfinet/linux-src/include/linux/blkdev.h b/pfinet/linux-src/include/linux/blkdev.h
new file mode 100644
index 00000000..87a9092b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/blkdev.h
@@ -0,0 +1,94 @@
+#ifndef _LINUX_BLKDEV_H
+#define _LINUX_BLKDEV_H
+
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/genhd.h>
+#include <linux/tqueue.h>
+
+/*
+ * Ok, this is an expanded form so that we can use the same
+ * request for paging requests when that is implemented. In
+ * paging, 'bh' is NULL, and the semaphore is used to wait
+ * for read/write completion.
+ */
+struct request {
+ volatile int rq_status; /* should split this into a few status bits */
+#define RQ_INACTIVE (-1)
+#define RQ_ACTIVE 1
+#define RQ_SCSI_BUSY 0xffff
+#define RQ_SCSI_DONE 0xfffe
+#define RQ_SCSI_DISCONNECTING 0xffe0
+
+ kdev_t rq_dev;
+ int cmd; /* READ or WRITE */
+ int errors;
+ unsigned long sector;
+ unsigned long nr_sectors;
+ unsigned long nr_segments;
+ unsigned long current_nr_sectors;
+ char * buffer;
+ struct semaphore * sem;
+ struct buffer_head * bh;
+ struct buffer_head * bhtail;
+ struct request * next;
+};
+
+typedef void (request_fn_proc) (void);
+typedef struct request ** (queue_proc) (kdev_t dev);
+
+struct blk_dev_struct {
+ request_fn_proc *request_fn;
+ /*
+ * queue_proc has to be atomic
+ */
+ queue_proc *queue;
+ void *data;
+ struct request *current_request;
+ struct request plug;
+ struct tq_struct plug_tq;
+};
+
+struct sec_size {
+ unsigned block_size;
+ unsigned block_size_bits;
+};
+
+extern struct sec_size * blk_sec[MAX_BLKDEV];
+extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
+extern struct wait_queue * wait_for_request;
+extern void resetup_one_dev(struct gendisk *dev, int drive);
+extern void unplug_device(void * data);
+extern void make_request(int major,int rw, struct buffer_head * bh);
+
+/* md needs this function to remap requests */
+extern int md_map (int minor, kdev_t *rdev, unsigned long *rsector, unsigned long size);
+extern int md_make_request (int minor, int rw, struct buffer_head * bh);
+extern int md_error (kdev_t mddev, kdev_t rdev);
+
+extern int * blk_size[MAX_BLKDEV];
+
+extern int * blksize_size[MAX_BLKDEV];
+
+extern int * hardsect_size[MAX_BLKDEV];
+
+extern int * max_readahead[MAX_BLKDEV];
+
+extern int * max_sectors[MAX_BLKDEV];
+
+extern int * max_segments[MAX_BLKDEV];
+
+#define MAX_SECTORS 128
+
+#define MAX_SEGMENTS MAX_SECTORS
+
+#define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
+#if 0 /* small readahead */
+#define MAX_READAHEAD PageAlignSize(4096*7)
+#define MIN_READAHEAD PageAlignSize(4096*2)
+#else /* large readahead */
+#define MAX_READAHEAD PageAlignSize(4096*31)
+#define MIN_READAHEAD PageAlignSize(4096*3)
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/bpqether.h b/pfinet/linux-src/include/linux/bpqether.h
new file mode 100644
index 00000000..a6c35e1a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/bpqether.h
@@ -0,0 +1,41 @@
+#ifndef __BPQETHER_H
+#define __BPQETHER_H
+
+/*
+ * Defines for the BPQETHER pseudo device driver
+ */
+
+#ifndef __LINUX_IF_ETHER_H
+#include <linux/if_ether.h>
+#endif
+
+#define SIOCSBPQETHOPT (SIOCDEVPRIVATE+0) /* reserved */
+#define SIOCSBPQETHADDR (SIOCDEVPRIVATE+1)
+
+struct bpq_ethaddr {
+ unsigned char destination[ETH_ALEN];
+ unsigned char accept[ETH_ALEN];
+};
+
+/*
+ * For SIOCSBPQETHOPT - this is compatible with PI2/PacketTwin card drivers,
+ * currently not implemented, though. If someone wants to hook a radio
+ * to his Ethernet card he may find this useful. ;-)
+ */
+
+#define SIOCGBPQETHPARAM 0x5000 /* get Level 1 parameters */
+#define SIOCSBPQETHPARAM 0x5001 /* set */
+
+struct bpq_req {
+ int cmd;
+ int speed; /* unused */
+ int clockmode; /* unused */
+ int txdelay;
+ unsigned char persist; /* unused */
+ int slotime; /* unused */
+ int squeldelay;
+ int dmachan; /* unused */
+ int irq; /* unused */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/busmouse.h b/pfinet/linux-src/include/linux/busmouse.h
new file mode 100644
index 00000000..eb71550d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/busmouse.h
@@ -0,0 +1,104 @@
+#ifndef _LINUX_BUSMOUSE_H
+#define _LINUX_BUSMOUSE_H
+
+/*
+ * linux/include/linux/busmouse.h: header file for Logitech Bus Mouse driver
+ * by James Banks
+ *
+ * based on information gleamed from various mouse drivers on the net
+ *
+ * Heavily modified by David giller (rafetmad@oxy.edu)
+ *
+ * Minor modifications for Linux 0.96c-pl1 by Nathan Laredo
+ * gt7080a@prism.gatech.edu (13JUL92)
+ *
+ * Microsoft BusMouse support by Teemu Rantanen (tvr@cs.hut.fi) (02AUG92)
+ *
+ * Microsoft Bus Mouse support modified by Derrick Cole (cole@concert.net)
+ * 8/28/92
+ *
+ * Microsoft Bus Mouse support folded into 0.97pl4 code
+ * by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
+ * Changes: Logitech and Microsoft support in the same kernel.
+ * Defined new constants in busmouse.h for MS mice.
+ * Added int mse_busmouse_type to distinguish busmouse types
+ * Added a couple of new functions to handle differences in using
+ * MS vs. Logitech (where the int variable wasn't appropriate).
+ *
+ */
+
+#define MOUSE_IRQ 5
+#define LOGITECH_BUSMOUSE 0 /* Minor device # for Logitech */
+#define MICROSOFT_BUSMOUSE 2 /* Minor device # for Microsoft */
+
+/*--------- LOGITECH BUSMOUSE ITEMS -------------*/
+
+#define LOGIBM_BASE 0x23c
+#define MSE_DATA_PORT 0x23c
+#define MSE_SIGNATURE_PORT 0x23d
+#define MSE_CONTROL_PORT 0x23e
+#define MSE_INTERRUPT_PORT 0x23e
+#define MSE_CONFIG_PORT 0x23f
+#define LOGIBM_EXTENT 0x4
+
+#define MSE_ENABLE_INTERRUPTS 0x00
+#define MSE_DISABLE_INTERRUPTS 0x10
+
+#define MSE_READ_X_LOW 0x80
+#define MSE_READ_X_HIGH 0xa0
+#define MSE_READ_Y_LOW 0xc0
+#define MSE_READ_Y_HIGH 0xe0
+
+/* Magic number used to check if the mouse exists */
+#define MSE_CONFIG_BYTE 0x91
+#define MSE_DEFAULT_MODE 0x90
+#define MSE_SIGNATURE_BYTE 0xa5
+
+/* useful Logitech Mouse macros */
+
+#define MSE_INT_OFF() outb(MSE_DISABLE_INTERRUPTS, MSE_CONTROL_PORT)
+#define MSE_INT_ON() outb(MSE_ENABLE_INTERRUPTS, MSE_CONTROL_PORT)
+
+/*--------- MICROSOFT BUSMOUSE ITEMS -------------*/
+
+#define MSBM_BASE 0x23d
+#define MS_MSE_DATA_PORT 0x23d
+#define MS_MSE_SIGNATURE_PORT 0x23e
+#define MS_MSE_CONTROL_PORT 0x23c
+#define MS_MSE_CONFIG_PORT 0x23f
+#define MSBM_EXTENT 0x3
+
+#define MS_MSE_ENABLE_INTERRUPTS 0x11
+#define MS_MSE_DISABLE_INTERRUPTS 0x10
+
+#define MS_MSE_READ_BUTTONS 0x00
+#define MS_MSE_READ_X 0x01
+#define MS_MSE_READ_Y 0x02
+
+#define MS_MSE_START 0x80
+#define MS_MSE_COMMAND_MODE 0x07
+
+/* useful microsoft busmouse macros */
+
+#define MS_MSE_INT_OFF() {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
+ outb(MS_MSE_DISABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
+#define MS_MSE_INT_ON() {outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); \
+ outb(MS_MSE_ENABLE_INTERRUPTS, MS_MSE_DATA_PORT);}
+
+
+struct mouse_status {
+ unsigned char buttons;
+ unsigned char latch_buttons;
+ int dx;
+ int dy;
+ int present;
+ int ready;
+ int active;
+ struct wait_queue *wait;
+ struct fasync_struct *fasyncptr;
+};
+
+/* Function Prototypes */
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/capability.h b/pfinet/linux-src/include/linux/capability.h
new file mode 100644
index 00000000..07d554ca
--- /dev/null
+++ b/pfinet/linux-src/include/linux/capability.h
@@ -0,0 +1,337 @@
+/*
+ * This is <linux/capability.h>
+ *
+ * Andrew G. Morgan <morgan@transmeta.com>
+ * Alexander Kjeldaas <astor@guardian.no>
+ * with help from Aleph1, Roland Buresund and Andrew Main.
+ */
+
+#ifndef _LINUX_CAPABILITY_H
+#define _LINUX_CAPABILITY_H
+
+#include <linux/types.h>
+#include <linux/fs.h>
+
+/* User-level do most of the mapping between kernel and user
+ capabilities based on the version tag given by the kernel. The
+ kernel might be somewhat backwards compatible, but don't bet on
+ it. */
+
+/* XXX - Note, cap_t, is defined by POSIX to be an "opaque" pointer to
+ a set of three capability sets. The transposition of 3*the
+ following structure to such a composite is better handled in a user
+ library since the draft standard requires the use of malloc/free
+ etc.. */
+
+#define _LINUX_CAPABILITY_VERSION 0x19980330
+
+typedef struct __user_cap_header_struct {
+ __u32 version;
+ int pid;
+} *cap_user_header_t;
+
+typedef struct __user_cap_data_struct {
+ __u32 effective;
+ __u32 permitted;
+ __u32 inheritable;
+} *cap_user_data_t;
+
+#ifdef __KERNEL__
+
+/* #define STRICT_CAP_T_TYPECHECKS */
+
+#ifdef STRICT_CAP_T_TYPECHECKS
+
+typedef struct kernel_cap_struct {
+ __u32 cap;
+} kernel_cap_t;
+
+#else
+
+typedef __u32 kernel_cap_t;
+
+#endif
+
+#define _USER_CAP_HEADER_SIZE (2*sizeof(__u32))
+#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))
+
+#endif
+
+
+/**
+ ** POSIX-draft defined capabilities.
+ **/
+
+/* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this
+ overrides the restriction of changing file ownership and group
+ ownership. */
+
+#define CAP_CHOWN 0
+
+/* Override all DAC access, including ACL execute access if
+ [_POSIX_ACL] is defined. Excluding DAC access covered by
+ CAP_LINUX_IMMUTABLE. */
+
+#define CAP_DAC_OVERRIDE 1
+
+/* Overrides all DAC restrictions regarding read and search on files
+ and directories, including ACL restrictions if [_POSIX_ACL] is
+ defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */
+
+#define CAP_DAC_READ_SEARCH 2
+
+/* Overrides all restrictions about allowed operations on files, where
+ file owner ID must be equal to the user ID, except where CAP_FSETID
+ is applicable. It doesn't override MAC and DAC restrictions. */
+
+#define CAP_FOWNER 3
+
+/* Overrides the following restrictions that the effective user ID
+ shall match the file owner ID when setting the S_ISUID and S_ISGID
+ bits on that file; that the effective group ID (or one of the
+ supplementary group IDs shall match the file owner ID when setting
+ the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are
+ cleared on successful return from chown(2). */
+
+#define CAP_FSETID 4
+
+/* Used to decide between falling back on the old suser() or fsuser(). */
+
+#define CAP_FS_MASK 0x1f
+
+/* Overrides the restriction that the real or effective user ID of a
+ process sending a signal must match the real or effective user ID
+ of the process receiving the signal. */
+
+#define CAP_KILL 5
+
+/* Allows setgid(2) manipulation */
+/* Allows setgroups(2) */
+/* Allows forged gids on socket credentials passing. */
+
+#define CAP_SETGID 6
+
+/* Allows set*uid(2) manipulation (including fsuid). */
+/* Allows forged pids on socket credentials passing. */
+
+#define CAP_SETUID 7
+
+
+/**
+ ** Linux-specific capabilities
+ **/
+
+/* Transfer any capability in your permitted set to any pid,
+ remove any capability in your permitted set from any pid */
+
+#define CAP_SETPCAP 8
+
+/* Allow modification of S_IMMUTABLE and S_APPEND file attributes */
+
+#define CAP_LINUX_IMMUTABLE 9
+
+/* Allows binding to TCP/UDP sockets below 1024 */
+
+#define CAP_NET_BIND_SERVICE 10
+
+/* Allow broadcasting, listen to multicast */
+
+#define CAP_NET_BROADCAST 11
+
+/* Allow interface configuration */
+/* Allow administration of IP firewall, masquerading and accounting */
+/* Allow setting debug option on sockets */
+/* Allow modification of routing tables */
+/* Allow setting arbitrary process / process group ownership on
+ sockets */
+/* Allow binding to any address for transparent proxying */
+/* Allow setting TOS (type of service) */
+/* Allow setting promiscuous mode */
+/* Allow clearing driver statistics */
+/* Allow multicasting */
+/* Allow read/write of device-specific registers */
+
+#define CAP_NET_ADMIN 12
+
+/* Allow use of RAW sockets */
+/* Allow use of PACKET sockets */
+
+#define CAP_NET_RAW 13
+
+/* Allow locking of shared memory segments */
+/* Allow mlock and mlockall (which doesn't really have anything to do
+ with IPC) */
+
+#define CAP_IPC_LOCK 14
+
+/* Override IPC ownership checks */
+
+#define CAP_IPC_OWNER 15
+
+/* Insert and remove kernel modules */
+
+#define CAP_SYS_MODULE 16
+
+/* Allow ioperm/iopl access */
+
+#define CAP_SYS_RAWIO 17
+
+/* Allow use of chroot() */
+
+#define CAP_SYS_CHROOT 18
+
+/* Allow ptrace() of any process */
+
+#define CAP_SYS_PTRACE 19
+
+/* Allow configuration of process accounting */
+
+#define CAP_SYS_PACCT 20
+
+/* Allow configuration of the secure attention key */
+/* Allow administration of the random device */
+/* Allow device administration (mknod)*/
+/* Allow examination and configuration of disk quotas */
+/* Allow configuring the kernel's syslog (printk behaviour) */
+/* Allow setting the domainname */
+/* Allow setting the hostname */
+/* Allow calling bdflush() */
+/* Allow mount() and umount(), setting up new smb connection */
+/* Allow some autofs root ioctls */
+/* Allow nfsservctl */
+/* Allow VM86_REQUEST_IRQ */
+/* Allow to read/write pci config on alpha */
+/* Allow irix_prctl on mips (setstacksize) */
+/* Allow flushing all cache on m68k (sys_cacheflush) */
+/* Allow removing semaphores */
+/* Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores
+ and shared memory */
+/* Allow locking/unlocking of shared memory segment */
+/* Allow turning swap on/off */
+/* Allow forged pids on socket credentials passing */
+/* Allow setting readahead and flushing buffers on block devices */
+/* Allow setting geometry in floppy driver */
+/* Allow turning DMA on/off in xd driver */
+/* Allow administration of md devices (mostly the above, but some
+ extra ioctls) */
+/* Allow tuning the ide driver */
+/* Allow access to the nvram device */
+/* Allow administration of apm_bios, serial and bttv (TV) device */
+/* Allow manufacturer commands in isdn CAPI support driver */
+/* Allow reading non-standardized portions of pci configuration space */
+/* Allow DDI debug ioctl on sbpcd driver */
+/* Allow setting up serial ports */
+/* Allow sending raw qic-117 commands */
+/* Allow enabling/disabling tagged queuing on SCSI controllers and sending
+ arbitrary SCSI commands */
+/* Allow setting encryption key on loopback filesystem */
+
+#define CAP_SYS_ADMIN 21
+
+/* Allow use of reboot() */
+
+#define CAP_SYS_BOOT 22
+
+/* Allow raising priority and setting priority on other (different
+ UID) processes */
+/* Allow use of FIFO and round-robin (realtime) scheduling on own
+ processes and setting the scheduling algorithm used by another
+ process. */
+
+#define CAP_SYS_NICE 23
+
+/* Override resource limits. Set resource limits. */
+/* Override quota limits. */
+/* Override reserved space on ext2 filesystem */
+/* NOTE: ext2 honors fsuid when checking for resource overrides, so
+ you can override using fsuid too */
+/* Override size restrictions on IPC message queues */
+/* Allow more than 64hz interrupts from the real-time clock */
+/* Override max number of consoles on console allocation */
+/* Override max number of keymaps */
+
+#define CAP_SYS_RESOURCE 24
+
+/* Allow manipulation of system clock */
+/* Allow irix_stime on mips */
+/* Allow setting the real-time clock */
+
+#define CAP_SYS_TIME 25
+
+/* Allow configuration of tty devices */
+/* Allow vhangup() of tty */
+
+#define CAP_SYS_TTY_CONFIG 26
+
+#ifdef __KERNEL__
+/*
+ * Bounding set
+ */
+extern kernel_cap_t cap_bset;
+
+/*
+ * Internal kernel functions only
+ */
+
+#ifdef STRICT_CAP_T_TYPECHECKS
+
+#define to_cap_t(x) { x }
+#define cap_t(x) (x).cap
+
+#else
+
+#define to_cap_t(x) (x)
+#define cap_t(x) (x)
+
+#endif
+
+#define CAP_EMPTY_SET to_cap_t(0)
+#define CAP_FULL_SET to_cap_t(~0)
+#define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
+#define CAP_INIT_INH_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
+
+#define CAP_TO_MASK(x) (1 << (x))
+#define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag))
+#define cap_lower(c, flag) (cap_t(c) &= ~CAP_TO_MASK(flag))
+#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag) & cap_bset)
+
+static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
+{
+ kernel_cap_t dest;
+ cap_t(dest) = cap_t(a) | cap_t(b);
+ return dest;
+}
+
+static inline kernel_cap_t cap_intersect(kernel_cap_t a, kernel_cap_t b)
+{
+ kernel_cap_t dest;
+ cap_t(dest) = cap_t(a) & cap_t(b);
+ return dest;
+}
+
+static inline kernel_cap_t cap_drop(kernel_cap_t a, kernel_cap_t drop)
+{
+ kernel_cap_t dest;
+ cap_t(dest) = cap_t(a) & ~cap_t(drop);
+ return dest;
+}
+
+static inline kernel_cap_t cap_invert(kernel_cap_t c)
+{
+ kernel_cap_t dest;
+ cap_t(dest) = ~cap_t(c);
+ return dest;
+}
+
+#define cap_isclear(c) (!cap_t(c))
+#define cap_issubset(a,set) (!(cap_t(a) & ~cap_t(set)))
+
+#define cap_clear(c) do { cap_t(c) = 0; } while(0)
+#define cap_set_full(c) do { cap_t(c) = ~0; } while(0)
+#define cap_mask(c,mask) do { cap_t(c) &= cap_t(mask); } while(0)
+
+#define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
+
+#endif /* __KERNEL__ */
+
+#endif /* !_LINUX_CAPABILITY_H */
diff --git a/pfinet/linux-src/include/linux/capi.h b/pfinet/linux-src/include/linux/capi.h
new file mode 100644
index 00000000..9876da08
--- /dev/null
+++ b/pfinet/linux-src/include/linux/capi.h
@@ -0,0 +1,127 @@
+/*
+ * $Id: capi.h,v 1.1 1997/03/04 21:27:33 calle Exp $
+ *
+ * CAPI 2.0 Interface for Linux
+ *
+ * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: capi.h,v $
+ * Revision 1.1 1997/03/04 21:27:33 calle
+ * First version in isdn4linux
+ *
+ * Revision 2.2 1997/02/12 09:31:39 calle
+ * new version
+ *
+ * Revision 1.1 1997/01/31 10:32:20 calle
+ * Initial revision
+ *
+ *
+ */
+
+#ifndef __LINUX_CAPI_H__
+#define __LINUX_CAPI_H__
+
+#include <asm/types.h>
+#include <linux/ioctl.h>
+#ifndef __KERNEL__
+#include <linux/kernelcapi.h>
+#endif
+
+/*
+ * CAPI_REGISTER
+ */
+
+typedef struct capi_register_params { /* CAPI_REGISTER */
+ __u32 level3cnt; /* No. of simulatneous user data connections */
+ __u32 datablkcnt; /* No. of buffered data messages */
+ __u32 datablklen; /* Size of buffered data messages */
+} capi_register_params;
+
+#define CAPI_REGISTER _IOW('C',0x01,struct capi_register_params)
+
+/*
+ * CAPI_GET_MANUFACTURER
+ */
+
+#define CAPI_MANUFACTURER_LEN 64
+
+#define CAPI_GET_MANUFACTURER _IOWR('C',0x06,CAPI_MANUFACTURER_LEN)
+
+/*
+ * CAPI_GET_VERSION
+ */
+
+typedef struct capi_version {
+ __u32 majorversion;
+ __u32 minorversion;
+ __u32 majormanuversion;
+ __u32 minormanuversion;
+} capi_version;
+
+#define CAPI_GET_VERSION _IOWR('C',0x07,struct capi_version)
+
+/*
+ * CAPI_GET_SERIAL
+ */
+
+#define CAPI_SERIAL_LEN 8
+#define CAPI_GET_SERIAL _IOWR('C',0x08, CAPI_SERIAL_LEN)
+
+/*
+ * CAPI_GET_PROFILE
+ */
+
+typedef struct capi_profile {
+ __u16 ncontroller; /* number of installed controller */
+ __u16 nbchannel; /* number of B-Channels */
+ __u32 goptions; /* global options */
+ __u32 support1; /* B1 protocols support */
+ __u32 support2; /* B2 protocols support */
+ __u32 support3; /* B3 protocols support */
+ __u32 reserved[6]; /* reserved */
+ __u32 manu[5]; /* manufacturer specific information */
+} capi_profile;
+
+#define CAPI_GET_PROFILE _IOWR('C',0x09,struct capi_profile)
+
+typedef struct capi_manufacturer_cmd {
+ unsigned long cmd;
+ void *data;
+} capi_manufacturer_cmd;
+
+/*
+ * CAPI_MANUFACTURER_CMD
+ */
+
+#define CAPI_MANUFACTURER_CMD _IOWR('C',0x20, struct capi_manufacturer_cmd)
+
+/*
+ * CAPI_GET_ERRCODE
+ * capi errcode is set, * if read, write, or ioctl returns EIO,
+ * ioctl returns errcode directly, and in arg, if != 0
+ */
+
+#define CAPI_GET_ERRCODE _IOR('C',0x21, __u16)
+
+/*
+ * CAPI_INSTALLED
+ */
+#define CAPI_INSTALLED _IOR('C',0x22, __u16)
+
+/*
+ * member contr is input for
+ * CAPI_GET_MANUFACTURER, CAPI_VERSION, CAPI_GET_SERIAL
+ * and CAPI_GET_PROFILE
+ */
+typedef union capi_ioctl_struct {
+ __u32 contr;
+ capi_register_params rparams;
+ __u8 manufacturer[CAPI_MANUFACTURER_LEN];
+ capi_version version;
+ __u8 serial[CAPI_SERIAL_LEN];
+ capi_profile profile;
+ capi_manufacturer_cmd cmd;
+ __u16 errcode;
+} capi_ioctl_struct;
+
+#endif /* __LINUX_CAPI_H__ */
diff --git a/pfinet/linux-src/include/linux/cd1400.h b/pfinet/linux-src/include/linux/cd1400.h
new file mode 100644
index 00000000..d07d1e61
--- /dev/null
+++ b/pfinet/linux-src/include/linux/cd1400.h
@@ -0,0 +1,292 @@
+/*****************************************************************************/
+
+/*
+ * cd1400.h -- cd1400 UART hardware info.
+ *
+ * Copyright (C) 1996-1998 Stallion Technologies (support@stallion.oz.au).
+ * Copyright (C) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*****************************************************************************/
+#ifndef _CD1400_H
+#define _CD1400_H
+/*****************************************************************************/
+
+/*
+ * Define the number of async ports per cd1400 uart chip.
+ */
+#define CD1400_PORTS 4
+
+/*
+ * Define the cd1400 uarts internal FIFO sizes.
+ */
+#define CD1400_TXFIFOSIZE 12
+#define CD1400_RXFIFOSIZE 12
+
+/*
+ * Local RX FIFO thresh hold level. Also define the RTS thresh hold
+ * based on the RX thresh hold.
+ */
+#define FIFO_RXTHRESHOLD 6
+#define FIFO_RTSTHRESHOLD 7
+
+/*****************************************************************************/
+
+/*
+ * Define the cd1400 register addresses. These are all the valid
+ * registers with the cd1400. Some are global, some virtual, some
+ * per port.
+ */
+#define GFRCR 0x40
+#define CAR 0x68
+#define GCR 0x4b
+#define SVRR 0x67
+#define RICR 0x44
+#define TICR 0x45
+#define MICR 0x46
+#define RIR 0x6b
+#define TIR 0x6a
+#define MIR 0x69
+#define PPR 0x7e
+
+#define RIVR 0x43
+#define TIVR 0x42
+#define MIVR 0x41
+#define TDR 0x63
+#define RDSR 0x62
+#define MISR 0x4c
+#define EOSRR 0x60
+
+#define LIVR 0x18
+#define CCR 0x05
+#define SRER 0x06
+#define COR1 0x08
+#define COR2 0x09
+#define COR3 0x0a
+#define COR4 0x1e
+#define COR5 0x1f
+#define CCSR 0x0b
+#define RDCR 0x0e
+#define SCHR1 0x1a
+#define SCHR2 0x1b
+#define SCHR3 0x1c
+#define SCHR4 0x1d
+#define SCRL 0x22
+#define SCRH 0x23
+#define LNC 0x24
+#define MCOR1 0x15
+#define MCOR2 0x16
+#define RTPR 0x21
+#define MSVR1 0x6c
+#define MSVR2 0x6d
+#define PSVR 0x6f
+#define RBPR 0x78
+#define RCOR 0x7c
+#define TBPR 0x72
+#define TCOR 0x76
+
+/*****************************************************************************/
+
+/*
+ * Define the set of baud rate clock divisors.
+ */
+#define CD1400_CLK0 8
+#define CD1400_CLK1 32
+#define CD1400_CLK2 128
+#define CD1400_CLK3 512
+#define CD1400_CLK4 2048
+
+#define CD1400_NUMCLKS 5
+
+/*****************************************************************************/
+
+/*
+ * Define the clock pre-scalar value to be a 5 ms clock. This should be
+ * OK for now. It would probably be better to make it 10 ms, but we
+ * can't fit that divisor into 8 bits!
+ */
+#define PPR_SCALAR 244
+
+/*****************************************************************************/
+
+/*
+ * Define values used to set character size options.
+ */
+#define COR1_CHL5 0x00
+#define COR1_CHL6 0x01
+#define COR1_CHL7 0x02
+#define COR1_CHL8 0x03
+
+/*
+ * Define values used to set the number of stop bits.
+ */
+#define COR1_STOP1 0x00
+#define COR1_STOP15 0x04
+#define COR1_STOP2 0x08
+
+/*
+ * Define values used to set the parity scheme in use.
+ */
+#define COR1_PARNONE 0x00
+#define COR1_PARFORCE 0x20
+#define COR1_PARENB 0x40
+#define COR1_PARIGNORE 0x10
+
+#define COR1_PARODD 0x80
+#define COR1_PAREVEN 0x00
+
+#define COR2_IXM 0x80
+#define COR2_TXIBE 0x40
+#define COR2_ETC 0x20
+#define COR2_LLM 0x10
+#define COR2_RLM 0x08
+#define COR2_RTSAO 0x04
+#define COR2_CTSAE 0x02
+
+#define COR3_SCDRNG 0x80
+#define COR3_SCD34 0x40
+#define COR3_FCT 0x20
+#define COR3_SCD12 0x10
+
+/*
+ * Define values used by COR4.
+ */
+#define COR4_BRKINT 0x08
+#define COR4_IGNBRK 0x18
+
+/*****************************************************************************/
+
+/*
+ * Define the modem control register values.
+ * Note that the actual hardware is a little different to the conventional
+ * pin names on the cd1400.
+ */
+#define MSVR1_DTR 0x01
+#define MSVR1_DSR 0x10
+#define MSVR1_RI 0x20
+#define MSVR1_CTS 0x40
+#define MSVR1_DCD 0x80
+
+#define MSVR2_RTS 0x02
+#define MSVR2_DSR 0x10
+#define MSVR2_RI 0x20
+#define MSVR2_CTS 0x40
+#define MSVR2_DCD 0x80
+
+#define MCOR1_DCD 0x80
+#define MCOR1_CTS 0x40
+#define MCOR1_RI 0x20
+#define MCOR1_DSR 0x10
+
+#define MCOR2_DCD 0x80
+#define MCOR2_CTS 0x40
+#define MCOR2_RI 0x20
+#define MCOR2_DSR 0x10
+
+/*****************************************************************************/
+
+/*
+ * Define the bits used with the service (interrupt) enable register.
+ */
+#define SRER_NNDT 0x01
+#define SRER_TXEMPTY 0x02
+#define SRER_TXDATA 0x04
+#define SRER_RXDATA 0x10
+#define SRER_MODEM 0x80
+
+/*****************************************************************************/
+
+/*
+ * Define operational commands for the command register.
+ */
+#define CCR_RESET 0x80
+#define CCR_CORCHANGE 0x4e
+#define CCR_SENDCH 0x20
+#define CCR_CHANCTRL 0x10
+
+#define CCR_TXENABLE (CCR_CHANCTRL | 0x08)
+#define CCR_TXDISABLE (CCR_CHANCTRL | 0x04)
+#define CCR_RXENABLE (CCR_CHANCTRL | 0x02)
+#define CCR_RXDISABLE (CCR_CHANCTRL | 0x01)
+
+#define CCR_SENDSCHR1 (CCR_SENDCH | 0x01)
+#define CCR_SENDSCHR2 (CCR_SENDCH | 0x02)
+#define CCR_SENDSCHR3 (CCR_SENDCH | 0x03)
+#define CCR_SENDSCHR4 (CCR_SENDCH | 0x04)
+
+#define CCR_RESETCHAN (CCR_RESET | 0x00)
+#define CCR_RESETFULL (CCR_RESET | 0x01)
+#define CCR_TXFLUSHFIFO (CCR_RESET | 0x02)
+
+#define CCR_MAXWAIT 10000
+
+/*****************************************************************************/
+
+/*
+ * Define the valid acknowledgement types (for hw ack cycle).
+ */
+#define ACK_TYPMASK 0x07
+#define ACK_TYPTX 0x02
+#define ACK_TYPMDM 0x01
+#define ACK_TYPRXGOOD 0x03
+#define ACK_TYPRXBAD 0x07
+
+#define SVRR_RX 0x01
+#define SVRR_TX 0x02
+#define SVRR_MDM 0x04
+
+#define ST_OVERRUN 0x01
+#define ST_FRAMING 0x02
+#define ST_PARITY 0x04
+#define ST_BREAK 0x08
+#define ST_SCHAR1 0x10
+#define ST_SCHAR2 0x20
+#define ST_SCHAR3 0x30
+#define ST_SCHAR4 0x40
+#define ST_RANGE 0x70
+#define ST_SCHARMASK 0x70
+#define ST_TIMEOUT 0x80
+
+#define MISR_DCD 0x80
+#define MISR_CTS 0x40
+#define MISR_RI 0x20
+#define MISR_DSR 0x10
+
+/*****************************************************************************/
+
+/*
+ * Defines for the CCSR status register.
+ */
+#define CCSR_RXENABLED 0x80
+#define CCSR_RXFLOWON 0x40
+#define CCSR_RXFLOWOFF 0x20
+#define CCSR_TXENABLED 0x08
+#define CCSR_TXFLOWON 0x04
+#define CCSR_TXFLOWOFF 0x02
+
+/*****************************************************************************/
+
+/*
+ * Define the embedded commands.
+ */
+#define ETC_CMD 0x00
+#define ETC_STARTBREAK 0x81
+#define ETC_DELAY 0x82
+#define ETC_STOPBREAK 0x83
+
+/*****************************************************************************/
+#endif
diff --git a/pfinet/linux-src/include/linux/cdk.h b/pfinet/linux-src/include/linux/cdk.h
new file mode 100644
index 00000000..2180e433
--- /dev/null
+++ b/pfinet/linux-src/include/linux/cdk.h
@@ -0,0 +1,486 @@
+/*****************************************************************************/
+
+/*
+ * cdk.h -- CDK interface definitions.
+ *
+ * Copyright (C) 1996-1998 Stallion Technologies (support@stallion.oz.au).
+ * Copyright (C) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*****************************************************************************/
+#ifndef _CDK_H
+#define _CDK_H
+/*****************************************************************************/
+
+#pragma pack(2)
+
+/*
+ * The following set of definitions is used to communicate with the
+ * shared memory interface of the Stallion intelligent multiport serial
+ * boards. The definitions in this file are taken directly from the
+ * document titled "Generic Stackable Interface, Downloader and
+ * Communications Development Kit".
+ */
+
+/*
+ * Define the set of important shared memory addresses. These are
+ * required to initialize the board and get things started. All of these
+ * addresses are relative to the start of the shared memory.
+ */
+#define CDK_SIGADDR 0x200
+#define CDK_FEATADDR 0x280
+#define CDK_CDKADDR 0x300
+#define CDK_RDYADDR 0x262
+
+#define CDK_ALIVEMARKER 13
+
+/*
+ * On hardware power up the ROMs located on the EasyConnection 8/64 will
+ * fill out the following signature information into shared memory. This
+ * way the host system can quickly determine that the board is present
+ * and is operational.
+ */
+typedef struct cdkecpsig {
+ unsigned long magic;
+ unsigned short romver;
+ unsigned short cputype;
+ unsigned char panelid[8];
+} cdkecpsig_t;
+
+#define ECP_MAGIC 0x21504345
+
+/*
+ * On hardware power up the ROMs located on the ONboard, Stallion and
+ * Brumbys will fill out the following signature information into shared
+ * memory. This way the host system can quickly determine that the board
+ * is present and is operational.
+ */
+typedef struct cdkonbsig {
+ unsigned short magic0;
+ unsigned short magic1;
+ unsigned short magic2;
+ unsigned short magic3;
+ unsigned short romver;
+ unsigned short memoff;
+ unsigned short memseg;
+ unsigned short amask0;
+ unsigned short pic;
+ unsigned short status;
+ unsigned short btype;
+ unsigned short clkticks;
+ unsigned short clkspeed;
+ unsigned short amask1;
+ unsigned short amask2;
+} cdkonbsig_t;
+
+#define ONB_MAGIC0 0xf2a7
+#define ONB_MAGIC1 0xa149
+#define ONB_MAGIC2 0x6352
+#define ONB_MAGIC3 0xf121
+
+/*
+ * Define the feature area structure. The feature area is the set of
+ * startup parameters used by the slave image when it starts executing.
+ * They allow for the specification of buffer sizes, debug trace, etc.
+ */
+typedef struct cdkfeature {
+ unsigned long debug;
+ unsigned long banner;
+ unsigned long etype;
+ unsigned long nrdevs;
+ unsigned long brdspec;
+ unsigned long txrqsize;
+ unsigned long rxrqsize;
+ unsigned long flags;
+} cdkfeature_t;
+
+#define ETYP_DDK 0
+#define ETYP_CDK 1
+
+/*
+ * Define the CDK header structure. This is the info that the slave
+ * environment sets up after it has been downloaded and started. It
+ * essentially provides a memory map for the shared memory interface.
+ */
+typedef struct cdkhdr {
+ unsigned short command;
+ unsigned short status;
+ unsigned short port;
+ unsigned short mode;
+ unsigned long cmd_buf[14];
+ unsigned short alive_cnt;
+ unsigned short intrpt_mode;
+ unsigned char intrpt_id[8];
+ unsigned char ver_release;
+ unsigned char ver_modification;
+ unsigned char ver_fix;
+ unsigned char deadman_restart;
+ unsigned short deadman;
+ unsigned short nrdevs;
+ unsigned long memp;
+ unsigned long hostp;
+ unsigned long slavep;
+ unsigned char hostreq;
+ unsigned char slavereq;
+ unsigned char cmd_reserved[30];
+} cdkhdr_t;
+
+#define MODE_DDK 0
+#define MODE_CDK 1
+
+#define IMD_INTR 0x0
+#define IMD_PPINTR 0x1
+#define IMD_POLL 0xff
+
+/*
+ * Define the memory mapping structure. This structure is pointed to by
+ * the memp field in the stlcdkhdr struct. As many as these structures
+ * as required are layed out in shared memory to define how the rest of
+ * shared memory is divided up. There will be one for each port.
+ */
+typedef struct cdkmem {
+ unsigned short dtype;
+ unsigned long offset;
+} cdkmem_t;
+
+#define TYP_UNDEFINED 0x0
+#define TYP_ASYNCTRL 0x1
+#define TYP_ASYNC 0x20
+#define TYP_PARALLEL 0x40
+#define TYP_SYNCX21 0x60
+
+/*****************************************************************************/
+
+/*
+ * Following is a set of defines and structures used to actually deal
+ * with the serial ports on the board. Firstly is the set of commands
+ * that can be applied to ports.
+ */
+#define ASYCMD (((unsigned long) 'a') << 8)
+
+#define A_NULL (ASYCMD | 0)
+#define A_FLUSH (ASYCMD | 1)
+#define A_BREAK (ASYCMD | 2)
+#define A_GETPORT (ASYCMD | 3)
+#define A_SETPORT (ASYCMD | 4)
+#define A_SETPORTF (ASYCMD | 5)
+#define A_SETPORTFTX (ASYCMD | 6)
+#define A_SETPORTFRX (ASYCMD | 7)
+#define A_GETSIGNALS (ASYCMD | 8)
+#define A_SETSIGNALS (ASYCMD | 9)
+#define A_SETSIGNALSF (ASYCMD | 10)
+#define A_SETSIGNALSFTX (ASYCMD | 11)
+#define A_SETSIGNALSFRX (ASYCMD | 12)
+#define A_GETNOTIFY (ASYCMD | 13)
+#define A_SETNOTIFY (ASYCMD | 14)
+#define A_NOTIFY (ASYCMD | 15)
+#define A_PORTCTRL (ASYCMD | 16)
+#define A_GETSTATS (ASYCMD | 17)
+#define A_RQSTATE (ASYCMD | 18)
+#define A_FLOWSTATE (ASYCMD | 19)
+#define A_CLEARSTATS (ASYCMD | 20)
+
+/*
+ * Define those arguments used for simple commands.
+ */
+#define FLUSHRX 0x1
+#define FLUSHTX 0x2
+
+#define BREAKON -1
+#define BREAKOFF -2
+
+/*
+ * Define the port setting structure, and all those defines that go along
+ * with it. Basically this structure defines the characteristics of this
+ * port: baud rate, chars, parity, input/output char cooking etc.
+ */
+typedef struct asyport {
+ unsigned long baudout;
+ unsigned long baudin;
+ unsigned long iflag;
+ unsigned long oflag;
+ unsigned long lflag;
+ unsigned long pflag;
+ unsigned long flow;
+ unsigned long spare1;
+ unsigned short vtime;
+ unsigned short vmin;
+ unsigned short txlo;
+ unsigned short txhi;
+ unsigned short rxlo;
+ unsigned short rxhi;
+ unsigned short rxhog;
+ unsigned short spare2;
+ unsigned char csize;
+ unsigned char stopbs;
+ unsigned char parity;
+ unsigned char stopin;
+ unsigned char startin;
+ unsigned char stopout;
+ unsigned char startout;
+ unsigned char parmark;
+ unsigned char brkmark;
+ unsigned char cc[11];
+} asyport_t;
+
+#define PT_STOP1 0x0
+#define PT_STOP15 0x1
+#define PT_STOP2 0x2
+
+#define PT_NOPARITY 0x0
+#define PT_ODDPARITY 0x1
+#define PT_EVENPARITY 0x2
+#define PT_MARKPARITY 0x3
+#define PT_SPACEPARITY 0x4
+
+#define F_NONE 0x0
+#define F_IXON 0x1
+#define F_IXOFF 0x2
+#define F_IXANY 0x4
+#define F_IOXANY 0x8
+#define F_RTSFLOW 0x10
+#define F_CTSFLOW 0x20
+#define F_DTRFLOW 0x40
+#define F_DCDFLOW 0x80
+#define F_DSROFLOW 0x100
+#define F_DSRIFLOW 0x200
+
+#define FI_NORX 0x1
+#define FI_RAW 0x2
+#define FI_ISTRIP 0x4
+#define FI_UCLC 0x8
+#define FI_INLCR 0x10
+#define FI_ICRNL 0x20
+#define FI_IGNCR 0x40
+#define FI_IGNBREAK 0x80
+#define FI_DSCRDBREAK 0x100
+#define FI_1MARKBREAK 0x200
+#define FI_2MARKBREAK 0x400
+#define FI_XCHNGBREAK 0x800
+#define FI_IGNRXERRS 0x1000
+#define FI_DSCDRXERRS 0x2000
+#define FI_1MARKRXERRS 0x4000
+#define FI_2MARKRXERRS 0x8000
+#define FI_XCHNGRXERRS 0x10000
+#define FI_DSCRDNULL 0x20000
+
+#define FO_OLCUC 0x1
+#define FO_ONLCR 0x2
+#define FO_OOCRNL 0x4
+#define FO_ONOCR 0x8
+#define FO_ONLRET 0x10
+#define FO_ONL 0x20
+#define FO_OBS 0x40
+#define FO_OVT 0x80
+#define FO_OFF 0x100
+#define FO_OTAB1 0x200
+#define FO_OTAB2 0x400
+#define FO_OTAB3 0x800
+#define FO_OCR1 0x1000
+#define FO_OCR2 0x2000
+#define FO_OCR3 0x4000
+#define FO_OFILL 0x8000
+#define FO_ODELL 0x10000
+
+#define P_RTSLOCK 0x1
+#define P_CTSLOCK 0x2
+#define P_MAPRTS 0x4
+#define P_MAPCTS 0x8
+#define P_LOOPBACK 0x10
+#define P_DTRFOLLOW 0x20
+#define P_FAKEDCD 0x40
+
+#define P_RXIMIN 0x10000
+#define P_RXITIME 0x20000
+#define P_RXTHOLD 0x40000
+
+/*
+ * Define a structure to communicate serial port signal and data state
+ * information.
+ */
+typedef struct asysigs {
+ unsigned long data;
+ unsigned long signal;
+ unsigned long sigvalue;
+} asysigs_t;
+
+#define DT_TXBUSY 0x1
+#define DT_TXEMPTY 0x2
+#define DT_TXLOW 0x4
+#define DT_TXHIGH 0x8
+#define DT_TXFULL 0x10
+#define DT_TXHOG 0x20
+#define DT_TXFLOWED 0x40
+#define DT_TXBREAK 0x80
+
+#define DT_RXBUSY 0x100
+#define DT_RXEMPTY 0x200
+#define DT_RXLOW 0x400
+#define DT_RXHIGH 0x800
+#define DT_RXFULL 0x1000
+#define DT_RXHOG 0x2000
+#define DT_RXFLOWED 0x4000
+#define DT_RXBREAK 0x8000
+
+#define SG_DTR 0x1
+#define SG_DCD 0x2
+#define SG_RTS 0x4
+#define SG_CTS 0x8
+#define SG_DSR 0x10
+#define SG_RI 0x20
+
+/*
+ * Define the notification setting structure. This is used to tell the
+ * port what events we want to be informed about. Fields here use the
+ * same defines as for the asysigs structure above.
+ */
+typedef struct asynotify {
+ unsigned long ctrl;
+ unsigned long data;
+ unsigned long signal;
+ unsigned long sigvalue;
+} asynotify_t;
+
+/*
+ * Define the port control structure. It is used to do fine grain
+ * control operations on the port.
+ */
+typedef struct {
+ unsigned long rxctrl;
+ unsigned long txctrl;
+ char rximdch;
+ char tximdch;
+ char spare1;
+ char spare2;
+} asyctrl_t;
+
+#define CT_ENABLE 0x1
+#define CT_DISABLE 0x2
+#define CT_STOP 0x4
+#define CT_START 0x8
+#define CT_STARTFLOW 0x10
+#define CT_STOPFLOW 0x20
+#define CT_SENDCHR 0x40
+
+/*
+ * Define the stats structure kept for each port. This is a useful set
+ * of data collected for each port on the slave. The A_GETSTATS command
+ * is used to retrieve this data from the slave.
+ */
+typedef struct asystats {
+ unsigned long opens;
+ unsigned long txchars;
+ unsigned long rxchars;
+ unsigned long txringq;
+ unsigned long rxringq;
+ unsigned long txmsgs;
+ unsigned long rxmsgs;
+ unsigned long txflushes;
+ unsigned long rxflushes;
+ unsigned long overruns;
+ unsigned long framing;
+ unsigned long parity;
+ unsigned long ringover;
+ unsigned long lost;
+ unsigned long rxstart;
+ unsigned long rxstop;
+ unsigned long txstart;
+ unsigned long txstop;
+ unsigned long dcdcnt;
+ unsigned long dtrcnt;
+ unsigned long ctscnt;
+ unsigned long rtscnt;
+ unsigned long dsrcnt;
+ unsigned long ricnt;
+ unsigned long txbreaks;
+ unsigned long rxbreaks;
+ unsigned long signals;
+ unsigned long state;
+ unsigned long hwid;
+} asystats_t;
+
+/*****************************************************************************/
+
+/*
+ * All command and control communication with a device on the slave is
+ * via a control block in shared memory. Each device has its own control
+ * block, defined by the following structure. The control block allows
+ * the host to open, close and control the device on the slave.
+ */
+typedef struct cdkctrl {
+ unsigned char open;
+ unsigned char close;
+ unsigned long openarg;
+ unsigned long closearg;
+ unsigned long cmd;
+ unsigned long status;
+ unsigned long args[32];
+} cdkctrl_t;
+
+/*
+ * Each device on the slave passes data to and from the host via a ring
+ * queue in shared memory. Define a ring queue structure to hold the
+ * vital information about each ring queue. Two ring queues will be
+ * allocated for each port, one for receive data and one for transmit
+ * data.
+ */
+typedef struct cdkasyrq {
+ unsigned long offset;
+ unsigned short size;
+ unsigned short head;
+ unsigned short tail;
+} cdkasyrq_t;
+
+/*
+ * Each asynchronous port is defined in shared memory by the following
+ * structure. It contains a control block to command a device, and also
+ * the necessary data channel information as well.
+ */
+typedef struct cdkasy {
+ cdkctrl_t ctrl;
+ unsigned short notify;
+ asynotify_t changed;
+ unsigned short receive;
+ cdkasyrq_t rxq;
+ unsigned short transmit;
+ cdkasyrq_t txq;
+} cdkasy_t;
+
+#pragma pack()
+
+/*****************************************************************************/
+
+/*
+ * Define the set of ioctls used by the driver to do special things
+ * to the board. These include interrupting it, and initializing
+ * the driver after board startup and shutdown.
+ */
+#include <linux/ioctl.h>
+
+#define STL_BINTR _IO('s',20)
+#define STL_BSTART _IO('s',21)
+#define STL_BSTOP _IO('s',22)
+#define STL_BRESET _IO('s',23)
+
+/*
+ * Define a set of ioctl extensions, used to get at special stuff.
+ */
+#define STL_GETPFLAG _IO('s',80)
+#define STL_SETPFLAG _IO('s',81)
+
+/*****************************************************************************/
+#endif
diff --git a/pfinet/linux-src/include/linux/cdrom.h b/pfinet/linux-src/include/linux/cdrom.h
new file mode 100644
index 00000000..a8c028fb
--- /dev/null
+++ b/pfinet/linux-src/include/linux/cdrom.h
@@ -0,0 +1,433 @@
+/*
+ * -- <linux/cdrom.h>
+ * General header file for linux CD-ROM drivers
+ * Copyright (C) 1992 David Giller, rafetmad@oxy.edu
+ * 1994, 1995 Eberhard Moenkeberg, emoenke@gwdg.de
+ * 1996 David van Leeuwen, david@tm.tno.nl
+ * 1997, 1998 Erik Andersen, andersee@debian.org
+ * 1998, 1999 Jens Axboe, axboe@image.dk
+ */
+
+#ifndef _LINUX_CDROM_H
+#define _LINUX_CDROM_H
+
+/*******************************************************
+ * As of Linux 2.1.x, all Linux CD-ROM application programs will use this
+ * (and only this) include file. It is my hope to provide Linux with
+ * a uniform interface between software accessing CD-ROMs and the various
+ * device drivers that actually talk to the drives. There may still be
+ * 23 different kinds of strange CD-ROM drives, but at least there will
+ * now be one, and only one, Linux CD-ROM interface.
+ *
+ * Additionally, as of Linux 2.1.x, all Linux application programs
+ * should use the O_NONBLOCK option when opening a CD-ROM device
+ * for subsequent ioctl commands. This allows for neat system errors
+ * like "No medium found" or "Wrong medium type" upon attempting to
+ * mount or play an empty slot, mount an audio disc, or play a data disc.
+ * Generally, changing an application program to support O_NONBLOCK
+ * is as easy as the following:
+ * - drive = open("/dev/cdrom", O_RDONLY);
+ * + drive = open("/dev/cdrom", O_RDONLY | O_NONBLOCK);
+ * It is worth the small change.
+ *
+ * Patches for many common CD programs (provided by David A. van Leeuwen)
+ * can be found at: ftp://ftp.gwdg.de/pub/linux/cdrom/drivers/cm206/
+ *
+ *******************************************************/
+
+/* When a driver supports a certain function, but the cdrom drive we are
+ * using doesn't, we will return the error EDRIVE_CANT_DO_THIS. We will
+ * borrow the "Operation not supported" error from the network folks to
+ * accomplish this. Maybe someday we will get a more targeted error code,
+ * but this will do for now... */
+#define EDRIVE_CANT_DO_THIS EOPNOTSUPP
+
+/*******************************************************
+ * The CD-ROM IOCTL commands -- these should be supported by
+ * all the various cdrom drivers. For the CD-ROM ioctls, we
+ * will commandeer byte 0x53, or 'S'.
+ *******************************************************/
+#define CDROMPAUSE 0x5301 /* Pause Audio Operation */
+#define CDROMRESUME 0x5302 /* Resume paused Audio Operation */
+#define CDROMPLAYMSF 0x5303 /* Play Audio MSF (struct cdrom_msf) */
+#define CDROMPLAYTRKIND 0x5304 /* Play Audio Track/index
+ (struct cdrom_ti) */
+#define CDROMREADTOCHDR 0x5305 /* Read TOC header
+ (struct cdrom_tochdr) */
+#define CDROMREADTOCENTRY 0x5306 /* Read TOC entry
+ (struct cdrom_tocentry) */
+#define CDROMSTOP 0x5307 /* Stop the cdrom drive */
+#define CDROMSTART 0x5308 /* Start the cdrom drive */
+#define CDROMEJECT 0x5309 /* Ejects the cdrom media */
+#define CDROMVOLCTRL 0x530a /* Control output volume
+ (struct cdrom_volctrl) */
+#define CDROMSUBCHNL 0x530b /* Read subchannel data
+ (struct cdrom_subchnl) */
+#define CDROMREADMODE2 0x530c /* Read CDROM mode 2 data (2336 Bytes)
+ (struct cdrom_read) */
+#define CDROMREADMODE1 0x530d /* Read CDROM mode 1 data (2048 Bytes)
+ (struct cdrom_read) */
+#define CDROMREADAUDIO 0x530e /* (struct cdrom_read_audio) */
+#define CDROMEJECT_SW 0x530f /* enable(1)/disable(0) auto-ejecting */
+#define CDROMMULTISESSION 0x5310 /* Obtain the start-of-last-session
+ address of multi session disks
+ (struct cdrom_multisession) */
+#define CDROM_GET_MCN 0x5311 /* Obtain the "Universal Product Code"
+ if available (struct cdrom_mcn) */
+#define CDROM_GET_UPC CDROM_GET_MCN /* This one is depricated,
+ but here anyway for compatability */
+#define CDROMRESET 0x5312 /* hard-reset the drive */
+#define CDROMVOLREAD 0x5313 /* Get the drive's volume setting
+ (struct cdrom_volctrl) */
+#define CDROMREADRAW 0x5314 /* read data in raw mode (2352 Bytes)
+ (struct cdrom_read) */
+/*
+ * These ioctls are used only used in aztcd.c and optcd.c
+ */
+#define CDROMREADCOOKED 0x5315 /* read data in cooked mode */
+#define CDROMSEEK 0x5316 /* seek msf address */
+
+/*
+ * This ioctl is only used by the scsi-cd driver.
+ It is for playing audio in logical block addressing mode.
+ */
+#define CDROMPLAYBLK 0x5317 /* (struct cdrom_blk) */
+
+/*
+ * These ioctls are used only used in optcd.c
+ */
+#define CDROMREADALL 0x5318 /* read all 2646 bytes */
+#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */
+
+/*
+ * These ioctls are implemented through the uniform CD-ROM driver
+ * They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM
+ * drivers are eventually ported to the uniform CD-ROM driver interface.
+ */
+#define CDROM_SET_OPTIONS 0x5320 /* Set behavior options */
+#define CDROM_CLEAR_OPTIONS 0x5321 /* Clear behavior options */
+#define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */
+#define CDROM_SELECT_DISC 0x5323 /* Select disc (for juke-boxes) */
+#define CDROM_MEDIA_CHANGED 0x5325 /* Check is media changed */
+#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
+#define CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */
+#define CDROM_CHANGER_NSLOTS 0x5328 /* Get number of slots */
+#define CDROM_LOCKDOOR 0x5329 /* lock or unlock door */
+#define CDROM_DEBUG 0x5330 /* Turn debug messages on/off */
+#define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
+
+/* This ioctl is only used by sbpcd at the moment */
+#define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */
+
+/*******************************************************
+ * CDROM IOCTL structures
+ *******************************************************/
+
+/* Address in MSF format */
+struct cdrom_msf0
+{
+ u_char minute;
+ u_char second;
+ u_char frame;
+};
+
+/* Address in either MSF or logical format */
+union cdrom_addr
+{
+ struct cdrom_msf0 msf;
+ int lba;
+};
+
+/* This struct is used by the CDROMPLAYMSF ioctl */
+struct cdrom_msf
+{
+ u_char cdmsf_min0; /* start minute */
+ u_char cdmsf_sec0; /* start second */
+ u_char cdmsf_frame0; /* start frame */
+ u_char cdmsf_min1; /* end minute */
+ u_char cdmsf_sec1; /* end second */
+ u_char cdmsf_frame1; /* end frame */
+};
+
+/* This struct is used by the CDROMPLAYTRKIND ioctl */
+struct cdrom_ti
+{
+ u_char cdti_trk0; /* start track */
+ u_char cdti_ind0; /* start index */
+ u_char cdti_trk1; /* end track */
+ u_char cdti_ind1; /* end index */
+};
+
+/* This struct is used by the CDROMREADTOCHDR ioctl */
+struct cdrom_tochdr
+{
+ u_char cdth_trk0; /* start track */
+ u_char cdth_trk1; /* end track */
+};
+
+/* This struct is used by the CDROMVOLCTRL and CDROMVOLREAD ioctls */
+struct cdrom_volctrl
+{
+ u_char channel0;
+ u_char channel1;
+ u_char channel2;
+ u_char channel3;
+};
+
+/* This struct is used by the CDROMSUBCHNL ioctl */
+struct cdrom_subchnl
+{
+ u_char cdsc_format;
+ u_char cdsc_audiostatus;
+ u_char cdsc_adr: 4;
+ u_char cdsc_ctrl: 4;
+ u_char cdsc_trk;
+ u_char cdsc_ind;
+ union cdrom_addr cdsc_absaddr;
+ union cdrom_addr cdsc_reladdr;
+};
+
+
+/* This struct is used by the CDROMREADTOCENTRY ioctl */
+struct cdrom_tocentry
+{
+ u_char cdte_track;
+ u_char cdte_adr :4;
+ u_char cdte_ctrl :4;
+ u_char cdte_format;
+ union cdrom_addr cdte_addr;
+ u_char cdte_datamode;
+};
+
+/* This struct is used by the CDROMREADMODE1, and CDROMREADMODE2 ioctls */
+struct cdrom_read
+{
+ int cdread_lba;
+ caddr_t cdread_bufaddr;
+ int cdread_buflen;
+};
+
+/* This struct is used by the CDROMREADAUDIO ioctl */
+struct cdrom_read_audio
+{
+ union cdrom_addr addr; /* frame address */
+ u_char addr_format; /* CDROM_LBA or CDROM_MSF */
+ int nframes; /* number of 2352-byte-frames to read at once */
+ u_char *buf; /* frame buffer (size: nframes*2352 bytes) */
+};
+
+/* This struct is used with the CDROMMULTISESSION ioctl */
+struct cdrom_multisession
+{
+ union cdrom_addr addr; /* frame address: start-of-last-session
+ (not the new "frame 16"!). Only valid
+ if the "xa_flag" is true. */
+ u_char xa_flag; /* 1: "is XA disk" */
+ u_char addr_format; /* CDROM_LBA or CDROM_MSF */
+};
+
+/* This struct is used with the CDROM_GET_MCN ioctl.
+ * Very few audio discs actually have Universal Product Code information,
+ * which should just be the Medium Catalog Number on the box. Also note
+ * that the way the codeis written on CD is _not_ uniform across all discs!
+ */
+struct cdrom_mcn
+{
+ u_char medium_catalog_number[14]; /* 13 ASCII digits, null-terminated */
+};
+
+/* This is used by the CDROMPLAYBLK ioctl */
+struct cdrom_blk
+{
+ unsigned from;
+ unsigned short len;
+};
+
+
+/*
+ * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336,
+ * 2340, or 2352 bytes long.
+
+* Sector types of the standard CD-ROM data formats:
+ *
+ * format sector type user data size (bytes)
+ * -----------------------------------------------------------------------------
+ * 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW)
+ * 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE)
+ * 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0)
+ * 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE)
+ * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes)
+ *
+ *
+ * The layout of the standard CD-ROM data formats:
+ * -----------------------------------------------------------------------------
+ * - audio (red): | audio_sample_bytes |
+ * | 2352 |
+ *
+ * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC |
+ * | 12 - 4 - 2048 - 4 - 8 - 276 |
+ *
+ * - data (yellow, mode2): | sync - head - data |
+ * | 12 - 4 - 2336 |
+ *
+ * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC |
+ * | 12 - 4 - 8 - 2048 - 4 - 276 |
+ *
+ * - XA data (green, mode2 form2): | sync - head - sub - data - Spare |
+ * | 12 - 4 - 8 - 2324 - 4 |
+ *
+ */
+
+/* Some generally useful CD-ROM information -- mostly based on the above */
+#define CD_MINS 74 /* max. minutes per CD, not really a limit */
+#define CD_SECS 60 /* seconds per minute */
+#define CD_FRAMES 75 /* frames per second */
+#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */
+#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */
+#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */
+#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */
+#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */
+#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */
+#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */
+#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */
+#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */
+#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */
+#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */
+#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */
+#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */
+/* most drives don't deliver everything: */
+#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/
+#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/
+
+#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */
+#define CD_XA_TAIL (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */
+#define CD_XA_SYNC_HEAD (CD_SYNC_SIZE+CD_XA_HEAD) /* sync bytes + header of XA frame */
+
+/* CD-ROM address types (cdrom_tocentry.cdte_format) */
+#define CDROM_LBA 0x01 /* "logical block": first frame is #0 */
+#define CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */
+
+/* bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl) */
+#define CDROM_DATA_TRACK 0x04
+
+/* The leadout track is always 0xAA, regardless of # of tracks on disc */
+#define CDROM_LEADOUT 0xAA
+
+/* audio states (from SCSI-2, but seen with other drives, too) */
+#define CDROM_AUDIO_INVALID 0x00 /* audio status not supported */
+#define CDROM_AUDIO_PLAY 0x11 /* audio play operation in progress */
+#define CDROM_AUDIO_PAUSED 0x12 /* audio play operation paused */
+#define CDROM_AUDIO_COMPLETED 0x13 /* audio play successfully completed */
+#define CDROM_AUDIO_ERROR 0x14 /* audio play stopped due to error */
+#define CDROM_AUDIO_NO_STATUS 0x15 /* no current audio status to return */
+
+/* CD-ROM-specific SCSI command opcodes */
+#define SCMD_READ_TOC 0x43 /* read table of contents */
+#define SCMD_PLAYAUDIO_MSF 0x47 /* play data at time offset */
+#define SCMD_PLAYAUDIO_TI 0x48 /* play data at track/index */
+#define SCMD_PAUSE_RESUME 0x4B /* pause/resume audio */
+#define SCMD_READ_SUBCHANNEL 0x42 /* read SC info on playing disc */
+#define SCMD_PLAYAUDIO10 0x45 /* play data at logical block */
+
+/* capability flags used with the uniform CD-ROM driver */
+#define CDC_CLOSE_TRAY 0x1 /* caddy systems _can't_ close */
+#define CDC_OPEN_TRAY 0x2 /* but _can_ eject. */
+#define CDC_LOCK 0x4 /* disable manual eject */
+#define CDC_SELECT_SPEED 0x8 /* programmable speed */
+#define CDC_SELECT_DISC 0x10 /* select disc from juke-box */
+#define CDC_MULTI_SESSION 0x20 /* read sessions>1 */
+#define CDC_MCN 0x40 /* Medium Catalog Number */
+#define CDC_MEDIA_CHANGED 0x80 /* media changed */
+#define CDC_PLAY_AUDIO 0x100 /* audio functions */
+#define CDC_RESET 0x200 /* hard reset device */
+#define CDC_IOCTLS 0x400 /* driver has non-standard ioctls */
+#define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */
+
+/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
+#define CDS_NO_INFO 0 /* if not implemented */
+#define CDS_NO_DISC 1
+#define CDS_TRAY_OPEN 2
+#define CDS_DRIVE_NOT_READY 3
+#define CDS_DISC_OK 4
+
+/* return values for the CDROM_DISC_STATUS ioctl */
+/* can also return CDS_NO_[INFO|DISC], from above */
+#define CDS_AUDIO 100
+#define CDS_DATA_1 101
+#define CDS_DATA_2 102
+#define CDS_XA_2_1 103
+#define CDS_XA_2_2 104
+#define CDS_MIXED 105
+
+/* User-configurable behavior options for the uniform CD-ROM driver */
+#define CDO_AUTO_CLOSE 0x1 /* close tray on first open() */
+#define CDO_AUTO_EJECT 0x2 /* open tray on last release() */
+#define CDO_USE_FFLAGS 0x4 /* use O_NONBLOCK information on open */
+#define CDO_LOCK 0x8 /* lock tray on open files */
+#define CDO_CHECK_TYPE 0x10 /* check type on open for data */
+
+/* Special codes used when specifying changer slots. */
+#define CDSL_NONE ((int) (~0U>>1)-1)
+#define CDSL_CURRENT ((int) (~0U>>1))
+
+#ifdef __KERNEL__
+/* Uniform cdrom data structures for cdrom.c */
+struct cdrom_device_info {
+ struct cdrom_device_ops *ops; /* link to device_ops */
+ struct cdrom_device_info *next; /* next device_info for this major */
+ void *handle; /* driver-dependent data */
+/* specifications */
+ kdev_t dev; /* device number */
+ int mask; /* mask of capability: disables them */
+ int speed; /* maximum speed for reading data */
+ int capacity; /* number of discs in jukebox */
+/* device-related storage */
+ int options : 30; /* options flags */
+ unsigned mc_flags : 2; /* media change buffer flags */
+ int use_count; /* number of times device opened */
+ char name[20]; /* name of the device type */
+
+};
+
+struct cdrom_device_ops {
+/* routines */
+ int (*open) (struct cdrom_device_info *, int);
+ void (*release) (struct cdrom_device_info *);
+ int (*drive_status) (struct cdrom_device_info *, int);
+ int (*media_changed) (struct cdrom_device_info *, int);
+ int (*tray_move) (struct cdrom_device_info *, int);
+ int (*lock_door) (struct cdrom_device_info *, int);
+ int (*select_speed) (struct cdrom_device_info *, int);
+ int (*select_disc) (struct cdrom_device_info *, int);
+ int (*get_last_session) (struct cdrom_device_info *,
+ struct cdrom_multisession *);
+ int (*get_mcn) (struct cdrom_device_info *,
+ struct cdrom_mcn *);
+ /* hard reset device */
+ int (*reset) (struct cdrom_device_info *);
+ /* play stuff */
+ int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *);
+ /* dev-specific */
+ int (*dev_ioctl) (struct cdrom_device_info *,
+ unsigned int, unsigned long);
+/* driver specifications */
+ const int capability; /* capability flags */
+ int n_minors; /* number of active minor devices */
+};
+
+/* the general file operations structure: */
+extern struct file_operations cdrom_fops;
+
+extern int register_cdrom(struct cdrom_device_info *cdi);
+extern int unregister_cdrom(struct cdrom_device_info *cdi);
+typedef struct {
+ int data;
+ int audio;
+ int cdi;
+ int xa;
+ long error;
+} tracktype;
+extern void cdrom_count_tracks(struct cdrom_device_info *cdi,tracktype* tracks);
+#endif /* End of kernel only stuff */
+
+#endif /* _LINUX_CDROM_H */
diff --git a/pfinet/linux-src/include/linux/coda.h b/pfinet/linux-src/include/linux/coda.h
new file mode 100644
index 00000000..8cb3ff46
--- /dev/null
+++ b/pfinet/linux-src/include/linux/coda.h
@@ -0,0 +1,800 @@
+/*
+ You may distribute this file under either of the two licenses that
+ follow at your discretion.
+*/
+
+/* BLURB lgpl
+
+ Coda File System
+ Release 5
+
+ Copyright (c) 1987-1999 Carnegie Mellon University
+ Additional copyrights listed below
+
+This code is distributed "AS IS" without warranty of any kind under
+the terms of the GNU Library General Public Licence Version 2, as
+shown in the file LICENSE, or under the license shown below. The
+technical and financial contributors to Coda are listed in the file
+CREDITS.
+
+ Additional copyrights
+*/
+
+/*
+
+ Coda: an Experimental Distributed File System
+ Release 4.0
+
+ Copyright (c) 1987-1999 Carnegie Mellon University
+ All Rights Reserved
+
+Permission to use, copy, modify and distribute this software and its
+documentation is hereby granted, provided that both the copyright
+notice and this permission notice appear in all copies of the
+software, derivative works or modified versions, and any portions
+thereof, and that both notices appear in supporting documentation, and
+that credit is given to Carnegie Mellon University in all documents
+and publicity pertaining to direct or indirect use of this code or its
+derivatives.
+
+CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
+SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
+FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
+DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
+RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
+ANY DERIVATIVE WORK.
+
+Carnegie Mellon encourages users of this software to return any
+improvements or extensions that they make, and to grant Carnegie
+Mellon the rights to redistribute these changes without encumbrance.
+*/
+
+/*
+ *
+ * Based on cfs.h from Mach, but revamped for increased simplicity.
+ * Linux modifications by
+ * Peter Braam, Aug 1996
+ */
+
+#ifndef _CODA_HEADER_
+#define _CODA_HEADER_
+
+
+
+/* Catch new _KERNEL defn for NetBSD */
+#ifdef __NetBSD__
+#include <sys/types.h>
+#endif
+
+#ifndef CODA_MAXSYMLINKS
+#define CODA_MAXSYMLINKS 10
+#endif
+
+#if defined(DJGPP) || defined(__CYGWIN32__)
+#ifdef KERNEL
+typedef unsigned long u_long;
+typedef unsigned int u_int;
+typedef unsigned short u_short;
+typedef u_long ino_t;
+typedef u_long dev_t;
+typedef void * caddr_t;
+#ifdef DOS
+typedef unsigned __int64 u_quad_t;
+#else
+typedef unsigned long long u_quad_t;
+#endif
+
+#define inline
+
+struct timespec {
+ long ts_sec;
+ long ts_nsec;
+};
+#else /* DJGPP but not KERNEL */
+#include <sys/types.h>
+#include <sys/time.h>
+typedef unsigned long long u_quad_t;
+#endif /* !KERNEL */
+#endif /* !DJGPP */
+
+
+#if defined(__linux__)
+#define cdev_t u_quad_t
+#ifndef __KERNEL__
+#if !defined(_UQUAD_T_) && (!defined(__GLIBC__) || __GLIBC__ < 2)
+#define _UQUAD_T_ 1
+typedef unsigned long long u_quad_t;
+#endif
+#else /*__KERNEL__ */
+typedef unsigned long long u_quad_t;
+#endif /* __KERNEL__ */
+#else
+#define cdev_t dev_t
+#endif
+
+#ifdef __CYGWIN32__
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+#endif
+
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+typedef signed char int8_t;
+typedef unsigned char u_int8_t;
+typedef short int16_t;
+typedef unsigned short u_int16_t;
+typedef int int32_t;
+typedef unsigned int u_int32_t;
+#endif
+
+
+/*
+ * Cfs constants
+ */
+#define CODA_MAXNAMLEN 255
+#define CODA_MAXPATHLEN 1024
+#define CODA_MAXSYMLINK 10
+
+/* these are Coda's version of O_RDONLY etc combinations
+ * to deal with VFS open modes
+ */
+#define C_O_READ 0x001
+#define C_O_WRITE 0x002
+#define C_O_TRUNC 0x010
+#define C_O_EXCL 0x100
+#define C_O_CREAT 0x200
+
+/* these are to find mode bits in Venus */
+#define C_M_READ 00400
+#define C_M_WRITE 00200
+
+/* for access Venus will use */
+#define C_A_C_OK 8 /* Test for writing upon create. */
+#define C_A_R_OK 4 /* Test for read permission. */
+#define C_A_W_OK 2 /* Test for write permission. */
+#define C_A_X_OK 1 /* Test for execute permission. */
+#define C_A_F_OK 0 /* Test for existence. */
+
+
+
+#ifndef _VENUS_DIRENT_T_
+#define _VENUS_DIRENT_T_ 1
+struct venus_dirent {
+ unsigned long d_fileno; /* file number of entry */
+ unsigned short d_reclen; /* length of this record */
+ unsigned char d_type; /* file type, see below */
+ unsigned char d_namlen; /* length of string in d_name */
+ char d_name[CODA_MAXNAMLEN + 1];/* name must be no longer than this */
+};
+#undef DIRSIZ
+#define DIRSIZ(dp) ((sizeof (struct venus_dirent) - (CODA_MAXNAMLEN+1)) + \
+ (((dp)->d_namlen+1 + 3) &~ 3))
+
+/*
+ * File types
+ */
+#define CDT_UNKNOWN 0
+#define CDT_FIFO 1
+#define CDT_CHR 2
+#define CDT_DIR 4
+#define CDT_BLK 6
+#define CDT_REG 8
+#define CDT_LNK 10
+#define CDT_SOCK 12
+#define CDT_WHT 14
+
+/*
+ * Convert between stat structure types and directory types.
+ */
+#define IFTOCDT(mode) (((mode) & 0170000) >> 12)
+#define CDTTOIF(dirtype) ((dirtype) << 12)
+
+#endif
+
+#ifndef _FID_T_
+#define _FID_T_ 1
+typedef u_long VolumeId;
+typedef u_long VnodeId;
+typedef u_long Unique_t;
+typedef u_long FileVersion;
+#endif
+
+#ifndef _VICEFID_T_
+#define _VICEFID_T_ 1
+typedef struct ViceFid {
+ VolumeId Volume;
+ VnodeId Vnode;
+ Unique_t Unique;
+} ViceFid;
+#endif /* VICEFID */
+
+
+#ifdef __linux__
+static __inline__ ino_t coda_f2i(struct ViceFid *fid)
+{
+ if ( ! fid )
+ return 0;
+ if (fid->Vnode == 0xfffffffe || fid->Vnode == 0xffffffff)
+ return ((fid->Volume << 20) | (fid->Unique & 0xfffff));
+ else
+ return (fid->Unique + (fid->Vnode<<10) + (fid->Volume<<20));
+}
+
+#else
+#define coda_f2i(fid)\
+ ((fid) ? ((fid)->Unique + ((fid)->Vnode<<10) + ((fid)->Volume<<20)) : 0)
+#endif
+
+
+#ifndef _VUID_T_
+#define _VUID_T_
+typedef u_int32_t vuid_t;
+typedef u_int32_t vgid_t;
+#endif /*_VUID_T_ */
+
+#ifndef _CODACRED_T_
+#define _CODACRED_T_
+struct coda_cred {
+ vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/
+ vgid_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
+};
+#endif
+
+#ifndef _VENUS_VATTR_T_
+#define _VENUS_VATTR_T_
+/*
+ * Vnode types. VNON means no type.
+ */
+enum coda_vtype { C_VNON, C_VREG, C_VDIR, C_VBLK, C_VCHR, C_VLNK, C_VSOCK, C_VFIFO, C_VBAD };
+
+struct coda_vattr {
+ long va_type; /* vnode type (for create) */
+ u_short va_mode; /* files access mode and type */
+ short va_nlink; /* number of references to file */
+ vuid_t va_uid; /* owner user id */
+ vgid_t va_gid; /* owner group id */
+ long va_fileid; /* file id */
+ u_quad_t va_size; /* file size in bytes */
+ long va_blocksize; /* blocksize preferred for i/o */
+ struct timespec va_atime; /* time of last access */
+ struct timespec va_mtime; /* time of last modification */
+ struct timespec va_ctime; /* time file changed */
+ u_long va_gen; /* generation number of file */
+ u_long va_flags; /* flags defined for file */
+ cdev_t va_rdev; /* device special file represents */
+ u_quad_t va_bytes; /* bytes of disk space held by file */
+ u_quad_t va_filerev; /* file modification number */
+};
+
+#endif
+
+/* structure used by CODA_STATFS for getting cache information from venus */
+struct coda_statfs {
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_bavail;
+ int32_t f_files;
+ int32_t f_ffree;
+};
+
+/*
+ * Kernel <--> Venus communications.
+ */
+
+#define CODA_ROOT 2
+#define CODA_SYNC 3
+#define CODA_OPEN 4
+#define CODA_CLOSE 5
+#define CODA_IOCTL 6
+#define CODA_GETATTR 7
+#define CODA_SETATTR 8
+#define CODA_ACCESS 9
+#define CODA_LOOKUP 10
+#define CODA_CREATE 11
+#define CODA_REMOVE 12
+#define CODA_LINK 13
+#define CODA_RENAME 14
+#define CODA_MKDIR 15
+#define CODA_RMDIR 16
+#define CODA_READDIR 17
+#define CODA_SYMLINK 18
+#define CODA_READLINK 19
+#define CODA_FSYNC 20
+#define CODA_INACTIVE 21
+#define CODA_VGET 22
+#define CODA_SIGNAL 23
+#define CODA_REPLACE 24
+#define CODA_FLUSH 25
+#define CODA_PURGEUSER 26
+#define CODA_ZAPFILE 27
+#define CODA_ZAPDIR 28
+#define CODA_PURGEFID 30
+#define CODA_OPEN_BY_PATH 31
+#define CODA_RESOLVE 32
+#define CODA_REINTEGRATE 33
+#define CODA_STATFS 34
+#define CODA_NCALLS 35
+
+#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID)
+
+#define VC_MAXDATASIZE 8192
+#define VC_MAXMSGSIZE sizeof(union inputArgs)+sizeof(union outputArgs) +\
+ VC_MAXDATASIZE
+
+#define CIOC_KERNEL_VERSION _IOWR('c', 10, sizeof (int))
+#if 0
+ /* don't care about kernel version number */
+#define CODA_KERNEL_VERSION 0
+ /* The old venus 4.6 compatible interface */
+#define CODA_KERNEL_VERSION 1
+#endif
+ /* venus_lookup gets an extra parameter to aid windows.*/
+#define CODA_KERNEL_VERSION 2
+
+/*
+ * Venus <-> Coda RPC arguments
+ */
+struct coda_in_hdr {
+ unsigned long opcode;
+ unsigned long unique; /* Keep multiple outstanding msgs distinct */
+ u_short pid; /* Common to all */
+ u_short pgid; /* Common to all */
+ u_short sid; /* Common to all */
+ struct coda_cred cred; /* Common to all */
+};
+
+/* Really important that opcode and unique are 1st two fields! */
+struct coda_out_hdr {
+ unsigned long opcode;
+ unsigned long unique;
+ unsigned long result;
+};
+
+/* coda_root: NO_IN */
+struct coda_root_out {
+ struct coda_out_hdr oh;
+ ViceFid VFid;
+};
+
+struct coda_root_in {
+ struct coda_in_hdr in;
+};
+
+/* coda_sync: */
+/* Nothing needed for coda_sync */
+
+/* coda_open: */
+struct coda_open_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int flags;
+};
+
+struct coda_open_out {
+ struct coda_out_hdr oh;
+ cdev_t dev;
+ ino_t inode;
+};
+
+
+/* coda_close: */
+struct coda_close_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int flags;
+};
+
+struct coda_close_out {
+ struct coda_out_hdr out;
+};
+
+/* coda_ioctl: */
+struct coda_ioctl_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int cmd;
+ int len;
+ int rwflag;
+ char *data; /* Place holder for data. */
+};
+
+struct coda_ioctl_out {
+ struct coda_out_hdr oh;
+ int len;
+ caddr_t data; /* Place holder for data. */
+};
+
+
+/* coda_getattr: */
+struct coda_getattr_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+};
+
+struct coda_getattr_out {
+ struct coda_out_hdr oh;
+ struct coda_vattr attr;
+};
+
+
+/* coda_setattr: NO_OUT */
+struct coda_setattr_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ struct coda_vattr attr;
+};
+
+struct coda_setattr_out {
+ struct coda_out_hdr out;
+};
+
+/* coda_access: NO_OUT */
+struct coda_access_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int flags;
+};
+
+struct coda_access_out {
+ struct coda_out_hdr out;
+};
+
+
+/* lookup flags */
+#define CLU_CASE_SENSITIVE 0x01
+#define CLU_CASE_INSENSITIVE 0x02
+
+/* coda_lookup: */
+struct coda_lookup_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int name; /* Place holder for data. */
+ int flags;
+};
+
+struct coda_lookup_out {
+ struct coda_out_hdr oh;
+ ViceFid VFid;
+ int vtype;
+};
+
+
+/* coda_create: */
+struct coda_create_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ struct coda_vattr attr;
+ int excl;
+ int mode;
+ int name; /* Place holder for data. */
+};
+
+struct coda_create_out {
+ struct coda_out_hdr oh;
+ ViceFid VFid;
+ struct coda_vattr attr;
+};
+
+
+/* coda_remove: NO_OUT */
+struct coda_remove_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int name; /* Place holder for data. */
+};
+
+struct coda_remove_out {
+ struct coda_out_hdr out;
+};
+
+/* coda_link: NO_OUT */
+struct coda_link_in {
+ struct coda_in_hdr ih;
+ ViceFid sourceFid; /* cnode to link *to* */
+ ViceFid destFid; /* Directory in which to place link */
+ int tname; /* Place holder for data. */
+};
+
+struct coda_link_out {
+ struct coda_out_hdr out;
+};
+
+
+/* coda_rename: NO_OUT */
+struct coda_rename_in {
+ struct coda_in_hdr ih;
+ ViceFid sourceFid;
+ int srcname;
+ ViceFid destFid;
+ int destname;
+};
+
+struct coda_rename_out {
+ struct coda_out_hdr out;
+};
+
+/* coda_mkdir: */
+struct coda_mkdir_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ struct coda_vattr attr;
+ int name; /* Place holder for data. */
+};
+
+struct coda_mkdir_out {
+ struct coda_out_hdr oh;
+ ViceFid VFid;
+ struct coda_vattr attr;
+};
+
+
+/* coda_rmdir: NO_OUT */
+struct coda_rmdir_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int name; /* Place holder for data. */
+};
+
+struct coda_rmdir_out {
+ struct coda_out_hdr out;
+};
+
+/* coda_readdir: */
+struct coda_readdir_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int count;
+ int offset;
+};
+
+struct coda_readdir_out {
+ struct coda_out_hdr oh;
+ int size;
+ caddr_t data; /* Place holder for data. */
+};
+
+/* coda_symlink: NO_OUT */
+struct coda_symlink_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid; /* Directory to put symlink in */
+ int srcname;
+ struct coda_vattr attr;
+ int tname;
+};
+
+struct coda_symlink_out {
+ struct coda_out_hdr out;
+};
+
+/* coda_readlink: */
+struct coda_readlink_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+};
+
+struct coda_readlink_out {
+ struct coda_out_hdr oh;
+ int count;
+ caddr_t data; /* Place holder for data. */
+};
+
+
+/* coda_fsync: NO_OUT */
+struct coda_fsync_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+};
+
+struct coda_fsync_out {
+ struct coda_out_hdr out;
+};
+
+/* coda_inactive: NO_OUT */
+struct coda_inactive_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+};
+
+/* coda_vget: */
+struct coda_vget_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+};
+
+struct coda_vget_out {
+ struct coda_out_hdr oh;
+ ViceFid VFid;
+ int vtype;
+};
+
+
+/* CODA_SIGNAL is out-of-band, doesn't need data. */
+/* CODA_INVALIDATE is a venus->kernel call */
+/* CODA_FLUSH is a venus->kernel call */
+
+/* coda_purgeuser: */
+/* CODA_PURGEUSER is a venus->kernel call */
+struct coda_purgeuser_out {
+ struct coda_out_hdr oh;
+ struct coda_cred cred;
+};
+
+/* coda_zapfile: */
+/* CODA_ZAPFILE is a venus->kernel call */
+struct coda_zapfile_out {
+ struct coda_out_hdr oh;
+ ViceFid CodaFid;
+};
+
+/* coda_zapdir: */
+/* CODA_ZAPDIR is a venus->kernel call */
+struct coda_zapdir_out {
+ struct coda_out_hdr oh;
+ ViceFid CodaFid;
+};
+
+/* coda_zapnode: */
+/* CODA_ZAPVNODE is a venus->kernel call */
+struct coda_zapvnode_out {
+ struct coda_out_hdr oh;
+ struct coda_cred cred;
+ ViceFid VFid;
+};
+
+/* coda_purgefid: */
+/* CODA_PURGEFID is a venus->kernel call */
+struct coda_purgefid_out {
+ struct coda_out_hdr oh;
+ ViceFid CodaFid;
+};
+
+/* coda_rdwr: */
+struct coda_rdwr_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int rwflag;
+ int count;
+ int offset;
+ int ioflag;
+ caddr_t data; /* Place holder for data. */
+};
+
+struct coda_rdwr_out {
+ struct coda_out_hdr oh;
+ int rwflag;
+ int count;
+ caddr_t data; /* Place holder for data. */
+};
+
+
+/* coda_replace: */
+/* CODA_REPLACE is a venus->kernel call */
+struct coda_replace_out { /* coda_replace is a venus->kernel call */
+ struct coda_out_hdr oh;
+ ViceFid NewFid;
+ ViceFid OldFid;
+};
+
+/* coda_open_by_path: */
+struct coda_open_by_path_in {
+ struct coda_in_hdr ih;
+ ViceFid VFid;
+ int flags;
+};
+
+struct coda_open_by_path_out {
+ struct coda_out_hdr oh;
+ int path;
+};
+
+/* coda_statfs: NO_IN */
+struct coda_statfs_in {
+ struct coda_in_hdr in;
+};
+
+struct coda_statfs_out {
+ struct coda_out_hdr oh;
+ struct coda_statfs stat;
+};
+
+/*
+ * Occasionally, we don't cache the fid returned by CODA_LOOKUP.
+ * For instance, if the fid is inconsistent.
+ * This case is handled by setting the top bit of the type result parameter.
+ */
+#define CODA_NOCACHE 0x80000000
+
+union inputArgs {
+ struct coda_in_hdr ih; /* NB: every struct below begins with an ih */
+ struct coda_open_in coda_open;
+ struct coda_close_in coda_close;
+ struct coda_ioctl_in coda_ioctl;
+ struct coda_getattr_in coda_getattr;
+ struct coda_setattr_in coda_setattr;
+ struct coda_access_in coda_access;
+ struct coda_lookup_in coda_lookup;
+ struct coda_create_in coda_create;
+ struct coda_remove_in coda_remove;
+ struct coda_link_in coda_link;
+ struct coda_rename_in coda_rename;
+ struct coda_mkdir_in coda_mkdir;
+ struct coda_rmdir_in coda_rmdir;
+ struct coda_readdir_in coda_readdir;
+ struct coda_symlink_in coda_symlink;
+ struct coda_readlink_in coda_readlink;
+ struct coda_fsync_in coda_fsync;
+ struct coda_inactive_in coda_inactive;
+ struct coda_vget_in coda_vget;
+ struct coda_rdwr_in coda_rdwr;
+ struct coda_open_by_path_in coda_open_by_path;
+ struct coda_statfs_in coda_statfs;
+};
+
+union outputArgs {
+ struct coda_out_hdr oh; /* NB: every struct below begins with an oh */
+ struct coda_root_out coda_root;
+ struct coda_open_out coda_open;
+ struct coda_ioctl_out coda_ioctl;
+ struct coda_getattr_out coda_getattr;
+ struct coda_lookup_out coda_lookup;
+ struct coda_create_out coda_create;
+ struct coda_mkdir_out coda_mkdir;
+ struct coda_readdir_out coda_readdir;
+ struct coda_readlink_out coda_readlink;
+ struct coda_vget_out coda_vget;
+ struct coda_purgeuser_out coda_purgeuser;
+ struct coda_zapfile_out coda_zapfile;
+ struct coda_zapdir_out coda_zapdir;
+ struct coda_zapvnode_out coda_zapvnode;
+ struct coda_purgefid_out coda_purgefid;
+ struct coda_rdwr_out coda_rdwr;
+ struct coda_replace_out coda_replace;
+ struct coda_open_by_path_out coda_open_by_path;
+ struct coda_statfs_out coda_statfs;
+};
+
+union coda_downcalls {
+ /* CODA_INVALIDATE is a venus->kernel call */
+ /* CODA_FLUSH is a venus->kernel call */
+ struct coda_purgeuser_out purgeuser;
+ struct coda_zapfile_out zapfile;
+ struct coda_zapdir_out zapdir;
+ struct coda_zapvnode_out zapvnode;
+ struct coda_purgefid_out purgefid;
+ struct coda_replace_out replace;
+};
+
+
+/*
+ * Used for identifying usage of "Control" and pioctls
+ */
+
+#define PIOCPARM_MASK 0x0000ffff
+struct ViceIoctl {
+ caddr_t in, out; /* Data to be transferred in, or out */
+ short in_size; /* Size of input buffer <= 2K */
+ short out_size; /* Maximum size of output buffer, <= 2K */
+};
+
+struct PioctlData {
+ const char *path;
+ int follow;
+ struct ViceIoctl vi;
+};
+
+#define CODA_CONTROL ".CONTROL"
+#define CODA_CONTROLLEN 8
+#define CTL_VOL -1
+#define CTL_VNO -1
+#define CTL_UNI -1
+#define CTL_INO -1
+#define CTL_FILE "/coda/.CONTROL"
+
+
+#define IS_CTL_FID(fidp) ((fidp)->Volume == CTL_VOL &&\
+ (fidp)->Vnode == CTL_VNO &&\
+ (fidp)->Unique == CTL_UNI)
+#endif
+
diff --git a/pfinet/linux-src/include/linux/coda_cache.h b/pfinet/linux-src/include/linux/coda_cache.h
new file mode 100644
index 00000000..e549b02e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/coda_cache.h
@@ -0,0 +1,77 @@
+/* Coda filesystem -- Linux Minicache
+ *
+ * Copyright (C) 1989 - 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon University encourages users of this software to
+ * contribute improvements to the Coda project. Contact Peter Braam
+ * <coda@cs.cmu.edu>
+ */
+
+#ifndef _CFSNC_HEADER_
+#define _CFSNC_HEADER_
+
+/*
+ * Structure for an element in the Coda Credential Cache.
+ */
+
+struct coda_cache {
+ struct list_head cc_cclist; /* list of all cache entries */
+ struct list_head cc_cnlist; /* list of cache entries/cnode */
+ int cc_mask;
+ struct coda_cred cc_cred;
+};
+
+/* credential cache */
+void coda_cache_enter(struct inode *inode, int mask);
+void coda_cache_clear_inode(struct inode *);
+void coda_cache_clear_all(struct super_block *sb);
+void coda_cache_clear_cred(struct super_block *sb, struct coda_cred *cred);
+int coda_cache_check(struct inode *inode, int mask);
+
+/* for downcalls and attributes and lookups */
+void coda_flag_inode(struct inode *inode, int flag);
+void coda_flag_inode_children(struct inode *inode, int flag);
+
+
+/*
+ * Structure to contain statistics on the cache usage
+ */
+
+struct cfsnc_statistics {
+ unsigned hits;
+ unsigned misses;
+ unsigned enters;
+ unsigned dbl_enters;
+ unsigned long_name_enters;
+ unsigned long_name_lookups;
+ unsigned long_remove;
+ unsigned lru_rm;
+ unsigned zapPfids;
+ unsigned zapFids;
+ unsigned zapFile;
+ unsigned zapUsers;
+ unsigned Flushes;
+ unsigned Sum_bucket_len;
+ unsigned Sum2_bucket_len;
+ unsigned Max_bucket_len;
+ unsigned Num_zero_len;
+ unsigned Search_len;
+};
+
+
+#define CFSNC_FIND ((u_long) 1)
+#define CFSNC_REMOVE ((u_long) 2)
+#define CFSNC_INIT ((u_long) 3)
+#define CFSNC_ENTER ((u_long) 4)
+#define CFSNC_LOOKUP ((u_long) 5)
+#define CFSNC_ZAPPFID ((u_long) 6)
+#define CFSNC_ZAPFID ((u_long) 7)
+#define CFSNC_ZAPVNODE ((u_long) 8)
+#define CFSNC_ZAPFILE ((u_long) 9)
+#define CFSNC_PURGEUSER ((u_long) 10)
+#define CFSNC_FLUSH ((u_long) 11)
+#define CFSNC_PRINTCFSNC ((u_long) 12)
+#define CFSNC_PRINTSTATS ((u_long) 13)
+#define CFSNC_REPLACE ((u_long) 14)
+
+#endif _CFSNC_HEADER_
diff --git a/pfinet/linux-src/include/linux/coda_fs_i.h b/pfinet/linux-src/include/linux/coda_fs_i.h
new file mode 100644
index 00000000..8a55e8e3
--- /dev/null
+++ b/pfinet/linux-src/include/linux/coda_fs_i.h
@@ -0,0 +1,56 @@
+/*
+ * coda_fs_i.h
+ *
+ * Copyright (C) 1998 Carnegie Mellon University
+ *
+ */
+
+#ifndef _LINUX_CODA_FS_I
+#define _LINUX_CODA_FS_I
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/coda.h>
+
+
+
+#define CODA_CNODE_MAGIC 0x47114711
+/*
+ * coda fs inode data
+ */
+struct coda_inode_info {
+ /*
+ * This is a place holder so named pipes work (more or less
+ * correctly). This must be first in the struct because the
+ * data is really accessed via inode->u.pipe_i.
+ */
+ struct pipe_inode_info pipeinfo;
+
+ struct ViceFid c_fid; /* Coda identifier */
+ u_short c_flags; /* flags (see below) */
+ u_short c_ocount; /* count of openers */
+ u_short c_owrite; /* count of open for write */
+ u_short c_mmcount; /* count of mmappers */
+ struct inode *c_ovp; /* open inode pointer */
+ struct list_head c_cnhead; /* head of cache entries */
+ struct list_head c_volrootlist; /* list of volroot cnoddes */
+ struct inode *c_vnode; /* inode associated with cnode */
+ int c_magic; /* to verify the data structure */
+};
+
+/* flags */
+#define C_VATTR 0x1 /* Validity of vattr in inode */
+#define C_PURGE 0x8
+#define C_ZAPDIR 0x10
+#define C_DYING 0x4 /* from venus (which died) */
+#define C_INITED 0x20
+#define C_FLUSH 0x2 /* used after a flush */
+
+int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *);
+int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
+struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb);
+void coda_replace_fid(struct inode *, ViceFid *, ViceFid *);
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/coda_linux.h b/pfinet/linux-src/include/linux/coda_linux.h
new file mode 100644
index 00000000..cd0e46ce
--- /dev/null
+++ b/pfinet/linux-src/include/linux/coda_linux.h
@@ -0,0 +1,143 @@
+/*
+ * Coda File System, Linux Kernel module
+ *
+ * Original version, adapted from cfs_mach.c, (C) Carnegie Mellon University
+ * Linux modifications (C) 1996, Peter J. Braam
+ * Rewritten for Linux 2.1 (C) 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon University encourages users of this software to
+ * contribute improvements to the Coda project.
+ */
+
+#ifndef _LINUX_CODA_FS
+#define _LINUX_CODA_FS
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/malloc.h>
+#include <linux/wait.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+
+/* operations */
+extern struct inode_operations coda_dir_inode_operations;
+extern struct inode_operations coda_file_inode_operations;
+extern struct inode_operations coda_ioctl_inode_operations;
+extern struct inode_operations coda_symlink_inode_operations;
+
+extern struct file_operations coda_dir_operations;
+extern struct file_operations coda_file_operations;
+extern struct file_operations coda_ioctl_operations;
+
+/* operations shared over more than one file */
+int coda_open(struct inode *i, struct file *f);
+int coda_release(struct inode *i, struct file *f);
+int coda_permission(struct inode *inode, int mask);
+int coda_revalidate_inode(struct dentry *);
+
+/* global variables */
+extern int coda_debug;
+extern int coda_print_entry;
+extern int coda_access_cache;
+
+/* this file: heloers */
+static __inline__ struct ViceFid *coda_i2f(struct inode *);
+char *coda_f2s(ViceFid *f);
+char *coda_f2s2(ViceFid *f);
+int coda_isroot(struct inode *i);
+int coda_fid_is_volroot(struct ViceFid *);
+int coda_fid_is_weird(struct ViceFid *fid);
+int coda_iscontrol(const char *name, size_t length);
+
+void coda_load_creds(struct coda_cred *cred);
+int coda_mycred(struct coda_cred *);
+void coda_vattr_to_iattr(struct inode *, struct coda_vattr *);
+void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *);
+unsigned short coda_flags_to_cflags(unsigned short);
+void print_vattr( struct coda_vattr *attr );
+int coda_cred_ok(struct coda_cred *cred);
+int coda_cred_eq(struct coda_cred *cred1, struct coda_cred *cred2);
+
+/* defined in file.c */
+void coda_prepare_openfile(struct inode *coda_inode, struct file *coda_file,
+ struct inode *open_inode, struct file *open_file,
+ struct dentry *open_dentry);
+void coda_restore_codafile(struct inode *coda_inode, struct file *coda_file,
+ struct inode *open_inode, struct file *open_file);
+int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind);
+
+#define NB_SFS_SIZ 0x895440
+
+/* cache.c */
+void coda_purge_children(struct inode *, int);
+void coda_purge_dentries(struct inode *);
+
+/* sysctl.h */
+void coda_sysctl_init(void);
+void coda_sysctl_clean(void);
+
+
+/* debugging masks */
+#define D_SUPER 1 /* print results returned by Venus */
+#define D_INODE 2 /* print entry and exit into procedure */
+#define D_FILE 4
+#define D_CACHE 8 /* cache debugging */
+#define D_MALLOC 16 /* print malloc, de-alloc information */
+#define D_CNODE 32
+#define D_UPCALL 64 /* up and downcall debugging */
+#define D_PSDEV 128
+#define D_PIOCTL 256
+#define D_SPECIAL 512
+#define D_TIMING 1024
+#define D_DOWNCALL 2048
+
+#define CDEBUG(mask, format, a...) \
+ do { \
+ if (coda_debug & mask) { \
+ printk("(%s,l. %d): ", __FUNCTION__, __LINE__); \
+ printk(format, ## a); } \
+} while (0) ;
+
+#define ENTRY \
+ if(coda_print_entry) printk("Process %d entered %s\n",current->pid,__FUNCTION__)
+
+#define EXIT \
+ if(coda_print_entry) printk("Process %d leaving %s\n",current->pid,__FUNCTION__)
+
+#define CHECK_CNODE(c) do { } while (0);
+
+#define CODA_ALLOC(ptr, cast, size) \
+do { \
+ if (size < 3000) { \
+ ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \
+ CDEBUG(D_MALLOC, "kmalloced: %lx at %p.\n", (long)size, ptr);\
+ } else { \
+ ptr = (cast)vmalloc((unsigned long) size); \
+ CDEBUG(D_MALLOC, "vmalloced: %lx at %p .\n", (long)size, ptr);}\
+ if (ptr == 0) { \
+ printk("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \
+ } \
+ memset( ptr, 0, size ); \
+} while (0)
+
+
+#define CODA_FREE(ptr,size) do {if (size < 3000) { kfree_s((ptr), (size)); CDEBUG(D_MALLOC, "kfreed: %lx at %p.\n", (long) size, ptr); } else { vfree((ptr)); CDEBUG(D_MALLOC, "vfreed: %lx at %p.\n", (long) size, ptr);} } while (0)
+
+/* inode to cnode */
+
+static __inline__ struct ViceFid *coda_i2f(struct inode *inode)
+{
+ return &(inode->u.coda_i.c_fid);
+}
+
+#define ITOC(inode) (&((inode)->u.coda_i))
+
+
+
+
+
+
+#endif
diff --git a/pfinet/linux-src/include/linux/coda_opstats.h b/pfinet/linux-src/include/linux/coda_opstats.h
new file mode 100644
index 00000000..fdf3fac4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/coda_opstats.h
@@ -0,0 +1,94 @@
+
+/*
+ * Operation statistics for Coda.
+ * Copyright (C) 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon University encourages users of this software
+ * to contribute improvements to the Coda project. Contact Peter Braam
+ * <coda@coda.cs.cmu.edu>.
+ */
+
+
+
+#define CFS_MOUNT_STATS 0
+#define CFS_UMOUNT_STATS 1
+#define CFS_ROOT_STATS 2
+#define CFS_STATFS_STATS 3
+#define CFS_SYNC_STATS 4
+#define CFS_VGET_STATS 5
+#define CFS_VFSOPS_SIZE 6
+
+/* vnodeops:
+ * open: all to venus
+ * close: all to venus
+ * rdrw: bogus. Maybe redirected to UFS.
+ * May call open/close for internal opens/closes
+ * (Does exec not call open?)
+ * ioctl: causes a lookupname
+ * passes through
+ * select: can't get there from here.
+ * getattr: can be satsified by cache
+ * setattr: all go through
+ * access: can be satisfied by cache
+ * readlink: can be satisfied by cache
+ * fsync: passes through
+ * inactive: passes through
+ * lookup: can be satisfied by cache
+ * create: passes through
+ * remove: passes through
+ * link: passes through
+ * rename: passes through
+ * mkdir: passes through
+ * rmdir: passes through
+ * symlink: passes through
+ * readdir: may be redirected to UFS
+ * may cause an "internal" open/close
+ */
+
+#define CFS_OPEN_STATS 0
+#define CFS_CLOSE_STATS 1
+#define CFS_RDWR_STATS 2
+#define CFS_IOCTL_STATS 3
+#define CFS_SELECT_STATS 4
+#define CFS_GETATTR_STATS 5
+#define CFS_SETATTR_STATS 6
+#define CFS_ACCESS_STATS 7
+#define CFS_READLINK_STATS 8
+#define CFS_FSYNC_STATS 9
+#define CFS_INACTIVE_STATS 10
+#define CFS_LOOKUP_STATS 11
+#define CFS_CREATE_STATS 12
+#define CFS_REMOVE_STATS 13
+#define CFS_LINK_STATS 14
+#define CFS_RENAME_STATS 15
+#define CFS_MKDIR_STATS 16
+#define CFS_RMDIR_STATS 17
+#define CFS_SYMLINK_STATS 18
+#define CFS_READDIR_STATS 19
+#define CFS_VNODEOPS_SIZE 20
+
+
+/*
+ * I propose the following structres:
+ */
+
+
+struct cfs_op_stats {
+ int opcode; /* vfs opcode */
+ long entries; /* number of times call attempted */
+ long sat_intrn; /* number of times call satisfied by cache */
+ long unsat_intrn; /* number of times call failed in cache, but
+ was not bounced to venus proper. */
+ long gen_intrn; /* number of times call generated internally */
+ /* (do we need that?) */
+};
+
+
+/*
+ * With each call to the minicache, we'll bump the counters whenver
+ * a call is satisfied internally (through the cache or through a
+ * redirect), and whenever an operation is caused internally.
+ * Then, we can add the total operations caught by the minicache
+ * to the world-wide totals, and leave a caveat for the specific
+ * graphs later.
+ */
diff --git a/pfinet/linux-src/include/linux/coda_proc.h b/pfinet/linux-src/include/linux/coda_proc.h
new file mode 100644
index 00000000..7c4ca8a0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/coda_proc.h
@@ -0,0 +1,145 @@
+/*
+ * coda_statis.h
+ *
+ * CODA operation statistics
+ *
+ * (c) March, 1998
+ * by Michihiro Kuramochi, Zhenyu Xia and Zhanyong Wan
+ * zhanyong.wan@yale.edu
+ *
+ */
+
+#ifndef _CODA_PROC_H
+#define _CODA_PROC_H
+
+void coda_sysctl_init(void);
+void coda_sysctl_clean(void);
+void coda_upcall_stats(int opcode, unsigned long jiffies);
+
+#include <linux/sysctl.h>
+#include <linux/coda_fs_i.h>
+#include <linux/coda.h>
+
+/* these four files are presented to show the result of the statistics:
+ *
+ * /proc/fs/coda/vfs_stats
+ * upcall_stats
+ * permission_stats
+ * cache_inv_stats
+ *
+ * these four files are presented to reset the statistics to 0:
+ *
+ * /proc/sys/coda/vfs_stats
+ * upcall_stats
+ * permission_stats
+ * cache_inv_stats
+ */
+
+/* VFS operation statistics */
+struct coda_vfs_stats
+{
+ /* file operations */
+ int file_read;
+ int file_write;
+ int file_mmap;
+ int open;
+ int release;
+ int fsync;
+
+ /* dir operations */
+ int readdir;
+
+ /* inode operations */
+ int create;
+ int lookup;
+ int link;
+ int unlink;
+ int symlink;
+ int mkdir;
+ int rmdir;
+ int rename;
+ int permission;
+ int readpage;
+
+ /* symlink operatoins*/
+ int follow_link;
+ int readlink;
+};
+
+struct coda_upcall_stats_entry
+{
+ int count;
+ unsigned long time_sum;
+ unsigned long time_squared_sum;
+};
+
+
+
+/* cache hits for permissions statistics */
+struct coda_permission_stats
+{
+ int count;
+ int hit_count;
+};
+
+/* cache invalidation statistics */
+struct coda_cache_inv_stats
+{
+ int flush;
+ int purge_user;
+ int zap_dir;
+ int zap_file;
+ int zap_vnode;
+ int purge_fid;
+ int replace;
+};
+
+/* these global variables hold the actual statistics data */
+extern struct coda_vfs_stats coda_vfs_stat;
+extern struct coda_permission_stats coda_permission_stat;
+extern struct coda_cache_inv_stats coda_cache_inv_stat;
+extern int coda_upcall_timestamping;
+
+/* reset statistics to 0 */
+void reset_coda_vfs_stats( void );
+void reset_coda_upcall_stats( void );
+void reset_coda_permission_stats( void );
+void reset_coda_cache_inv_stats( void );
+
+/* some utitlities to make it easier for you to do statistics for time */
+void do_time_stats( struct coda_upcall_stats_entry * pentry,
+ unsigned long jiffy );
+/*
+double get_time_average( const struct coda_upcall_stats_entry * pentry );
+double get_time_std_deviation( const struct coda_upcall_stats_entry * pentry );
+*/
+unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry );
+unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry );
+
+/* like coda_dointvec, these functions are to be registered in the ctl_table
+ * data structure for /proc/sys/... files
+ */
+int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
+ void * buffer, size_t * lenp );
+int do_reset_coda_upcall_stats( ctl_table * table, int write,
+ struct file * filp, void * buffer,
+ size_t * lenp );
+int do_reset_coda_permission_stats( ctl_table * table, int write,
+ struct file * filp, void * buffer,
+ size_t * lenp );
+int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
+ struct file * filp, void * buffer,
+ size_t * lenp );
+
+/* these functions are called to form the content of /proc/fs/coda/... files */
+int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
+ int length, int dummy );
+int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
+ int length, int dummy );
+int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
+ int length, int dummy );
+int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
+ int length, int dummy );
+
+
+#endif /* _CODA_PROC_H */
diff --git a/pfinet/linux-src/include/linux/coda_psdev.h b/pfinet/linux-src/include/linux/coda_psdev.h
new file mode 100644
index 00000000..8c564f9a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/coda_psdev.h
@@ -0,0 +1,131 @@
+#ifndef __CODA_PSDEV_H
+#define __CODA_PSDEV_H
+
+#define CODA_PSDEV_MAJOR 67
+#define MAX_CODADEVS 5 /* how many do we allow */
+
+extern struct venus_comm coda_upc_comm;
+extern struct coda_sb_info coda_super_info;
+#define CODA_SUPER_MAGIC 0x73757245
+
+struct coda_sb_info
+{
+ struct inode * sbi_psdev; /* /dev/cfs? Venus/kernel device */
+ struct inode * sbi_ctlcp; /* control magic file */
+ int sbi_refct;
+ struct venus_comm * sbi_vcomm;
+ struct inode * sbi_root;
+ struct super_block *sbi_sb;
+ struct list_head sbi_cchead;
+ struct list_head sbi_volroothead;
+};
+
+/* communication pending/processing queues */
+struct venus_comm {
+ u_long vc_seq;
+ struct wait_queue *vc_waitq; /* Venus wait queue */
+ struct list_head vc_pending;
+ struct list_head vc_processing;
+ int vc_inuse;
+ pid_t vc_pid; /* Venus pid */
+};
+
+
+static inline struct coda_sb_info *coda_sbp(struct super_block *sb)
+{
+ return ((struct coda_sb_info *)((sb)->u.generic_sbp));
+}
+
+
+
+extern void coda_psdev_detach(int unit);
+extern int init_coda_psdev(void);
+
+
+/* upcalls */
+int venus_rootfid(struct super_block *sb, ViceFid *fidp);
+int venus_getattr(struct super_block *sb, struct ViceFid *fid,
+ struct coda_vattr *attr);
+int venus_setattr(struct super_block *, struct ViceFid *,
+ struct coda_vattr *);
+int venus_lookup(struct super_block *sb, struct ViceFid *fid,
+ const char *name, int length, int *type,
+ struct ViceFid *resfid);
+int venus_release(struct super_block *sb, struct ViceFid *fid, int flags,
+ struct coda_cred *);
+int venus_open(struct super_block *sb, struct ViceFid *fid,
+ int flags, ino_t *ino, dev_t *dev);
+int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid,
+ const char *name, int length,
+ struct ViceFid *newfid, struct coda_vattr *attrs);
+int venus_create(struct super_block *sb, struct ViceFid *dirfid,
+ const char *name, int length, int excl, int mode, int rdev,
+ struct ViceFid *newfid, struct coda_vattr *attrs) ;
+int venus_rmdir(struct super_block *sb, struct ViceFid *dirfid,
+ const char *name, int length);
+int venus_remove(struct super_block *sb, struct ViceFid *dirfid,
+ const char *name, int length);
+int venus_readlink(struct super_block *sb, struct ViceFid *fid,
+ char *buffer, int *length);
+int venus_rename(struct super_block *, struct ViceFid *new_fid,
+ struct ViceFid *old_fid, size_t old_length,
+ size_t new_length, const char *old_name,
+ const char *new_name);
+int venus_link(struct super_block *sb, struct ViceFid *fid,
+ struct ViceFid *dirfid, const char *name, int len );
+int venus_symlink(struct super_block *sb, struct ViceFid *fid,
+ const char *name, int len, const char *symname, int symlen);
+int venus_access(struct super_block *sb, struct ViceFid *fid, int mask);
+int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
+ unsigned int cmd, struct PioctlData *data);
+int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb);
+int venus_fsync(struct super_block *sb, struct ViceFid *fid);
+int venus_statfs(struct super_block *sb, struct statfs *sfs);
+
+
+/* messages between coda filesystem in kernel and Venus */
+extern int coda_hard;
+extern unsigned long coda_timeout;
+struct upc_req {
+ struct list_head uc_chain;
+ caddr_t uc_data;
+ u_short uc_flags;
+ u_short uc_inSize; /* Size is at most 5000 bytes */
+ u_short uc_outSize;
+ u_short uc_opcode; /* copied from data to save lookup */
+ int uc_unique;
+ struct wait_queue *uc_sleep; /* process' wait queue */
+ unsigned long uc_posttime;
+};
+
+#define REQ_ASYNC 0x1
+#define REQ_READ 0x2
+#define REQ_WRITE 0x4
+
+
+/*
+ * Statistics
+ */
+struct coda_upcallstats {
+ int ncalls; /* client requests */
+ int nbadcalls; /* upcall failures */
+ int reqs[CODA_NCALLS]; /* count of each request */
+} ;
+
+extern struct coda_upcallstats coda_callstats;
+
+static inline void clstats(int opcode)
+{
+ coda_callstats.ncalls++;
+ if ( (0 <= opcode) && (opcode <= CODA_NCALLS) )
+ coda_callstats.reqs[opcode]++;
+ else
+ printk("clstats called with bad opcode %d\n", opcode);
+}
+
+static inline void badclstats(void)
+{
+ coda_callstats.nbadcalls++;
+}
+
+#endif
diff --git a/pfinet/linux-src/include/linux/coff.h b/pfinet/linux-src/include/linux/coff.h
new file mode 100644
index 00000000..a1ba4666
--- /dev/null
+++ b/pfinet/linux-src/include/linux/coff.h
@@ -0,0 +1,351 @@
+/* This file is derived from the GAS 2.1.4 assembler control file.
+ The GAS product is under the GNU Public License, version 2 or later.
+ As such, this file is also under that license.
+
+ If the file format changes in the COFF object, this file should be
+ subsequently updated to reflect the changes.
+
+ The actual loader module only uses a few of these structures. The full
+ set is documented here because I received the full set. If you wish
+ more information about COFF, then O'Reilly has a very excellent book.
+*/
+
+#define E_SYMNMLEN 8 /* Number of characters in a symbol name */
+#define E_FILNMLEN 14 /* Number of characters in a file name */
+#define E_DIMNUM 4 /* Number of array dimensions in auxiliary entry */
+
+/*
+ * These defines are byte order independent. There is no alignment of fields
+ * permitted in the structures. Therefore they are declared as characters
+ * and the values loaded from the character positions. It also makes it
+ * nice to have it "endian" independent.
+ */
+
+/* Load a short int from the following tables with little-endian formats */
+#define COFF_SHORT_L(ps) ((short)(((unsigned short)((unsigned char)ps[1])<<8)|\
+ ((unsigned short)((unsigned char)ps[0]))))
+
+/* Load a long int from the following tables with little-endian formats */
+#define COFF_LONG_L(ps) (((long)(((unsigned long)((unsigned char)ps[3])<<24) |\
+ ((unsigned long)((unsigned char)ps[2])<<16) |\
+ ((unsigned long)((unsigned char)ps[1])<<8) |\
+ ((unsigned long)((unsigned char)ps[0])))))
+
+/* Load a short int from the following tables with big-endian formats */
+#define COFF_SHORT_H(ps) ((short)(((unsigned short)((unsigned char)ps[0])<<8)|\
+ ((unsigned short)((unsigned char)ps[1]))))
+
+/* Load a long int from the following tables with big-endian formats */
+#define COFF_LONG_H(ps) (((long)(((unsigned long)((unsigned char)ps[0])<<24) |\
+ ((unsigned long)((unsigned char)ps[1])<<16) |\
+ ((unsigned long)((unsigned char)ps[2])<<8) |\
+ ((unsigned long)((unsigned char)ps[3])))))
+
+/* These may be overridden later by brain dead implementations which generate
+ a big-endian header with little-endian data. In that case, generate a
+ replacement macro which tests a flag and uses either of the two above
+ as appropriate. */
+
+#define COFF_LONG(v) COFF_LONG_L(v)
+#define COFF_SHORT(v) COFF_SHORT_L(v)
+
+/*** coff information for Intel 386/486. */
+
+/********************** FILE HEADER **********************/
+
+struct COFF_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+/*
+ * Bits for f_flags:
+ *
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (i.e. no unresolved external
+ * references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_MINMAL this is a minimal object file (".m") output of fextract
+ * F_UPDATE this is a fully bound update file, output of ogen
+ * F_SWABD this file has had its bytes swabbed (in names)
+ * F_AR16WR this file has the byte ordering of an AR16WR
+ * (e.g. 11/70) machine
+ * F_AR32WR this file has the byte ordering of an AR32WR machine
+ * (e.g. vax and iNTEL 386)
+ * F_AR32W this file has the byte ordering of an AR32W machine
+ * (e.g. 3b,maxi)
+ * F_PATCH file contains "patch" list in optional header
+ * F_NODF (minimal file only) no decision functions for
+ * replaced functions
+ */
+
+#define COFF_F_RELFLG 0000001
+#define COFF_F_EXEC 0000002
+#define COFF_F_LNNO 0000004
+#define COFF_F_LSYMS 0000010
+#define COFF_F_MINMAL 0000020
+#define COFF_F_UPDATE 0000040
+#define COFF_F_SWABD 0000100
+#define COFF_F_AR16WR 0000200
+#define COFF_F_AR32WR 0000400
+#define COFF_F_AR32W 0001000
+#define COFF_F_PATCH 0002000
+#define COFF_F_NODF 0002000
+
+#define COFF_I386MAGIC 0x14c /* Linux's system */
+
+#if 0 /* Perhaps, someday, these formats may be used. */
+#define COFF_I386PTXMAGIC 0x154
+#define COFF_I386AIXMAGIC 0x175 /* IBM's AIX system */
+#define COFF_I386BADMAG(x) ((COFF_SHORT((x).f_magic) != COFF_I386MAGIC) \
+ && COFF_SHORT((x).f_magic) != COFF_I386PTXMAGIC \
+ && COFF_SHORT((x).f_magic) != COFF_I386AIXMAGIC)
+#else
+#define COFF_I386BADMAG(x) (COFF_SHORT((x).f_magic) != COFF_I386MAGIC)
+#endif
+
+#define COFF_FILHDR struct COFF_filehdr
+#define COFF_FILHSZ sizeof(COFF_FILHDR)
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+/* Linux COFF must have this "optional" header. Standard COFF has no entry
+ location for the "entry" point. They normally would start with the first
+ location of the .text section. This is not a good idea for linux. So,
+ the use of this "optional" header is not optional. It is required.
+
+ Do not be tempted to assume that the size of the optional header is
+ a constant and simply index the next byte by the size of this structure.
+ Use the 'f_opthdr' field in the main coff header for the size of the
+ structure actually written to the file!!
+*/
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry */
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+COFF_AOUTHDR;
+
+#define COFF_AOUTSZ (sizeof(COFF_AOUTHDR))
+
+#define COFF_STMAGIC 0401
+#define COFF_OMAGIC 0404
+#define COFF_JMAGIC 0407 /* dirty text and data image, can't share */
+#define COFF_DMAGIC 0410 /* dirty text segment, data aligned */
+#define COFF_ZMAGIC 0413 /* The proper magic number for executables */
+#define COFF_SHMAGIC 0443 /* shared library header */
+
+/********************** SECTION HEADER **********************/
+
+struct COFF_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries */
+ char s_flags[4]; /* flags */
+};
+
+#define COFF_SCNHDR struct COFF_scnhdr
+#define COFF_SCNHSZ sizeof(COFF_SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+
+#define COFF_TEXT ".text"
+#define COFF_DATA ".data"
+#define COFF_BSS ".bss"
+#define COFF_COMMENT ".comment"
+#define COFF_LIB ".lib"
+
+#define COFF_SECT_TEXT 0 /* Section for instruction code */
+#define COFF_SECT_DATA 1 /* Section for initialized globals */
+#define COFF_SECT_BSS 2 /* Section for un-initialized globals */
+#define COFF_SECT_REQD 3 /* Minimum number of sections for good file */
+
+#define COFF_STYP_REG 0x00 /* regular segment */
+#define COFF_STYP_DSECT 0x01 /* dummy segment */
+#define COFF_STYP_NOLOAD 0x02 /* no-load segment */
+#define COFF_STYP_GROUP 0x04 /* group segment */
+#define COFF_STYP_PAD 0x08 /* .pad segment */
+#define COFF_STYP_COPY 0x10 /* copy section */
+#define COFF_STYP_TEXT 0x20 /* .text segment */
+#define COFF_STYP_DATA 0x40 /* .data segment */
+#define COFF_STYP_BSS 0x80 /* .bss segment */
+#define COFF_STYP_INFO 0x200 /* .comment section */
+#define COFF_STYP_OVER 0x400 /* overlay section */
+#define COFF_STYP_LIB 0x800 /* library section */
+
+/*
+ * Shared libraries have the following section header in the data field for
+ * each library.
+ */
+
+struct COFF_slib {
+ char sl_entsz[4]; /* Size of this entry */
+ char sl_pathndx[4]; /* size of the header field */
+};
+
+#define COFF_SLIBHD struct COFF_slib
+#define COFF_SLIBSZ sizeof(COFF_SLIBHD)
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+
+struct COFF_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+#define COFF_LINENO struct COFF_lineno
+#define COFF_LINESZ 6
+
+/********************** SYMBOLS **********************/
+
+#define COFF_E_SYMNMLEN 8 /* # characters in a short symbol name */
+#define COFF_E_FILNMLEN 14 /* # characters in a file name */
+#define COFF_E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+/*
+ * All symbols and sections have the following definition
+ */
+
+struct COFF_syment
+{
+ union {
+ char e_name[E_SYMNMLEN]; /* Symbol name (first 8 characters) */
+ struct {
+ char e_zeroes[4]; /* Leading zeros */
+ char e_offset[4]; /* Offset if this is a header section */
+ } e;
+ } e;
+
+ char e_value[4]; /* Value (address) of the segment */
+ char e_scnum[2]; /* Section number */
+ char e_type[2]; /* Type of section */
+ char e_sclass[1]; /* Loader class */
+ char e_numaux[1]; /* Number of auxiliary entries which follow */
+};
+
+#define COFF_N_BTMASK (0xf) /* Mask for important class bits */
+#define COFF_N_TMASK (0x30) /* Mask for important type bits */
+#define COFF_N_BTSHFT (4) /* # bits to shift class field */
+#define COFF_N_TSHIFT (2) /* # bits to shift type field */
+
+/*
+ * Auxiliary entries because the main table is too limiting.
+ */
+
+union COFF_auxent {
+
+/*
+ * Debugger information
+ */
+
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+/*
+ * Source file names (debugger information)
+ */
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+/*
+ * Section information
+ */
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+/*
+ * Transfer vector (branch table)
+ */
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+};
+
+#define COFF_SYMENT struct COFF_syment
+#define COFF_SYMESZ 18
+#define COFF_AUXENT union COFF_auxent
+#define COFF_AUXESZ 18
+
+#define COFF_ETEXT "etext"
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct COFF_reloc {
+ char r_vaddr[4]; /* Virtual address of item */
+ char r_symndx[4]; /* Symbol index in the symtab */
+ char r_type[2]; /* Relocation type */
+};
+
+#define COFF_RELOC struct COFF_reloc
+#define COFF_RELSZ 10
+
+#define COFF_DEF_DATA_SECTION_ALIGNMENT 4
+#define COFF_DEF_BSS_SECTION_ALIGNMENT 4
+#define COFF_DEF_TEXT_SECTION_ALIGNMENT 4
+
+/* For new sections we haven't heard of before */
+#define COFF_DEF_SECTION_ALIGNMENT 4
diff --git a/pfinet/linux-src/include/linux/comstats.h b/pfinet/linux-src/include/linux/comstats.h
new file mode 100644
index 00000000..06688859
--- /dev/null
+++ b/pfinet/linux-src/include/linux/comstats.h
@@ -0,0 +1,119 @@
+/*****************************************************************************/
+
+/*
+ * comstats.h -- Serial Port Stats.
+ *
+ * Copyright (C) 1996-1998 Stallion Technologies (support@stallion.oz.au).
+ * Copyright (C) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*****************************************************************************/
+#ifndef _COMSTATS_H
+#define _COMSTATS_H
+/*****************************************************************************/
+
+/*
+ * Serial port stats structure. The structure itself is UART
+ * independent, but some fields may be UART/driver specific (for
+ * example state).
+ */
+
+typedef struct {
+ unsigned long brd;
+ unsigned long panel;
+ unsigned long port;
+ unsigned long hwid;
+ unsigned long type;
+ unsigned long txtotal;
+ unsigned long rxtotal;
+ unsigned long txbuffered;
+ unsigned long rxbuffered;
+ unsigned long rxoverrun;
+ unsigned long rxparity;
+ unsigned long rxframing;
+ unsigned long rxlost;
+ unsigned long txbreaks;
+ unsigned long rxbreaks;
+ unsigned long txxon;
+ unsigned long txxoff;
+ unsigned long rxxon;
+ unsigned long rxxoff;
+ unsigned long txctson;
+ unsigned long txctsoff;
+ unsigned long rxrtson;
+ unsigned long rxrtsoff;
+ unsigned long modem;
+ unsigned long state;
+ unsigned long flags;
+ unsigned long ttystate;
+ unsigned long cflags;
+ unsigned long iflags;
+ unsigned long oflags;
+ unsigned long lflags;
+ unsigned long signals;
+} comstats_t;
+
+
+/*
+ * Board stats structure. Returns useful info about the board.
+ */
+
+#define COM_MAXPANELS 8
+
+typedef struct {
+ unsigned long panel;
+ unsigned long type;
+ unsigned long hwid;
+ unsigned long nrports;
+} companel_t;
+
+typedef struct {
+ unsigned long brd;
+ unsigned long type;
+ unsigned long hwid;
+ unsigned long state;
+ unsigned long ioaddr;
+ unsigned long ioaddr2;
+ unsigned long memaddr;
+ unsigned long irq;
+ unsigned long nrpanels;
+ unsigned long nrports;
+ companel_t panels[COM_MAXPANELS];
+} combrd_t;
+
+
+/*
+ * Define the ioctl operations for stats stuff.
+ */
+#include <linux/ioctl.h>
+
+#define COM_GETPORTSTATS _IO('c',30)
+#define COM_CLRPORTSTATS _IO('c',31)
+#define COM_GETBRDSTATS _IO('c',32)
+
+
+/*
+ * Define the set of ioctls that give user level access to the
+ * private port, panel and board structures. The argument required
+ * will be driver dependent!
+ */
+#define COM_READPORT _IO('c',40)
+#define COM_READBOARD _IO('c',41)
+#define COM_READPANEL _IO('c',42)
+
+/*****************************************************************************/
+#endif
diff --git a/pfinet/linux-src/include/linux/concap.h b/pfinet/linux-src/include/linux/concap.h
new file mode 100644
index 00000000..05f74d82
--- /dev/null
+++ b/pfinet/linux-src/include/linux/concap.h
@@ -0,0 +1,113 @@
+/* $Id: concap.h,v 1.1 1998/02/01 00:15:11 keil Exp $
+*/
+#ifndef _LINUX_CONCAP_H
+#define _LINUX_CONCAP_H
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+/* Stuff to support encapsulation protocols genericly. The encapsulation
+ protocol is processed at the uppermost layer of the network interface.
+
+ (c) 1997 by Henner Eisen <eis@baty.hanse.de>
+ This software is subject to the GNU General Public License.
+
+ Based on a ideas developed in a 'synchronous device' thread in the
+ linux-x25 mailing list contributed by Alan Cox, Thomasz Motylewski
+ and Jonathan Naylor.
+
+ For more documetation on this refer to Documentation/isdn/README.concap
+ */
+
+struct concap_proto_ops;
+struct concap_device_ops;
+
+/* this manages all data needed by the encapsulation protocol
+ */
+struct concap_proto{
+ struct device *net_dev; /* net device using our service */
+ struct concap_device_ops *dops; /* callbacks provided by device */
+ struct concap_proto_ops *pops; /* callbacks provided by us */
+ int flags;
+ void *proto_data; /* protocol specific private data, to
+ be accessed via *pops methods only*/
+ /*
+ :
+ whatever
+ :
+ */
+};
+
+/* Operations to be supported by the net device. Called by the encapsulation
+ * protocol entity. No receive method is offered because the encapsulation
+ * protocol directly calls netif_rx().
+ */
+struct concap_device_ops{
+
+ /* to request data is submitted by device*/
+ int (*data_req)(struct concap_proto *, struct sk_buff *);
+
+ /* Control methods must be set to NULL by devices which do not
+ support connection control.*/
+ /* to request a connection is set up */
+ int (*connect_req)(struct concap_proto *);
+
+ /* to request a connection is released */
+ int (*disconn_req)(struct concap_proto *);
+};
+
+/* Operations to be supported by the encapsulation protocol. Called by
+ * device driver.
+ */
+struct concap_proto_ops{
+
+ /* create a new encapsulation protocol instance of same type */
+ struct concap_proto * (*proto_new) (void);
+
+ /* delete encapsulation protocol instance and free all its resources.
+ cprot may no loger be referenced after calling this */
+ void (*proto_del)(struct concap_proto *cprot);
+
+ /* initialize the protocol's data. To be called at interface startup
+ or when the device driver resets the interface. All services of the
+ encapsulation protocol may be used after this*/
+ int (*restart)(struct concap_proto *cprot,
+ struct device *ndev,
+ struct concap_device_ops *dops);
+
+ /* inactivate an encapsulation protocol instance. The encapsulation
+ protocol may not call any *dops methods after this. */
+ int (*close)(struct concap_proto *cprot);
+
+ /* process a frame handed down to us by upper layer */
+ int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb);
+
+ /* to be called for each data entity received from lower layer*/
+ int (*data_ind)(struct concap_proto *cprot, struct sk_buff *skb);
+
+ /* to be called when a connection was set up/down.
+ Protocols that don't process these primitives might fill in
+ dummy methods here */
+ int (*connect_ind)(struct concap_proto *cprot);
+ int (*disconn_ind)(struct concap_proto *cprot);
+ /*
+ Some network device support functions, like net_header(), rebuild_header(),
+ and others, that depend solely on the encapsulation protocol, might
+ be provided here, too. The net device would just fill them in its
+ corresponding fields when it is opened.
+ */
+};
+
+/* dummy restart/close/connect/reset/disconn methods
+ */
+extern int concap_nop(struct concap_proto *cprot);
+
+/* dummy submit method
+ */
+extern int concap_drop_skb(struct concap_proto *cprot, struct sk_buff *skb);
+#endif
+#endif
+
+
+
+
diff --git a/pfinet/linux-src/include/linux/config.h b/pfinet/linux-src/include/linux/config.h
new file mode 100644
index 00000000..9d1c14f7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/config.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_CONFIG_H
+#define _LINUX_CONFIG_H
+
+#include <linux/autoconf.h>
+
+#endif
diff --git a/pfinet/linux-src/include/linux/console.h b/pfinet/linux-src/include/linux/console.h
new file mode 100644
index 00000000..efb0003e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/console.h
@@ -0,0 +1,115 @@
+/*
+ * linux/include/linux/console.h
+ *
+ * Copyright (C) 1993 Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * Changed:
+ * 10-Mar-94: Arno Griffioen: Conversion for vt100 emulator port from PC LINUX
+ */
+
+#ifndef _LINUX_CONSOLE_H_
+#define _LINUX_CONSOLE_H_ 1
+
+struct vc_data;
+struct console_font_op;
+
+/*
+ * this is what the terminal answers to a ESC-Z or csi0c query.
+ */
+#define VT100ID "\033[?1;2c"
+#define VT102ID "\033[?6c"
+
+struct consw {
+ const char *(*con_startup)(void);
+ void (*con_init)(struct vc_data *, int);
+ void (*con_deinit)(struct vc_data *);
+ void (*con_clear)(struct vc_data *, int, int, int, int);
+ void (*con_putc)(struct vc_data *, int, int, int);
+ void (*con_putcs)(struct vc_data *, const unsigned short *, int, int, int);
+ void (*con_cursor)(struct vc_data *, int);
+ int (*con_scroll)(struct vc_data *, int, int, int, int);
+ void (*con_bmove)(struct vc_data *, int, int, int, int, int, int);
+ int (*con_switch)(struct vc_data *);
+ int (*con_blank)(struct vc_data *, int);
+ int (*con_font_op)(struct vc_data *, struct console_font_op *);
+ int (*con_set_palette)(struct vc_data *, unsigned char *);
+ int (*con_scrolldelta)(struct vc_data *, int);
+ int (*con_set_origin)(struct vc_data *);
+ void (*con_save_screen)(struct vc_data *);
+ u8 (*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8);
+ void (*con_invert_region)(struct vc_data *, u16 *, int);
+ u16 *(*con_screen_pos)(struct vc_data *, int);
+ unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
+};
+
+extern struct consw *conswitchp;
+
+extern struct consw dummy_con; /* dummy console buffer */
+extern struct consw fb_con; /* frame buffer based console */
+extern struct consw vga_con; /* VGA text console */
+extern struct consw newport_con; /* SGI Newport console */
+extern struct consw prom_con; /* SPARC PROM console */
+
+void take_over_console(struct consw *sw, int first, int last, int deflt);
+void give_up_console(struct consw *sw);
+
+/* scroll */
+#define SM_UP (1)
+#define SM_DOWN (2)
+
+/* cursor */
+#define CM_DRAW (1)
+#define CM_ERASE (2)
+#define CM_MOVE (3)
+
+/*
+ * Array of consoles built from command line options (console=)
+ */
+struct console_cmdline
+{
+ char name[8]; /* Name of the driver */
+ int index; /* Minor dev. to use */
+ char *options; /* Options for the driver */
+};
+#define MAX_CMDLINECONSOLES 8
+extern struct console_cmdline console_list[MAX_CMDLINECONSOLES];
+
+/*
+ * The interface for a console, or any other device that
+ * wants to capture console messages (printer driver?)
+ */
+
+#define CON_PRINTBUFFER (1)
+#define CON_CONSDEV (2) /* Last on the command line */
+#define CON_ENABLED (4)
+
+struct console
+{
+ char name[8];
+ void (*write)(struct console *, const char *, unsigned);
+ int (*read)(struct console *, const char *, unsigned);
+ kdev_t (*device)(struct console *);
+ int (*wait_key)(struct console *);
+ void (*unblank)(void);
+ int (*setup)(struct console *, char *);
+ short flags;
+ short index;
+ int cflag;
+ struct console *next;
+};
+
+extern void register_console(struct console *);
+extern int unregister_console(struct console *);
+extern struct console *console_drivers;
+
+/* VESA Blanking Levels */
+#define VESA_NO_BLANKING 0
+#define VESA_VSYNC_SUSPEND 1
+#define VESA_HSYNC_SUSPEND 2
+#define VESA_POWERDOWN 3
+
+#endif /* _LINUX_CONSOLE_H */
diff --git a/pfinet/linux-src/include/linux/console_struct.h b/pfinet/linux-src/include/linux/console_struct.h
new file mode 100644
index 00000000..0f664086
--- /dev/null
+++ b/pfinet/linux-src/include/linux/console_struct.h
@@ -0,0 +1,109 @@
+/*
+ * console_struct.h
+ *
+ * Data structure describing single virtual console except for data
+ * used by vt.c.
+ *
+ * Fields marked with [#] must be set by the low-level driver.
+ * Fields marked with [!] can be changed by the low-level driver
+ * to achieve effects such as fast scrolling by changing the origin.
+ */
+
+#define NPAR 16
+
+struct vc_data {
+ unsigned short vc_num; /* Console number */
+ unsigned int vc_cols; /* [#] Console size */
+ unsigned int vc_rows;
+ unsigned int vc_size_row; /* Bytes per row */
+ struct consw *vc_sw;
+ unsigned short *vc_screenbuf; /* In-memory character/attribute buffer */
+ unsigned int vc_screenbuf_size;
+ unsigned char vc_attr; /* Current attributes */
+ unsigned char vc_def_color; /* Default colors */
+ unsigned char vc_color; /* Foreground & background */
+ unsigned char vc_s_color; /* Saved foreground & background */
+ unsigned char vc_ulcolor; /* Color for underline mode */
+ unsigned char vc_halfcolor; /* Color for half intensity mode */
+ unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */
+ unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
+ unsigned short vc_video_erase_char; /* Background erase character */
+ unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
+ unsigned int vc_x, vc_y; /* Cursor position */
+ unsigned int vc_top, vc_bottom; /* Scrolling region */
+ unsigned int vc_state; /* Escape sequence parser state */
+ unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
+ unsigned long vc_origin; /* [!] Start of real screen */
+ unsigned long vc_scr_end; /* [!] End of real screen */
+ unsigned long vc_visible_origin; /* [!] Top of visible window */
+ unsigned long vc_pos; /* Cursor address */
+ unsigned int vc_saved_x;
+ unsigned int vc_saved_y;
+ /* mode flags */
+ unsigned int vc_charset : 1; /* Character set G0 / G1 */
+ unsigned int vc_s_charset : 1; /* Saved character set */
+ unsigned int vc_disp_ctrl : 1; /* Display chars < 32? */
+ unsigned int vc_toggle_meta : 1; /* Toggle high bit? */
+ unsigned int vc_decscnm : 1; /* Screen Mode */
+ unsigned int vc_decom : 1; /* Origin Mode */
+ unsigned int vc_decawm : 1; /* Autowrap Mode */
+ unsigned int vc_deccm : 1; /* Cursor Visible */
+ unsigned int vc_decim : 1; /* Insert Mode */
+ unsigned int vc_deccolm : 1; /* 80/132 Column Mode */
+ /* attribute flags */
+ unsigned int vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */
+ unsigned int vc_underline : 1;
+ unsigned int vc_blink : 1;
+ unsigned int vc_reverse : 1;
+ unsigned int vc_s_intensity : 2; /* saved rendition */
+ unsigned int vc_s_underline : 1;
+ unsigned int vc_s_blink : 1;
+ unsigned int vc_s_reverse : 1;
+ /* misc */
+ unsigned int vc_ques : 1;
+ unsigned int vc_need_wrap : 1;
+ unsigned int vc_can_do_color : 1;
+ unsigned int vc_report_mouse : 2;
+ unsigned int vc_kmalloced : 1;
+ unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */
+ unsigned char vc_utf_count;
+ int vc_utf_char;
+ unsigned int vc_tab_stop[5]; /* Tab stops. 160 columns. */
+ unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */
+ unsigned short * vc_translate;
+ unsigned char vc_G0_charset;
+ unsigned char vc_G1_charset;
+ unsigned char vc_saved_G0;
+ unsigned char vc_saved_G1;
+ unsigned int vc_bell_pitch; /* Console bell pitch */
+ unsigned int vc_bell_duration; /* Console bell duration */
+ unsigned int vc_cursor_type;
+ struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */
+ unsigned long vc_uni_pagedir;
+ unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
+ /* additional information is in vt_kern.h */
+};
+
+struct vc {
+ struct vc_data *d;
+
+ /* might add scrmem, vt_struct, kbd at some time,
+ to have everything in one place - the disadvantage
+ would be that vc_cons etc can no longer be static */
+};
+
+extern struct vc vc_cons [MAX_NR_CONSOLES];
+
+#define CUR_DEF 0
+#define CUR_NONE 1
+#define CUR_UNDERLINE 2
+#define CUR_LOWER_THIRD 3
+#define CUR_LOWER_HALF 4
+#define CUR_TWO_THIRDS 5
+#define CUR_BLOCK 6
+#define CUR_HWMASK 0x0f
+#define CUR_SWMASK 0xfff0
+
+#define CUR_DEFAULT CUR_UNDERLINE
+
+#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
diff --git a/pfinet/linux-src/include/linux/consolemap.h b/pfinet/linux-src/include/linux/consolemap.h
new file mode 100644
index 00000000..dee4b654
--- /dev/null
+++ b/pfinet/linux-src/include/linux/consolemap.h
@@ -0,0 +1,15 @@
+/*
+ * consolemap.h
+ *
+ * Interface between console.c, selection.c and consolemap.c
+ */
+#define LAT1_MAP 0
+#define GRAF_MAP 1
+#define IBMPC_MAP 2
+#define USER_MAP 3
+
+struct vc_data;
+
+extern unsigned char inverse_translate(struct vc_data *conp, int glyph);
+extern unsigned short *set_translate(int m,int currcons);
+extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
diff --git a/pfinet/linux-src/include/linux/ctype.h b/pfinet/linux-src/include/linux/ctype.h
new file mode 100644
index 00000000..afa36392
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ctype.h
@@ -0,0 +1,54 @@
+#ifndef _LINUX_CTYPE_H
+#define _LINUX_CTYPE_H
+
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U 0x01 /* upper */
+#define _L 0x02 /* lower */
+#define _D 0x04 /* digit */
+#define _C 0x08 /* cntrl */
+#define _P 0x10 /* punct */
+#define _S 0x20 /* white space (space/lf/tab) */
+#define _X 0x40 /* hex digit */
+#define _SP 0x80 /* hard space (0x20) */
+
+extern unsigned char _ctype[];
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
+#define isdigit(c) ((__ismask(c)&(_D)) != 0)
+#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c) ((__ismask(c)&(_L)) != 0)
+#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c) ((__ismask(c)&(_P)) != 0)
+#define isspace(c) ((__ismask(c)&(_S)) != 0)
+#define isupper(c) ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static inline unsigned char __tolower(unsigned char c)
+{
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static inline unsigned char __toupper(unsigned char c)
+{
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+#endif
diff --git a/pfinet/linux-src/include/linux/cyclades.h b/pfinet/linux-src/include/linux/cyclades.h
new file mode 100644
index 00000000..f1043fdf
--- /dev/null
+++ b/pfinet/linux-src/include/linux/cyclades.h
@@ -0,0 +1,793 @@
+/* $Revision: 2.6 $$Date: 1998/08/10 16:57:01 $
+ * linux/include/linux/cyclades.h
+ *
+ * This file is maintained by Ivan Passos <ivan@cyclades.com>,
+ * Marcio Saito <marcio@cyclades.com> and
+ * Randolph Bentson <bentson@grieg.seaslug.org>.
+ *
+ * This file contains the general definitions for the cyclades.c driver
+ *$Log: cyclades.h,v $
+ *Revision 2.5 1998/08/03 16:57:01 ivan
+ *added cyclades_idle_stats structure;
+ *
+ *Revision 2.4 1998/06/01 12:09:53 ivan
+ *removed closing_wait2 from cyclades_port structure;
+ *
+ *Revision 2.3 1998/03/16 18:01:12 ivan
+ *changes in the cyclades_port structure to get it closer to the
+ *standard serial port structure;
+ *added constants for new ioctls;
+ *
+ *Revision 2.2 1998/02/17 16:50:00 ivan
+ *changes in the cyclades_port structure (addition of shutdown_wait and
+ *chip_rev variables);
+ *added constants for new ioctls and for CD1400 rev. numbers.
+ *
+ *Revision 2.1 1997/10/24 16:03:00 ivan
+ *added rflow (which allows enabling the CD1400 special flow control
+ *feature) and rtsdtr_inv (which allows DTR/RTS pin inversion) to
+ *cyclades_port structure;
+ *added Alpha support
+ *
+ *Revision 2.0 1997/06/30 10:30:00 ivan
+ *added some new doorbell command constants related to IOCTLW and
+ *UART error signaling
+ *
+ *Revision 1.8 1997/06/03 15:30:00 ivan
+ *added constant ZFIRM_HLT
+ *added constant CyPCI_Ze_win ( = 2 * Cy_PCI_Zwin)
+ *
+ *Revision 1.7 1997/03/26 10:30:00 daniel
+ *new entries at the end of cyclades_port struct to reallocate
+ *variables illegally allocated within card memory.
+ *
+ *Revision 1.6 1996/09/09 18:35:30 bentson
+ *fold in changes for Cyclom-Z -- including structures for
+ *communicating with board as well modest changes to original
+ *structures to support new features.
+ *
+ *Revision 1.5 1995/11/13 21:13:31 bentson
+ *changes suggested by Michael Chastain <mec@duracef.shout.net>
+ *to support use of this file in non-kernel applications
+ *
+ *
+ */
+
+#ifndef _LINUX_CYCLADES_H
+#define _LINUX_CYCLADES_H
+
+struct cyclades_monitor {
+ unsigned long int_count;
+ unsigned long char_count;
+ unsigned long char_max;
+ unsigned long char_last;
+};
+
+/*
+ * These stats all reflect activity since the device was last initialized.
+ * (i.e., since the port was opened with no other processes already having it
+ * open)
+ */
+struct cyclades_idle_stats {
+ time_t in_use; /* Time device has been in use (secs) */
+ time_t recv_idle; /* Time since last char received (secs) */
+ time_t xmit_idle; /* Time since last char transmitted (secs) */
+ unsigned long recv_bytes; /* Bytes received */
+ unsigned long xmit_bytes; /* Bytes transmitted */
+ unsigned long overruns; /* Input overruns */
+ unsigned long frame_errs; /* Input framing errors */
+ unsigned long parity_errs; /* Input parity errors */
+};
+
+#define CYCLADES_MAGIC 0x4359
+
+#define CYGETMON 0x435901
+#define CYGETTHRESH 0x435902
+#define CYSETTHRESH 0x435903
+#define CYGETDEFTHRESH 0x435904
+#define CYSETDEFTHRESH 0x435905
+#define CYGETTIMEOUT 0x435906
+#define CYSETTIMEOUT 0x435907
+#define CYGETDEFTIMEOUT 0x435908
+#define CYSETDEFTIMEOUT 0x435909
+#define CYSETRFLOW 0x43590a
+#define CYGETRFLOW 0x43590b
+#define CYSETRTSDTR_INV 0x43590c
+#define CYGETRTSDTR_INV 0x43590d
+#define CYZSETPOLLCYCLE 0x43590e
+#define CYZGETPOLLCYCLE 0x43590f
+#define CYGETCD1400VER 0x435910
+#define CYGETCARDINFO 0x435911
+#define CYSETWAIT 0x435912
+#define CYGETWAIT 0x435913
+
+/*************** CYCLOM-Z ADDITIONS ***************/
+
+#define CZIOC ('M' << 8)
+#define CZ_NBOARDS (CZIOC|0xfa)
+#define CZ_BOOT_START (CZIOC|0xfb)
+#define CZ_BOOT_DATA (CZIOC|0xfc)
+#define CZ_BOOT_END (CZIOC|0xfd)
+#define CZ_TEST (CZIOC|0xfe)
+
+#define CZ_DEF_POLL (HZ/25)
+
+#define MAX_BOARD 4 /* Max number of boards */
+#define MAX_DEV 256 /* Max number of ports total */
+#define CYZ_MAX_SPEED 921600
+
+#define CYZ_FIFO_SIZE 16
+
+#define CYZ_BOOT_NWORDS 0x100
+struct CYZ_BOOT_CTRL {
+ unsigned short nboard;
+ int status[MAX_BOARD];
+ int nchannel[MAX_BOARD];
+ int fw_rev[MAX_BOARD];
+ unsigned long offset;
+ unsigned long data[CYZ_BOOT_NWORDS];
+};
+
+
+#ifndef DP_WINDOW_SIZE
+/* #include "cyclomz.h" */
+/****************** ****************** *******************/
+/*
+ * The data types defined below are used in all ZFIRM interface
+ * data structures. They accomodate differences between HW
+ * architectures and compilers.
+ */
+
+#if defined(__alpha__)
+typedef unsigned long ucdouble; /* 64 bits, unsigned */
+typedef unsigned int uclong; /* 32 bits, unsigned */
+#else
+typedef unsigned long uclong; /* 32 bits, unsigned */
+#endif
+typedef unsigned short ucshort; /* 16 bits, unsigned */
+typedef unsigned char ucchar; /* 8 bits, unsigned */
+
+/*
+ * Memory Window Sizes
+ */
+
+#define DP_WINDOW_SIZE (0x00080000) /* window size 512 Kb */
+#define ZE_DP_WINDOW_SIZE (0x00100000) /* window size 1 Mb (Ze and
+ 8Zo V.2 */
+#define CTRL_WINDOW_SIZE (0x00000080) /* runtime regs 128 bytes */
+
+/*
+ * CUSTOM_REG - Cyclom-Z/PCI Custom Registers Set. The driver
+ * normally will access only interested on the fpga_id, fpga_version,
+ * start_cpu and stop_cpu.
+ */
+
+struct CUSTOM_REG {
+ uclong fpga_id; /* FPGA Identification Register */
+ uclong fpga_version; /* FPGA Version Number Register */
+ uclong cpu_start; /* CPU start Register (write) */
+ uclong cpu_stop; /* CPU stop Register (write) */
+ uclong misc_reg; /* Miscelaneous Register */
+ uclong idt_mode; /* IDT mode Register */
+ uclong uart_irq_status; /* UART IRQ status Register */
+ uclong clear_timer0_irq; /* Clear timer interrupt Register */
+ uclong clear_timer1_irq; /* Clear timer interrupt Register */
+ uclong clear_timer2_irq; /* Clear timer interrupt Register */
+ uclong test_register; /* Test Register */
+ uclong test_count; /* Test Count Register */
+ uclong timer_select; /* Timer select register */
+ uclong pr_uart_irq_status; /* Prioritized UART IRQ stat Reg */
+ uclong ram_wait_state; /* RAM wait-state Register */
+ uclong uart_wait_state; /* UART wait-state Register */
+ uclong timer_wait_state; /* timer wait-state Register */
+ uclong ack_wait_state; /* ACK wait State Register */
+};
+
+/*
+ * RUNTIME_9060 - PLX PCI9060ES local configuration and shared runtime
+ * registers. This structure can be used to access the 9060 registers
+ * (memory mapped).
+ */
+
+struct RUNTIME_9060 {
+ uclong loc_addr_range; /* 00h - Local Address Range */
+ uclong loc_addr_base; /* 04h - Local Address Base */
+ uclong loc_arbitr; /* 08h - Local Arbitration */
+ uclong endian_descr; /* 0Ch - Big/Little Endian Descriptor */
+ uclong loc_rom_range; /* 10h - Local ROM Range */
+ uclong loc_rom_base; /* 14h - Local ROM Base */
+ uclong loc_bus_descr; /* 18h - Local Bus descriptor */
+ uclong loc_range_mst; /* 1Ch - Local Range for Master to PCI */
+ uclong loc_base_mst; /* 20h - Local Base for Master PCI */
+ uclong loc_range_io; /* 24h - Local Range for Master IO */
+ uclong pci_base_mst; /* 28h - PCI Base for Master PCI */
+ uclong pci_conf_io; /* 2Ch - PCI configuration for Master IO */
+ uclong filler1; /* 30h */
+ uclong filler2; /* 34h */
+ uclong filler3; /* 38h */
+ uclong filler4; /* 3Ch */
+ uclong mail_box_0; /* 40h - Mail Box 0 */
+ uclong mail_box_1; /* 44h - Mail Box 1 */
+ uclong mail_box_2; /* 48h - Mail Box 2 */
+ uclong mail_box_3; /* 4Ch - Mail Box 3 */
+ uclong filler5; /* 50h */
+ uclong filler6; /* 54h */
+ uclong filler7; /* 58h */
+ uclong filler8; /* 5Ch */
+ uclong pci_doorbell; /* 60h - PCI to Local Doorbell */
+ uclong loc_doorbell; /* 64h - Local to PCI Doorbell */
+ uclong intr_ctrl_stat; /* 68h - Interrupt Control/Status */
+ uclong init_ctrl; /* 6Ch - EEPROM control, Init Control, etc */
+};
+
+/* Values for the Local Base Address re-map register */
+
+#define WIN_RAM 0x00000001L /* set the sliding window to RAM */
+#define WIN_CREG 0x14000001L /* set the window to custom Registers */
+
+/* Values timer select registers */
+
+#define TIMER_BY_1M 0x00 /* clock divided by 1M */
+#define TIMER_BY_256K 0x01 /* clock divided by 256k */
+#define TIMER_BY_128K 0x02 /* clock divided by 128k */
+#define TIMER_BY_32K 0x03 /* clock divided by 32k */
+
+/****************** ****************** *******************/
+#endif
+
+#ifndef ZFIRM_ID
+/* #include "zfwint.h" */
+/****************** ****************** *******************/
+/*
+ * This file contains the definitions for interfacing with the
+ * Cyclom-Z ZFIRM Firmware.
+ */
+
+/* General Constant definitions */
+
+#define MAX_CHAN 64 /* max number of channels per board */
+
+/* firmware id structure (set after boot) */
+
+#define ID_ADDRESS 0x00000180L /* signature/pointer address */
+#define ZFIRM_ID 0x5557465AL /* ZFIRM/U signature */
+#define ZFIRM_HLT 0x59505B5CL /* ZFIRM needs external power supply */
+#define ZFIRM_RST 0x56040674L /* RST signal (due to FW reset) */
+
+#define ZF_TINACT_DEF 1000 /* default inactivity timeout
+ (1000 ms) */
+#define ZF_TINACT ZF_TINACT_DEF
+
+struct FIRM_ID {
+ uclong signature; /* ZFIRM/U signature */
+ uclong zfwctrl_addr; /* pointer to ZFW_CTRL structure */
+};
+
+/* Op. System id */
+
+#define C_OS_LINUX 0x00000030 /* generic Linux system */
+
+/* channel op_mode */
+
+#define C_CH_DISABLE 0x00000000 /* channel is disabled */
+#define C_CH_TXENABLE 0x00000001 /* channel Tx enabled */
+#define C_CH_RXENABLE 0x00000002 /* channel Rx enabled */
+#define C_CH_ENABLE 0x00000003 /* channel Tx/Rx enabled */
+#define C_CH_LOOPBACK 0x00000004 /* Loopback mode */
+
+/* comm_parity - parity */
+
+#define C_PR_NONE 0x00000000 /* None */
+#define C_PR_ODD 0x00000001 /* Odd */
+#define C_PR_EVEN 0x00000002 /* Even */
+#define C_PR_MARK 0x00000004 /* Mark */
+#define C_PR_SPACE 0x00000008 /* Space */
+#define C_PR_PARITY 0x000000ff
+
+#define C_PR_DISCARD 0x00000100 /* discard char with frame/par error */
+#define C_PR_IGNORE 0x00000200 /* ignore frame/par error */
+
+/* comm_data_l - data length and stop bits */
+
+#define C_DL_CS5 0x00000001
+#define C_DL_CS6 0x00000002
+#define C_DL_CS7 0x00000004
+#define C_DL_CS8 0x00000008
+#define C_DL_CS 0x0000000f
+#define C_DL_1STOP 0x00000010
+#define C_DL_15STOP 0x00000020
+#define C_DL_2STOP 0x00000040
+#define C_DL_STOP 0x000000f0
+
+/* interrupt enabling/status */
+
+#define C_IN_DISABLE 0x00000000 /* zero, disable interrupts */
+#define C_IN_TXBEMPTY 0x00000001 /* tx buffer empty */
+#define C_IN_TXLOWWM 0x00000002 /* tx buffer below LWM */
+#define C_IN_RXHIWM 0x00000010 /* rx buffer above HWM */
+#define C_IN_RXNNDT 0x00000020 /* rx no new data timeout */
+#define C_IN_MDCD 0x00000100 /* modem DCD change */
+#define C_IN_MDSR 0x00000200 /* modem DSR change */
+#define C_IN_MRI 0x00000400 /* modem RI change */
+#define C_IN_MCTS 0x00000800 /* modem CTS change */
+#define C_IN_RXBRK 0x00001000 /* Break received */
+#define C_IN_PR_ERROR 0x00002000 /* parity error */
+#define C_IN_FR_ERROR 0x00004000 /* frame error */
+#define C_IN_OVR_ERROR 0x00008000 /* overrun error */
+#define C_IN_RXOFL 0x00010000 /* RX buffer overflow */
+#define C_IN_IOCTLW 0x00020000 /* I/O control w/ wait */
+#define C_IN_MRTS 0x00040000 /* modem RTS drop */
+
+/* flow control */
+
+#define C_FL_OXX 0x00000001 /* output Xon/Xoff flow control */
+#define C_FL_IXX 0x00000002 /* output Xon/Xoff flow control */
+#define C_FL_OIXANY 0x00000004 /* output Xon/Xoff (any xon) */
+#define C_FL_SWFLOW 0x0000000f
+
+/* flow status */
+
+#define C_FS_TXIDLE 0x00000000 /* no Tx data in the buffer or UART */
+#define C_FS_SENDING 0x00000001 /* UART is sending data */
+#define C_FS_SWFLOW 0x00000002 /* Tx is stopped by received Xoff */
+
+/* rs_control/rs_status RS-232 signals */
+
+#define C_RS_PARAM 0x80000000 /* Indicates presence of parameter in
+ IOCTLM command */
+#define C_RS_RTS 0x00000001 /* RTS */
+#define C_RS_DTR 0x00000004 /* DTR */
+#define C_RS_DCD 0x00000100 /* CD */
+#define C_RS_DSR 0x00000200 /* DSR */
+#define C_RS_RI 0x00000400 /* RI */
+#define C_RS_CTS 0x00000800 /* CTS */
+
+/* commands Host <-> Board */
+
+#define C_CM_RESET 0x01 /* reset/flush buffers */
+#define C_CM_IOCTL 0x02 /* re-read CH_CTRL */
+#define C_CM_IOCTLW 0x03 /* re-read CH_CTRL, intr when done */
+#define C_CM_IOCTLM 0x04 /* RS-232 outputs change */
+#define C_CM_SENDXOFF 0x10 /* send Xoff */
+#define C_CM_SENDXON 0x11 /* send Xon */
+#define C_CM_CLFLOW 0x12 /* Clear flow control (resume) */
+#define C_CM_SENDBRK 0x41 /* send break */
+#define C_CM_INTBACK 0x42 /* Interrupt back */
+#define C_CM_SET_BREAK 0x43 /* Tx break on */
+#define C_CM_CLR_BREAK 0x44 /* Tx break off */
+#define C_CM_CMD_DONE 0x45 /* Previous command done */
+#define C_CM_INTBACK2 0x46 /* Alternate Interrupt back */
+#define C_CM_TINACT 0x51 /* set inactivity detection */
+#define C_CM_IRQ_ENBL 0x52 /* enable generation of interrupts */
+#define C_CM_IRQ_DSBL 0x53 /* disable generation of interrupts */
+#define C_CM_ACK_ENBL 0x54 /* enable acknowledged interrupt mode */
+#define C_CM_ACK_DSBL 0x55 /* disable acknowledged intr mode */
+#define C_CM_FLUSH_RX 0x56 /* flushes Rx buffer */
+#define C_CM_FLUSH_TX 0x57 /* flushes Tx buffer */
+#define C_CM_Q_ENABLE 0x58 /* enables queue access from the
+ driver */
+#define C_CM_Q_DISABLE 0x59 /* disables queue access from the
+ driver */
+
+#define C_CM_TXBEMPTY 0x60 /* Tx buffer is empty */
+#define C_CM_TXLOWWM 0x61 /* Tx buffer low water mark */
+#define C_CM_RXHIWM 0x62 /* Rx buffer high water mark */
+#define C_CM_RXNNDT 0x63 /* rx no new data timeout */
+#define C_CM_MDCD 0x70 /* modem DCD change */
+#define C_CM_MDSR 0x71 /* modem DSR change */
+#define C_CM_MRI 0x72 /* modem RI change */
+#define C_CM_MCTS 0x73 /* modem CTS change */
+#define C_CM_MRTS 0x74 /* modem RTS drop */
+#define C_CM_RXBRK 0x84 /* Break received */
+#define C_CM_PR_ERROR 0x85 /* Parity error */
+#define C_CM_FR_ERROR 0x86 /* Frame error */
+#define C_CM_OVR_ERROR 0x87 /* Overrun error */
+#define C_CM_RXOFL 0x88 /* RX buffer overflow */
+#define C_CM_CMDERROR 0x90 /* command error */
+#define C_CM_FATAL 0x91 /* fatal error */
+#define C_CM_HW_RESET 0x92 /* reset board */
+
+/*
+ * CH_CTRL - This per port structure contains all parameters
+ * that control an specific port. It can be seen as the
+ * configuration registers of a "super-serial-controller".
+ */
+
+struct CH_CTRL {
+ uclong op_mode; /* operation mode */
+ uclong intr_enable; /* interrupt masking */
+ uclong sw_flow; /* SW flow control */
+ uclong flow_status; /* output flow status */
+ uclong comm_baud; /* baud rate - numerically specified */
+ uclong comm_parity; /* parity */
+ uclong comm_data_l; /* data length/stop */
+ uclong comm_flags; /* other flags */
+ uclong hw_flow; /* HW flow control */
+ uclong rs_control; /* RS-232 outputs */
+ uclong rs_status; /* RS-232 inputs */
+ uclong flow_xon; /* xon char */
+ uclong flow_xoff; /* xoff char */
+ uclong hw_overflow; /* hw overflow counter */
+ uclong sw_overflow; /* sw overflow counter */
+ uclong comm_error; /* frame/parity error counter */
+};
+
+
+/*
+ * BUF_CTRL - This per channel structure contains
+ * all Tx and Rx buffer control for a given channel.
+ */
+
+struct BUF_CTRL {
+ uclong flag_dma; /* buffers are in Host memory */
+ uclong tx_bufaddr; /* address of the tx buffer */
+ uclong tx_bufsize; /* tx buffer size */
+ uclong tx_threshold; /* tx low water mark */
+ uclong tx_get; /* tail index tx buf */
+ uclong tx_put; /* head index tx buf */
+ uclong rx_bufaddr; /* address of the rx buffer */
+ uclong rx_bufsize; /* rx buffer size */
+ uclong rx_threshold; /* rx high water mark */
+ uclong rx_get; /* tail index rx buf */
+ uclong rx_put; /* head index rx buf */
+ uclong filler[5]; /* filler to align structures */
+};
+
+/*
+ * BOARD_CTRL - This per board structure contains all global
+ * control fields related to the board.
+ */
+
+struct BOARD_CTRL {
+
+ /* static info provided by the on-board CPU */
+ uclong n_channel; /* number of channels */
+ uclong fw_version; /* firmware version */
+
+ /* static info provided by the driver */
+ uclong op_system; /* op_system id */
+ uclong dr_version; /* driver version */
+
+ /* board control area */
+ uclong inactivity; /* inactivity control */
+
+ /* host to FW commands */
+ uclong hcmd_channel; /* channel number */
+ uclong hcmd_param; /* pointer to parameters */
+
+ /* FW to Host commands */
+ uclong fwcmd_channel; /* channel number */
+ uclong fwcmd_param; /* pointer to parameters */
+ uclong zf_int_queue_addr; /* offset for INT_QUEUE structure */
+
+ /* filler so the structures are aligned */
+ uclong filler[6];
+};
+
+/* Host Interrupt Queue */
+
+#define QUEUE_SIZE (10*MAX_CHAN)
+
+struct INT_QUEUE {
+ unsigned char intr_code[QUEUE_SIZE];
+ unsigned long channel[QUEUE_SIZE];
+ unsigned long param[QUEUE_SIZE];
+ unsigned long put;
+ unsigned long get;
+};
+
+/*
+ * ZFW_CTRL - This is the data structure that includes all other
+ * data structures used by the Firmware.
+ */
+
+struct ZFW_CTRL {
+ struct BOARD_CTRL board_ctrl;
+ struct CH_CTRL ch_ctrl[MAX_CHAN];
+ struct BUF_CTRL buf_ctrl[MAX_CHAN];
+};
+
+/****************** ****************** *******************/
+#endif
+
+
+
+
+#ifdef __KERNEL__
+
+/***************************************
+ * Memory access functions/macros *
+ * (required to support Alpha systems) *
+ ***************************************/
+
+#define cy_writeb(port,val) {writeb((ucchar)(val),(ulong)(port)); mb();}
+#define cy_writew(port,val) {writew((ushort)(val),(ulong)(port)); mb();}
+#define cy_writel(port,val) {writel((uclong)(val),(ulong)(port)); mb();}
+
+#define cy_readb(port) readb(port)
+#define cy_readw(port) readw(port)
+#define cy_readl(port) readl(port)
+
+/* Per card data structure */
+
+struct cyclades_card {
+ long base_addr;
+ long ctl_addr;
+ int irq;
+ int num_chips; /* 0 if card absent, -1 if Z/PCI, else Y */
+ int first_line; /* minor number of first channel on card */
+ int bus_index; /* address shift - 0 for ISA, 1 for PCI */
+ int intr_enabled; /* FW Interrupt flag - 0 disabled, 1 enabled */
+};
+
+struct cyclades_chip {
+ int filler;
+};
+
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+struct cyclades_port {
+ int magic;
+ int card;
+ int line;
+ int flags; /* defined in tty.h */
+ int type; /* UART type */
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int xmit_fifo_size;
+ int cor1,cor2,cor3,cor4,cor5;
+ int tbpr,tco,rbpr,rco;
+ int baud;
+ int rflow;
+ int rtsdtr_inv;
+ int chip_rev;
+ int custom_divisor;
+ int x_char; /* to be pushed out ASAP */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned long event;
+ unsigned long last_active;
+ int count; /* # of fd on device */
+ int breakon;
+ int breakoff;
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ int default_threshold;
+ int default_timeout;
+ struct tq_struct tqueue;
+ struct termios normal_termios;
+ struct termios callout_termios;
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+ struct wait_queue *shutdown_wait;
+ struct cyclades_monitor mon;
+ unsigned long jiffies[3];
+ unsigned long rflush_count;
+ struct cyclades_idle_stats idle_stats;
+};
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at cy interrupt time.
+ */
+#define Cy_EVENT_READ_PROCESS 0
+#define Cy_EVENT_WRITE_WAKEUP 1
+#define Cy_EVENT_HANGUP 2
+#define Cy_EVENT_BREAK 3
+#define Cy_EVENT_OPEN_WAKEUP 4
+#define Cy_EVENT_SHUTDOWN_WAKEUP 5
+
+#define CLOSING_WAIT_DELAY 30*HZ
+#define CY_CLOSING_WAIT_NONE 65535
+#define CY_CLOSING_WAIT_INF 0
+
+
+#define CyMAX_CHIPS_PER_CARD 8
+#define CyMAX_CHAR_FIFO 12
+#define CyPORTS_PER_CHIP 4
+#define CD1400_MAX_SPEED 115200
+
+#define CyISA_Ywin 0x2000
+
+#define CyPCI_Ywin 0x4000
+#define CyPCI_Yctl 0x80
+#define CyPCI_Zctl CTRL_WINDOW_SIZE
+#define CyPCI_Zwin 0x80000
+#define CyPCI_Ze_win (2 * CyPCI_Zwin)
+
+#define PCI_DEVICE_ID_MASK 0x06
+
+/**** CD1400 registers ****/
+
+#define CD1400_REV_G 0x46
+#define CD1400_REV_J 0x48
+
+#define CyRegSize 0x0400
+#define Cy_HwReset 0x1400
+#define Cy_ClrIntr 0x1800
+#define Cy_EpldRev 0x1e00
+
+/* Global Registers */
+
+#define CyGFRCR (0x40*2)
+#define CyRevE (44)
+#define CyCAR (0x68*2)
+#define CyCHAN_0 (0x00)
+#define CyCHAN_1 (0x01)
+#define CyCHAN_2 (0x02)
+#define CyCHAN_3 (0x03)
+#define CyGCR (0x4B*2)
+#define CyCH0_SERIAL (0x00)
+#define CyCH0_PARALLEL (0x80)
+#define CySVRR (0x67*2)
+#define CySRModem (0x04)
+#define CySRTransmit (0x02)
+#define CySRReceive (0x01)
+#define CyRICR (0x44*2)
+#define CyTICR (0x45*2)
+#define CyMICR (0x46*2)
+#define CyICR0 (0x00)
+#define CyICR1 (0x01)
+#define CyICR2 (0x02)
+#define CyICR3 (0x03)
+#define CyRIR (0x6B*2)
+#define CyTIR (0x6A*2)
+#define CyMIR (0x69*2)
+#define CyIRDirEq (0x80)
+#define CyIRBusy (0x40)
+#define CyIRUnfair (0x20)
+#define CyIRContext (0x1C)
+#define CyIRChannel (0x03)
+#define CyPPR (0x7E*2)
+#define CyCLOCK_20_1MS (0x27)
+#define CyCLOCK_25_1MS (0x31)
+#define CyCLOCK_25_5MS (0xf4)
+#define CyCLOCK_60_1MS (0x75)
+#define CyCLOCK_60_2MS (0xea)
+
+/* Virtual Registers */
+
+#define CyRIVR (0x43*2)
+#define CyTIVR (0x42*2)
+#define CyMIVR (0x41*2)
+#define CyIVRMask (0x07)
+#define CyIVRRxEx (0x07)
+#define CyIVRRxOK (0x03)
+#define CyIVRTxOK (0x02)
+#define CyIVRMdmOK (0x01)
+#define CyTDR (0x63*2)
+#define CyRDSR (0x62*2)
+#define CyTIMEOUT (0x80)
+#define CySPECHAR (0x70)
+#define CyBREAK (0x08)
+#define CyPARITY (0x04)
+#define CyFRAME (0x02)
+#define CyOVERRUN (0x01)
+#define CyMISR (0x4C*2)
+/* see CyMCOR_ and CyMSVR_ for bits*/
+#define CyEOSRR (0x60*2)
+
+/* Channel Registers */
+
+#define CyLIVR (0x18*2)
+#define CyMscsr (0x01)
+#define CyTdsr (0x02)
+#define CyRgdsr (0x03)
+#define CyRedsr (0x07)
+#define CyCCR (0x05*2)
+/* Format 1 */
+#define CyCHAN_RESET (0x80)
+#define CyCHIP_RESET (0x81)
+#define CyFlushTransFIFO (0x82)
+/* Format 2 */
+#define CyCOR_CHANGE (0x40)
+#define CyCOR1ch (0x02)
+#define CyCOR2ch (0x04)
+#define CyCOR3ch (0x08)
+/* Format 3 */
+#define CySEND_SPEC_1 (0x21)
+#define CySEND_SPEC_2 (0x22)
+#define CySEND_SPEC_3 (0x23)
+#define CySEND_SPEC_4 (0x24)
+/* Format 4 */
+#define CyCHAN_CTL (0x10)
+#define CyDIS_RCVR (0x01)
+#define CyENB_RCVR (0x02)
+#define CyDIS_XMTR (0x04)
+#define CyENB_XMTR (0x08)
+#define CySRER (0x06*2)
+#define CyMdmCh (0x80)
+#define CyRxData (0x10)
+#define CyTxRdy (0x04)
+#define CyTxMpty (0x02)
+#define CyNNDT (0x01)
+#define CyCOR1 (0x08*2)
+#define CyPARITY_NONE (0x00)
+#define CyPARITY_0 (0x20)
+#define CyPARITY_1 (0xA0)
+#define CyPARITY_E (0x40)
+#define CyPARITY_O (0xC0)
+#define Cy_1_STOP (0x00)
+#define Cy_1_5_STOP (0x04)
+#define Cy_2_STOP (0x08)
+#define Cy_5_BITS (0x00)
+#define Cy_6_BITS (0x01)
+#define Cy_7_BITS (0x02)
+#define Cy_8_BITS (0x03)
+#define CyCOR2 (0x09*2)
+#define CyIXM (0x80)
+#define CyTxIBE (0x40)
+#define CyETC (0x20)
+#define CyAUTO_TXFL (0x60)
+#define CyLLM (0x10)
+#define CyRLM (0x08)
+#define CyRtsAO (0x04)
+#define CyCtsAE (0x02)
+#define CyDsrAE (0x01)
+#define CyCOR3 (0x0A*2)
+#define CySPL_CH_DRANGE (0x80) /* special character detect range */
+#define CySPL_CH_DET1 (0x40) /* enable special character detection
+ on SCHR4-SCHR3 */
+#define CyFL_CTRL_TRNSP (0x20) /* Flow Control Transparency */
+#define CySPL_CH_DET2 (0x10) /* Enable special character detection
+ on SCHR2-SCHR1 */
+#define CyREC_FIFO (0x0F) /* Receive FIFO threshold */
+#define CyCOR4 (0x1E*2)
+#define CyCOR5 (0x1F*2)
+#define CyCCSR (0x0B*2)
+#define CyRxEN (0x80)
+#define CyRxFloff (0x40)
+#define CyRxFlon (0x20)
+#define CyTxEN (0x08)
+#define CyTxFloff (0x04)
+#define CyTxFlon (0x02)
+#define CyRDCR (0x0E*2)
+#define CySCHR1 (0x1A*2)
+#define CySCHR2 (0x1B*2)
+#define CySCHR3 (0x1C*2)
+#define CySCHR4 (0x1D*2)
+#define CySCRL (0x22*2)
+#define CySCRH (0x23*2)
+#define CyLNC (0x24*2)
+#define CyMCOR1 (0x15*2)
+#define CyMCOR2 (0x16*2)
+#define CyRTPR (0x21*2)
+#define CyMSVR1 (0x6C*2)
+#define CyMSVR2 (0x6D*2)
+#define CyDSR (0x80)
+#define CyCTS (0x40)
+#define CyRI (0x20)
+#define CyDCD (0x10)
+#define CyDTR (0x02)
+#define CyRTS (0x01)
+#define CyPVSR (0x6F*2)
+#define CyRBPR (0x78*2)
+#define CyRCOR (0x7C*2)
+#define CyTBPR (0x72*2)
+#define CyTCOR (0x76*2)
+
+/* Custom Registers */
+
+#define CyPLX_VER (0x3400)
+#define PLX_9050 0x0b
+#define PLX_9060 0x0c
+#define PLX_9080 0x0d
+
+/***************************************************************************/
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_CYCLADES_H */
diff --git a/pfinet/linux-src/include/linux/dcache.h b/pfinet/linux-src/include/linux/dcache.h
new file mode 100644
index 00000000..84e1376b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/dcache.h
@@ -0,0 +1,194 @@
+#ifndef __LINUX_DCACHE_H
+#define __LINUX_DCACHE_H
+
+#ifdef __KERNEL__
+
+/*
+ * linux/include/linux/dcache.h
+ *
+ * Dirent cache data structures
+ *
+ * (C) Copyright 1997 Thomas Schoebel-Theuer,
+ * with heavy changes by Linus Torvalds
+ */
+
+#define D_MAXLEN 1024
+
+#define IS_ROOT(x) ((x) == (x)->d_parent)
+
+/*
+ * "quick string" -- eases parameter passing, but more importantly
+ * saves "metadata" about the string (ie length and the hash).
+ */
+struct qstr {
+ const unsigned char * name;
+ unsigned int len;
+ unsigned int hash;
+};
+
+/* Name hashing routines. Initial hash value */
+#define init_name_hash() 0
+
+/* partial hash update function. Assume roughly 4 bits per character */
+static __inline__ unsigned long partial_name_hash(unsigned long c, unsigned long prevhash)
+{
+ prevhash = (prevhash << 4) | (prevhash >> (8*sizeof(unsigned long)-4));
+ return prevhash ^ c;
+}
+
+/* Finally: cut down the number of bits to a int value (and try to avoid losing bits) */
+static __inline__ unsigned long end_name_hash(unsigned long hash)
+{
+ if (sizeof(hash) > sizeof(unsigned int))
+ hash += hash >> 4*sizeof(hash);
+ return (unsigned int) hash;
+}
+
+/* Compute the hash for a name string. */
+static __inline__ unsigned int full_name_hash(const unsigned char * name, unsigned int len)
+{
+ unsigned long hash = init_name_hash();
+ while (len--)
+ hash = partial_name_hash(*name++, hash);
+ return end_name_hash(hash);
+}
+
+#define DNAME_INLINE_LEN 16
+
+struct dentry {
+ int d_count;
+ unsigned int d_flags;
+ struct inode * d_inode; /* Where the name belongs to - NULL is negative */
+ struct dentry * d_parent; /* parent directory */
+ struct dentry * d_mounts; /* mount information */
+ struct dentry * d_covers;
+ struct list_head d_hash; /* lookup hash list */
+ struct list_head d_lru; /* d_count = 0 LRU list */
+ struct list_head d_child; /* child of parent list */
+ struct list_head d_subdirs; /* our children */
+ struct list_head d_alias; /* inode alias list */
+ struct qstr d_name;
+ unsigned long d_time; /* used by d_revalidate */
+ struct dentry_operations *d_op;
+ struct super_block * d_sb; /* The root of the dentry tree */
+ unsigned long d_reftime; /* last time referenced */
+ void * d_fsdata; /* fs-specific data */
+ unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
+};
+
+struct dentry_operations {
+ int (*d_revalidate)(struct dentry *, int);
+ int (*d_hash) (struct dentry *, struct qstr *);
+ int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
+ void (*d_delete)(struct dentry *);
+ void (*d_release)(struct dentry *);
+ void (*d_iput)(struct dentry *, struct inode *);
+};
+
+/* the dentry parameter passed to d_hash and d_compare is the parent
+ * directory of the entries to be compared. It is used in case these
+ * functions need any directory specific information for determining
+ * equivalency classes. Using the dentry itself might not work, as it
+ * might be a negative dentry which has no information associated with
+ * it */
+
+
+
+/* d_flags entries */
+#define DCACHE_AUTOFS_PENDING 0x0001 /* autofs: "under construction" */
+#define DCACHE_NFSFS_RENAMED 0x0002 /* this dentry has been "silly
+ * renamed" and has to be
+ * deleted on the last dput()
+ */
+
+/*
+ * d_drop() unhashes the entry from the parent
+ * dentry hashes, so that it won't be found through
+ * a VFS lookup any more. Note that this is different
+ * from deleting the dentry - d_delete will try to
+ * mark the dentry negative if possible, giving a
+ * successful _negative_ lookup, while d_drop will
+ * just make the cache lookup fail.
+ *
+ * d_drop() is used mainly for stuff that wants
+ * to invalidate a dentry for some reason (NFS
+ * timeouts or autofs deletes).
+ */
+static __inline__ void d_drop(struct dentry * dentry)
+{
+ list_del(&dentry->d_hash);
+ INIT_LIST_HEAD(&dentry->d_hash);
+}
+
+static __inline__ int dname_external(struct dentry *d)
+{
+ return d->d_name.name != d->d_iname;
+}
+
+/*
+ * These are the low-level FS interfaces to the dcache..
+ */
+extern void d_instantiate(struct dentry *, struct inode *);
+extern void d_delete(struct dentry *);
+
+/* allocate/de-allocate */
+extern struct dentry * d_alloc(struct dentry * parent, const struct qstr *name);
+extern void prune_dcache(int);
+extern void shrink_dcache_sb(struct super_block *);
+extern void shrink_dcache_parent(struct dentry *);
+extern int d_invalidate(struct dentry *);
+
+#define shrink_dcache() prune_dcache(0)
+
+/* dcache memory management */
+extern int select_dcache(int, int);
+extern void shrink_dcache_memory(int, unsigned int);
+extern void check_dcache_memory(void);
+extern void free_inode_memory(int); /* defined in fs/inode.c */
+
+/* only used at mount-time */
+extern struct dentry * d_alloc_root(struct inode * root_inode, struct dentry * old_root);
+
+/* test whether root is busy without destroying dcache */
+extern int is_root_busy(struct dentry *);
+
+/*
+ * This adds the entry to the hash queues.
+ */
+extern void d_rehash(struct dentry * entry);
+/*
+ * This adds the entry to the hash queues and initializes "d_inode".
+ * The entry was actually filled in earlier during "d_alloc()"
+ */
+static __inline__ void d_add(struct dentry * entry, struct inode * inode)
+{
+ d_rehash(entry);
+ d_instantiate(entry, inode);
+}
+
+/* used for rename() and baskets */
+extern void d_move(struct dentry * entry, struct dentry * newdentry);
+
+/* appendix may either be NULL or be used for transname suffixes */
+extern struct dentry * d_lookup(struct dentry * dir, struct qstr * name);
+
+/* validate "insecure" dentry pointer */
+extern int d_validate(struct dentry *dentry, struct dentry *dparent,
+ unsigned int hash, unsigned int len);
+
+/* write full pathname into buffer and return start of pathname */
+extern char * d_path(struct dentry * entry, char * buf, int buflen);
+
+/* Allocation counts.. */
+static __inline__ struct dentry * dget(struct dentry *dentry)
+{
+ if (dentry)
+ dentry->d_count++;
+ return dentry;
+}
+
+extern void dput(struct dentry *);
+
+#endif /* __KERNEL__ */
+
+#endif /* __LINUX_DCACHE_H */
diff --git a/pfinet/linux-src/include/linux/delay.h b/pfinet/linux-src/include/linux/delay.h
new file mode 100644
index 00000000..e1cf03d6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/delay.h
@@ -0,0 +1,37 @@
+#ifndef _LINUX_DELAY_H
+#define _LINUX_DELAY_H
+
+/*
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines, using a pre-computed "loops_per_second" value.
+ */
+
+extern unsigned long loops_per_sec;
+
+#include <asm/delay.h>
+
+/*
+ * Using udelay() for intervals greater than a few milliseconds can
+ * risk overflow for high loops_per_sec (high bogomips) machines. The
+ * mdelay() provides a wrapper to prevent this. For delays greater
+ * than MAX_UDELAY_MS milliseconds, the wrapper is used. Architecture
+ * specific values can be defined in asm-???/delay.h as an override.
+ * The 2nd mdelay() definition ensures GCC will optimize away the
+ * while loop for the common cases where n <= MAX_UDELAY_MS -- Paul G.
+ */
+
+#ifndef MAX_UDELAY_MS
+#define MAX_UDELAY_MS 5
+#endif
+
+#ifdef notdef
+#define mdelay(n) (\
+ {unsigned long msec=(n); while (msec--) udelay(1000);})
+#else
+#define mdelay(n) (\
+ (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
+ ({unsigned long msec=(n); while (msec--) udelay(1000);}))
+#endif
+
+#endif /* defined(_LINUX_DELAY_H) */
diff --git a/pfinet/linux-src/include/linux/devpts_fs.h b/pfinet/linux-src/include/linux/devpts_fs.h
new file mode 100644
index 00000000..d9dfbb44
--- /dev/null
+++ b/pfinet/linux-src/include/linux/devpts_fs.h
@@ -0,0 +1,74 @@
+/* -*- linux-c -*- --------------------------------------------------------- *
+ *
+ * linux/include/linux/devpts_fs.h
+ *
+ * Copyright 1998 H. Peter Anvin -- All Rights Reserved
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+/*
+ * Prototypes for the pty driver <-> devpts filesystem interface. Most
+ * of this is really just a hack so we can exclude it or build it as a
+ * module, and probably should go away eventually.
+ */
+
+#ifndef _LINUX_DEVPTS_FS_H
+#define _LINUX_DEVPTS_FS_H 1
+
+#include <linux/config.h>
+#include <linux/kdev_t.h>
+#include <linux/tty.h>
+
+#ifdef CONFIG_DEVPTS_FS
+
+void devpts_pty_new(int, kdev_t);
+void devpts_pty_kill(int);
+#define unix98_max_ptys NR_PTYS * UNIX98_NR_MAJORS;
+
+#elif defined(CONFIG_DEVPTS_FS_MODULE)
+
+#ifdef BUILDING_PTY_C
+void (*devpts_upcall_new)(int,kdev_t) = NULL;
+void (*devpts_upcall_kill)(int) = NULL;
+unsigned int unix98_max_ptys = NR_PTYS * UNIX98_NR_MAJORS;
+
+EXPORT_SYMBOL(devpts_upcall_new);
+EXPORT_SYMBOL(devpts_upcall_kill);
+EXPORT_SYMBOL(unix98_max_ptys);
+#else
+extern void (*devpts_upcall_new)(int,kdev_t);
+extern void (*devpts_upcall_kill)(int);
+extern unsigned int unix98_max_ptys;
+#endif
+
+#ifndef BUILDING_DEVPTS
+extern inline void
+devpts_pty_new(int line, kdev_t device)
+{
+ if ( devpts_upcall_new )
+ return devpts_upcall_new(line,device);
+}
+
+extern inline void
+devpts_pty_kill(int line)
+{
+ if ( devpts_upcall_kill )
+ return devpts_upcall_kill(line);
+}
+#endif
+
+#else /* No /dev/pts filesystem at all */
+
+extern inline void
+devpts_pty_new(int line, kdev_t device) { }
+
+extern inline void
+devpts_pty_kill(int line) { }
+
+#endif
+
+#endif /* _LINUX_DEVPTS_FS_H */
diff --git a/pfinet/linux-src/include/linux/digi1.h b/pfinet/linux-src/include/linux/digi1.h
new file mode 100644
index 00000000..184378d2
--- /dev/null
+++ b/pfinet/linux-src/include/linux/digi1.h
@@ -0,0 +1,100 @@
+/* Definitions for DigiBoard ditty(1) command. */
+
+#if !defined(TIOCMODG)
+#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */
+#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */
+#endif
+
+#if !defined(TIOCMSET)
+#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */
+#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */
+#endif
+
+#if !defined(TIOCMBIC)
+#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */
+#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */
+#endif
+
+#if !defined(TIOCSDTR)
+#define TIOCSDTR ('e'<<8) | 0 /* set DTR */
+#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */
+#endif
+
+/************************************************************************
+ * Ioctl command arguments for DIGI parameters.
+ ************************************************************************/
+#define DIGI_GETA ('e'<<8) | 94 /* Read params */
+
+#define DIGI_SETA ('e'<<8) | 95 /* Set params */
+#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */
+#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */
+
+#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */
+ /* control characters */
+#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */
+ /* control characters */
+#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */
+ /* flow control chars */
+#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */
+ /* flow control chars */
+
+#define DIGI_GETINFO ('e'<<8) | 103 /* Fill in digi_info */
+#define DIGI_POLLER ('e'<<8) | 104 /* Turn on/off poller */
+#define DIGI_INIT ('e'<<8) | 105 /* Allow things to run. */
+
+struct digiflow_struct
+{
+ unsigned char startc; /* flow cntl start char */
+ unsigned char stopc; /* flow cntl stop char */
+};
+
+typedef struct digiflow_struct digiflow_t;
+
+
+/************************************************************************
+ * Values for digi_flags
+ ************************************************************************/
+#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */
+#define DIGI_FAST 0x0002 /* Fast baud rates */
+#define RTSPACE 0x0004 /* RTS input flow control */
+#define CTSPACE 0x0008 /* CTS output flow control */
+#define DSRPACE 0x0010 /* DSR output flow control */
+#define DCDPACE 0x0020 /* DCD output flow control */
+#define DTRPACE 0x0040 /* DTR input flow control */
+#define DIGI_FORCEDCD 0x0100 /* Force carrier */
+#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */
+#define DIGI_AIXON 0x0400 /* Aux flow control in fep */
+
+
+/************************************************************************
+ * Values for digiDload
+ ************************************************************************/
+#define NORMAL 0
+#define PCI_CTL 1
+
+#define SIZE8 0
+#define SIZE16 1
+#define SIZE32 2
+
+/************************************************************************
+ * Structure used with ioctl commands for DIGI parameters.
+ ************************************************************************/
+struct digi_struct
+{
+ unsigned short digi_flags; /* Flags (see above) */
+};
+
+typedef struct digi_struct digi_t;
+
+struct digi_info
+{
+ unsigned long board; /* Which board is this ? */
+ unsigned char status; /* Alive or dead */
+ unsigned char type; /* see epca.h */
+ unsigned char subtype; /* For future XEM, XR, etc ... */
+ unsigned short numports; /* Number of ports configured */
+ unsigned char *port; /* I/O Address */
+ unsigned char *membase; /* DPR Address */
+ unsigned char *version; /* For future ... */
+ unsigned short windowData; /* For future ... */
+} ;
diff --git a/pfinet/linux-src/include/linux/digiFep1.h b/pfinet/linux-src/include/linux/digiFep1.h
new file mode 100644
index 00000000..c47d7fcb
--- /dev/null
+++ b/pfinet/linux-src/include/linux/digiFep1.h
@@ -0,0 +1,136 @@
+
+#define CSTART 0x400L
+#define CMAX 0x800L
+#define ISTART 0x800L
+#define IMAX 0xC00L
+#define CIN 0xD10L
+#define GLOBAL 0xD10L
+#define EIN 0xD18L
+#define FEPSTAT 0xD20L
+#define CHANSTRUCT 0x1000L
+#define RXTXBUF 0x4000L
+
+
+struct global_data
+{
+ volatile ushort cin;
+ volatile ushort cout;
+ volatile ushort cstart;
+ volatile ushort cmax;
+ volatile ushort ein;
+ volatile ushort eout;
+ volatile ushort istart;
+ volatile ushort imax;
+};
+
+
+struct board_chan
+{
+ int filler1;
+ int filler2;
+ volatile ushort tseg;
+ volatile ushort tin;
+ volatile ushort tout;
+ volatile ushort tmax;
+
+ volatile ushort rseg;
+ volatile ushort rin;
+ volatile ushort rout;
+ volatile ushort rmax;
+
+ volatile ushort tlow;
+ volatile ushort rlow;
+ volatile ushort rhigh;
+ volatile ushort incr;
+
+ volatile ushort etime;
+ volatile ushort edelay;
+ volatile unchar *dev;
+
+ volatile ushort iflag;
+ volatile ushort oflag;
+ volatile ushort cflag;
+ volatile ushort gmask;
+
+ volatile ushort col;
+ volatile ushort delay;
+ volatile ushort imask;
+ volatile ushort tflush;
+
+ int filler3;
+ int filler4;
+ int filler5;
+ int filler6;
+
+ volatile unchar num;
+ volatile unchar ract;
+ volatile unchar bstat;
+ volatile unchar tbusy;
+ volatile unchar iempty;
+ volatile unchar ilow;
+ volatile unchar idata;
+ volatile unchar eflag;
+
+ volatile unchar tflag;
+ volatile unchar rflag;
+ volatile unchar xmask;
+ volatile unchar xval;
+ volatile unchar mstat;
+ volatile unchar mchange;
+ volatile unchar mint;
+ volatile unchar lstat;
+
+ volatile unchar mtran;
+ volatile unchar orun;
+ volatile unchar startca;
+ volatile unchar stopca;
+ volatile unchar startc;
+ volatile unchar stopc;
+ volatile unchar vnext;
+ volatile unchar hflow;
+
+ volatile unchar fillc;
+ volatile unchar ochar;
+ volatile unchar omask;
+
+ unchar filler7;
+ unchar filler8[28];
+};
+
+
+#define SRXLWATER 0xE0
+#define SRXHWATER 0xE1
+#define STOUT 0xE2
+#define PAUSETX 0xE3
+#define RESUMETX 0xE4
+#define SAUXONOFFC 0xE6
+#define SENDBREAK 0xE8
+#define SETMODEM 0xE9
+#define SETIFLAGS 0xEA
+#define SONOFFC 0xEB
+#define STXLWATER 0xEC
+#define PAUSERX 0xEE
+#define RESUMERX 0xEF
+#define SETBUFFER 0xF2
+#define SETCOOKED 0xF3
+#define SETHFLOW 0xF4
+#define SETCTRLFLAGS 0xF5
+#define SETVNEXT 0xF6
+
+
+
+#define BREAK_IND 0x01
+#define LOWTX_IND 0x02
+#define EMPTYTX_IND 0x04
+#define DATA_IND 0x08
+#define MODEMCHG_IND 0x20
+
+#define FEP_HUPCL 0002000
+#if 0
+#define RTS 0x02
+#define CD 0x08
+#define DSR 0x10
+#define CTS 0x20
+#define RI 0x40
+#define DTR 0x80
+#endif
diff --git a/pfinet/linux-src/include/linux/digiPCI.h b/pfinet/linux-src/include/linux/digiPCI.h
new file mode 100644
index 00000000..6ca7819e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/digiPCI.h
@@ -0,0 +1,42 @@
+/*************************************************************************
+ * Defines and structure definitions for PCI BIOS Interface
+ *************************************************************************/
+#define PCIMAX 32 /* maximum number of PCI boards */
+
+
+#define PCI_VENDOR_DIGI 0x114F
+#define PCI_DEVICE_EPC 0x0002
+#define PCI_DEVICE_RIGHTSWITCH 0x0003 /* For testing */
+#define PCI_DEVICE_XEM 0x0004
+#define PCI_DEVICE_XR 0x0005
+#define PCI_DEVICE_CX 0x0006
+#define PCI_DEVICE_XRJ 0x0009 /* Jupiter boards with */
+#define PCI_DEVICE_EPCJ 0x000a /* PLX 9060 chip for PCI */
+
+
+/*
+ * On the PCI boards, there is no IO space allocated
+ * The I/O registers will be in the first 3 bytes of the
+ * upper 2MB of the 4MB memory space. The board memory
+ * will be mapped into the low 2MB of the 4MB memory space
+ */
+
+/* Potential location of PCI Bios from E0000 to FFFFF*/
+#define PCI_BIOS_SIZE 0x00020000
+
+/* Size of Memory and I/O for PCI (4MB) */
+#define PCI_RAM_SIZE 0x00400000
+
+/* Size of Memory (2MB) */
+#define PCI_MEM_SIZE 0x00200000
+
+/* Offset of I/0 in Memory (2MB) */
+#define PCI_IO_OFFSET 0x00200000
+
+#define MEMOUTB(basemem, pnum, setmemval) *(caddr_t)((basemem) + ( PCI_IO_OFFSET | pnum << 4 | pnum )) = (setmemval)
+#define MEMINB(basemem, pnum) *(caddr_t)((basemem) + (PCI_IO_OFFSET | pnum << 4 | pnum )) /* for PCI I/O */
+
+
+
+
+
diff --git a/pfinet/linux-src/include/linux/dio.h b/pfinet/linux-src/include/linux/dio.h
new file mode 100644
index 00000000..087b06ec
--- /dev/null
+++ b/pfinet/linux-src/include/linux/dio.h
@@ -0,0 +1,204 @@
+/* header file for DIO boards for the HP300 architecture.
+ * Maybe this should handle DIO-II later?
+ * The general structure of this is vaguely based on how
+ * the Amiga port handles Zorro boards.
+ * Copyright (C) Peter Maydell 05/1998 <pmaydell@chiark.greenend.org.uk>
+ *
+ * The board IDs are from the NetBSD kernel, which for once provided
+ * helpful comments...
+ *
+ * This goes with arch/m68k/hp300/dio.c
+ */
+
+#ifndef _LINUX_DIO_H
+#define _LINUX_DIO_H
+
+/* The DIO boards in a system are distinguished by 'select codes' which
+ * range from 0-63 (DIO) and 132-255 (DIO-II).
+ * The DIO board with select code sc is located at physical address
+ * 0x600000 + sc * 0x10000
+ * So DIO cards cover [0x600000-0x800000); the areas [0x200000-0x400000) and
+ * [0x800000-0x1000000) are for additional space required by things
+ * like framebuffers. [0x400000-0x600000) is for miscellaneous internal I/O.
+ * On Linux, this is currently all mapped into the virtual address space
+ * at 0xf0000000 on bootup.
+ * DIO-II boards are at 0x1000000 + (sc - 132) * 0x400000
+ * which is address range [0x1000000-0x20000000) -- too big to map completely,
+ * so currently we just don't handle DIO-II boards. It wouldn't be hard to
+ * do with ioremap() though.
+ */
+#ifdef __KERNEL__
+/* DIO/DIO-II boards all have the following 8bit registers.
+ * These are offsets from the base of the device.
+ */
+#define DIO_IDOFF 0x01 /* primary device ID */
+#define DIO_IPLOFF 0x03 /* interrupt priority level */
+#define DIO_SECIDOFF 0x15 /* secondary device ID */
+#define DIOII_SIZEOFF 0x101 /* device size, DIO-II only */
+
+/* The internal HPIB device is special; this is its physaddr; its select code is 7.
+ * The reason why we have to treat it specially is because apparently it's broken:
+ * the device ID isn't consistent/reliable. *sigh*
+ */
+#define DIO_IHPIBADDR 0x47800
+#define DIO_IHPIBSCODE 7
+
+/* If we don't have the internal HPIB defined, then treat select code 7 like
+ * any other. If we *do* have internal HPIB, then we just have to assume that
+ * select code 7 is the internal HPIB regardless of the ID register :-<
+ */
+#define CONFIG_IHPIB /* hack hack : not yet a proper config option */
+#ifdef CONFIG_IHPIB
+#define DIO_ISIHPIB(scode) ((scode) == DIO_IHPIBSCODE)
+#else
+#define DIO_ISIHPIB(scode) 0
+#endif
+
+#define DIO_VIRADDRBASE 0xf0000000 /* vir addr where IOspace is mapped */
+
+#define DIO_BASE 0x600000 /* start of DIO space */
+#define DIO_END 0x1000000 /* end of DIO space */
+#define DIO_DEVSIZE 0x10000 /* size of a DIO device */
+
+#define DIOII_BASE 0x01000000 /* start of DIO-II space */
+#define DIOII_END 0x20000000 /* end of DIO-II space */
+#define DIOII_DEVSIZE 0x00400000 /* size of a DIO-II device */
+
+/* Highest valid select code. If we add DIO-II support this should become
+ * 256 for everything except HP320, which only has DIO.
+ */
+#define DIO_SCMAX 32
+#define DIOII_SCBASE 132 /* lowest DIO-II select code */
+#define DIO_SCINHOLE(scode) (((scode) >= 32) && ((scode) < DIOII_SCBASE))
+
+/* macros to read device IDs, given base address */
+#define DIO_ID(baseaddr) readb((baseaddr) + DIO_IDOFF)
+#define DIO_SECID(baseaddr) readb((baseaddr) + DIO_SECIDOFF)
+
+/* extract the interrupt level */
+#define DIO_IPL(baseaddr) (((readb((baseaddr) + DIO_IPLOFF) >> 4) & 0x03) + 3)
+
+/* find the size of a DIO-II board's address space.
+ * DIO boards are all fixed length.
+ */
+#define DIOII_SIZE(baseaddr) ((readb((baseaddr) + DIOII_SIZEOFF) + 1) * 0x100000)
+
+/* general purpose macro for both DIO and DIO-II */
+#define DIO_SIZE(scode, base) (DIO_ISDIOII((scode)) ? DIOII_SIZE((base)) : DIO_DEVSIZE)
+
+/* The hardware has primary and secondary IDs; we encode these in a single
+ * int as PRIMARY ID & (SECONDARY ID << 8).
+ * In practice this is only important for framebuffers,
+ * and everybody else just sets ID fields equal to the DIO_ID_FOO value.
+ */
+#define DIO_ENCODE_ID(pr,sec) ((((int)sec & 0xff) << 8) & ((int)pr & 0xff))
+/* macro to determine whether a given primary ID requires a secondary ID byte */
+#define DIO_NEEDSSECID(id) ((id) == DIO_ID_FBUFFER)
+
+/* Now a whole slew of macros giving device IDs and descriptive strings: */
+#define DIO_ID_DCA0 0x02 /* 98644A serial */
+#define DIO_DESC_DCA0 "98644A DCA0 serial"
+#define DIO_ID_DCA0REM 0x82 /* 98644A serial */
+#define DIO_DESC_DCA0REM "98644A DCA0REM serial"
+#define DIO_ID_DCA1 0x42 /* 98644A serial */
+#define DIO_DESC_DCA1 "98644A DCA1 serial"
+#define DIO_ID_DCA1REM 0xc2 /* 98644A serial */
+#define DIO_DESC_DCA1REM "98644A DCA1REM serial"
+#define DIO_ID_DCM 0x05 /* 98642A serial MUX */
+#define DIO_DESC_DCM "98642A DCM serial MUX"
+#define DIO_ID_DCMREM 0x85 /* 98642A serial MUX */
+#define DIO_DESC_DCMREM "98642A DCMREM serial MUX"
+#define DIO_ID_LAN 0x15 /* 98643A LAN */
+#define DIO_DESC_LAN "98643A LAN"
+#define DIO_ID_FHPIB 0x08 /* 98625A/98625B fast HP-IB */
+#define DIO_DESC_FHPIB "98625A/98625B fast HPIB"
+#define DIO_ID_NHPIB 0x80 /* 98624A HP-IB (normal ie slow) */
+#define DIO_DESC_NHPIB "98624A HPIB"
+#define DIO_ID_IHPIB 0x00 /* internal HPIB (not its real ID, it hasn't got one! */
+#define DIO_DESC_IHPIB "internal HPIB"
+#define DIO_ID_SCSI0 0x07 /* 98625A SCSI */
+#define DIO_DESC_SCSI0 "98625A SCSI0"
+#define DIO_ID_SCSI1 0x27 /* ditto */
+#define DIO_DESC_SCSI1 "98625A SCSI1"
+#define DIO_ID_SCSI2 0x47 /* ditto */
+#define DIO_DESC_SCSI2 "98625A SCSI2"
+#define DIO_ID_SCSI3 0x67 /* ditto */
+#define DIO_DESC_SCSI3 "98625A SCSI3"
+#define DIO_ID_FBUFFER 0x39 /* framebuffer: flavour is distinguished by secondary ID */
+#define DIO_DESC_FBUFFER "bitmapped display"
+/* the NetBSD kernel source is a bit unsure as to what these next IDs actually do :-> */
+#define DIO_ID_MISC0 0x03 /* 98622A */
+#define DIO_DESC_MISC0 "98622A"
+#define DIO_ID_MISC1 0x04 /* 98623A */
+#define DIO_DESC_MISC1 "98623A"
+#define DIO_ID_PARALLEL 0x06 /* internal parallel */
+#define DIO_DESC_PARALLEL "internal parallel"
+#define DIO_ID_MISC2 0x09 /* 98287A keyboard */
+#define DIO_DESC_MISC2 "98287A keyboard"
+#define DIO_ID_MISC3 0x0a /* HP98635A FP accelerator */
+#define DIO_DESC_MISC3 "HP98635A FP accelerator"
+#define DIO_ID_MISC4 0x0b /* timer */
+#define DIO_DESC_MISC4 "timer"
+#define DIO_ID_MISC5 0x12 /* 98640A */
+#define DIO_DESC_MISC5 "98640A"
+#define DIO_ID_MISC6 0x16 /* 98659A */
+#define DIO_DESC_MISC6 "98659A"
+#define DIO_ID_MISC7 0x19 /* 237 display */
+#define DIO_DESC_MISC7 "237 display"
+#define DIO_ID_MISC8 0x1a /* quad-wide card */
+#define DIO_DESC_MISC8 "quad-wide card"
+#define DIO_ID_MISC9 0x1b /* 98253A */
+#define DIO_DESC_MISC9 "98253A"
+#define DIO_ID_MISC10 0x1c /* 98627A */
+#define DIO_DESC_MISC10 "98253A"
+#define DIO_ID_MISC11 0x1d /* 98633A */
+#define DIO_DESC_MISC11 "98633A"
+#define DIO_ID_MISC12 0x1e /* 98259A */
+#define DIO_DESC_MISC12 "98259A"
+#define DIO_ID_MISC13 0x1f /* 8741 */
+#define DIO_DESC_MISC13 "8741"
+#define DIO_ID_VME 0x31 /* 98577A VME adapter */
+#define DIO_DESC_VME "98577A VME adapter"
+#define DIO_ID_DCL 0x34 /* 98628A serial */
+#define DIO_DESC_DCL "98628A DCL serial"
+#define DIO_ID_DCLREM 0xb4 /* 98628A serial */
+#define DIO_DESC_DCLREM "98628A DCLREM serial"
+/* These are the secondary IDs for the framebuffers */
+#define DIO_ID2_GATORBOX 0x01 /* 98700/98710 "gatorbox" */
+#define DIO_DESC2_GATORBOX "98700/98710 \"gatorbox\" display"
+#define DIO_ID2_TOPCAT 0x02 /* 98544/98545/98547 "topcat" */
+#define DIO_DESC2_TOPCAT "98544/98545/98547 \"topcat\" display"
+#define DIO_ID2_RENAISSANCE 0x04 /* 98720/98721 "renaissance" */
+#define DIO_DESC2_RENAISSANCE "98720/98721 \"renaissance\" display"
+#define DIO_ID2_LRCATSEYE 0x05 /* lowres "catseye" */
+#define DIO_DESC2_LRCATSEYE "low-res catseye display"
+#define DIO_ID2_HRCCATSEYE 0x06 /* highres colour "catseye" */
+#define DIO_DESC2_HRCCATSEYE "high-res color catseye display"
+#define DIO_ID2_HRMCATSEYE 0x07 /* highres mono "catseye" */
+#define DIO_DESC2_HRMCATSEYE "high-res mono catseye display"
+#define DIO_ID2_DAVINCI 0x08 /* 98730/98731 "davinci" */
+#define DIO_DESC2_DAVINCI "98730/98731 \"davinci\" display"
+#define DIO_ID2_XXXCATSEYE 0x09 /* "catseye" */
+#define DIO_DESC2_XXXCATSEYE "catseye display"
+#define DIO_ID2_HYPERION 0x0e /* A1096A "hyperion" */
+#define DIO_DESC2_HYPERION "A1096A \"hyperion\" display"
+#define DIO_ID2_XGENESIS 0x0b /* "x-genesis"; no NetBSD support */
+#define DIO_DESC2_XGENESIS "\"x-genesis\" display"
+#define DIO_ID2_TIGER 0x0c /* "tiger"; no NetBSD support */
+#define DIO_DESC2_TIGER "\"tiger\" display"
+#define DIO_ID2_YGENESIS 0x0d /* "y-genesis"; no NetBSD support */
+#define DIO_DESC2_YGENESIS "\"y-genesis\" display"
+/* if you add new IDs then you should tell dio.c about them so it can
+ * identify them...
+ */
+
+extern void dio_init(void);
+extern int dio_find(int deviceid);
+extern void *dio_scodetoviraddr(int scode);
+extern int dio_scodetoipl(int scode);
+extern void dio_config_board(int scode);
+extern void dio_unconfig_board(int scode);
+
+
+#endif /* __KERNEL__ */
+#endif /* ndef _LINUX_DIO_H */
diff --git a/pfinet/linux-src/include/linux/dirent.h b/pfinet/linux-src/include/linux/dirent.h
new file mode 100644
index 00000000..a18f7e46
--- /dev/null
+++ b/pfinet/linux-src/include/linux/dirent.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_DIRENT_H
+#define _LINUX_DIRENT_H
+
+struct dirent {
+ long d_ino;
+ __kernel_off_t d_off;
+ unsigned short d_reclen;
+ char d_name[256]; /* We must not include limits.h! */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/dlists.h b/pfinet/linux-src/include/linux/dlists.h
new file mode 100644
index 00000000..f92485e4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/dlists.h
@@ -0,0 +1,108 @@
+#ifndef DLISTS_H
+#define DLISTS_H
+/*
+ * include/linux/dlists.h - macros for double linked lists
+ *
+ * Copyright (C) 1997, Thomas Schoebel-Theuer,
+ * <schoebel@informatik.uni-stuttgart.de>.
+ */
+
+/* dlists are cyclic ringlists, so the last element cannot be tested
+ * for NULL. Use the following construct for traversing cyclic lists:
+ * ptr = anchor;
+ * if(ptr) do {
+ * ...
+ * ptr = ptr->{something}_{next,prev};
+ * } while(ptr != anchor);
+ * The effort here is paid off with much simpler inserts/removes.
+ * Examples for usage of these macros can be found in fs/ninode.c.
+ * To access the last element in constant time, simply use
+ * anchor->{something}_prev.
+ */
+
+#define DEF_GENERIC_INSERT(CHANGE,PREFIX,NAME,TYPE,NEXT,PREV) \
+static inline void PREFIX##NAME(TYPE ** anchor, TYPE * elem)\
+{\
+ TYPE * oldfirst = *anchor;\
+ if(!oldfirst) {\
+ elem->NEXT = elem->PREV = *anchor = elem;\
+ } else {\
+ elem->PREV = oldfirst->PREV;\
+ elem->NEXT = oldfirst;\
+ oldfirst->PREV->NEXT = elem;\
+ oldfirst->PREV = elem;\
+ if(CHANGE)\
+ *anchor = elem;\
+ }\
+}
+
+/* insert_* is always at the first position */
+#define DEF_INSERT(NAME,TYPE,NEXT,PREV) \
+ DEF_GENERIC_INSERT(1,insert_,NAME,TYPE,NEXT,PREV)
+
+/* append_* is always at the tail */
+#define DEF_APPEND(NAME,TYPE,NEXT,PREV) \
+ DEF_GENERIC_INSERT(0,append_,NAME,TYPE,NEXT,PREV)
+
+/* use this to insert _before_ oldelem somewhere in the middle of the list.
+ * the list must not be empty, and oldelem must be already a member.*/
+#define DEF_INSERT_MIDDLE(NAME,TYPE) \
+static inline void insert_middle_##NAME(TYPE ** anchor, TYPE * oldelem, TYPE * elem)\
+{\
+ int status = (oldelem == *anchor);\
+ insert_##NAME(&oldelem, elem);\
+ if(status)\
+ *anchor = oldelem;\
+}
+
+/* remove can be done with any element in the list */
+#define DEF_REMOVE(NAME,TYPE,NEXT,PREV) \
+static inline void remove_##NAME(TYPE ** anchor, TYPE * elem)\
+{\
+ TYPE * next = elem->NEXT;\
+ if(next == elem) {\
+ *anchor = NULL;\
+ } else {\
+ TYPE * prev = elem->PREV;\
+ prev->NEXT = next;\
+ next->PREV = prev;\
+ elem->NEXT = elem->PREV = NULL;/*leave this during debugging*/\
+ if(*anchor == elem)\
+ *anchor = next;\
+ }\
+}
+
+
+/* According to ideas from David S. Miller, here is a slightly
+ * more efficient plug-in compatible version using non-cyclic lists,
+ * but allowing neither backward traversals nor constant time access
+ * to the last element.
+ * Note that although the interface is the same, the PPREV pointer must be
+ * declared doubly indirect and the test for end-of-list is different. */
+
+/* as above, this inserts always at the head */
+#define DEF_LIN_INSERT(NAME,TYPE,NEXT,PPREV) \
+static inline void insert_##NAME(TYPE ** anchor, TYPE * elem)\
+{\
+ TYPE * first;\
+ if((elem->NEXT = first = *anchor))\
+ first->PPREV = &elem->NEXT;\
+ *anchor = elem;\
+ elem->PPREV = anchor;\
+}
+
+/* as above, this works with any list element */
+#define DEF_LIN_REMOVE(NAME,TYPE,NEXT,PPREV) \
+static inline void remove_##NAME(TYPE ** anchor, TYPE * elem)\
+{\
+ TYPE * pprev;\
+ if((pprev = elem->PPREV)) {\
+ TYPE * next;\
+ if((next = elem->NEXT))\
+ next->PPREV = pprev;\
+ *pprev = next;\
+ elem->PPREV = elem->NEXT = NULL; /*leave this for debugging*/\
+ }\
+}
+
+#endif
diff --git a/pfinet/linux-src/include/linux/dmascc.h b/pfinet/linux-src/include/linux/dmascc.h
new file mode 100644
index 00000000..01b46df7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/dmascc.h
@@ -0,0 +1,43 @@
+/*
+ * $Id: dmascc.h,v 1.1 1997/12/01 10:44:55 oe1kib Exp $
+ *
+ * Driver for high-speed SCC boards (those with DMA support)
+ * Copyright (C) 1997 Klaus Kudielka
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Ioctls */
+#define SIOCGSCCPARAM SIOCDEVPRIVATE
+#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1)
+
+/* Frequency of timer 0 */
+#define TMR_0_HZ 25600
+
+/* Configurable parameters */
+struct scc_param {
+ int pclk_hz; /* frequency of BRG input (read-only - don't change) */
+ int brg_tc; /* baud rate generator terminal count - BRG disabled if < 0 */
+ int nrzi; /* 0 (nrz), 1 (nrzi) */
+ int clocks; /* see documentation */
+ int txdelay; /* [1/TMR_0_HZ] */
+ int txtime; /* [1/HZ] */
+ int sqdelay; /* [1/TMR_0_HZ] */
+ int waittime; /* [1/TMR_0_HZ] */
+ int slottime; /* [1/TMR_0_HZ] */
+ int persist; /* 0 ... 255 */
+ int dma; /* 1, 3 */
+};
+
diff --git a/pfinet/linux-src/include/linux/dtlk.h b/pfinet/linux-src/include/linux/dtlk.h
new file mode 100644
index 00000000..07a6b82b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/dtlk.h
@@ -0,0 +1,104 @@
+#if 0
+
+#define TRACE_TXT(text) \
+ { \
+ if(dtlk_trace) \
+ { \
+ console_print(text); \
+ console_print("\n"); \
+ } \
+ }
+
+#define TRACE_CHR(chr) \
+ { \
+ if(dtlk_trace) \
+ console_print(chr); \
+ } \
+
+#endif
+
+#define DTLK_MINOR 0
+#define DTLK_IO_EXTENT 0x02
+
+ /* ioctl's use magic number of 0xa3 */
+#define DTLK_INTERROGATE 0xa390 /* get settings from the DoubleTalk */
+#define DTLK_STATUS 0xa391 /* get status from the DoubleTalk */
+
+
+#define DTLK_CLEAR 0x18 /* stops speech */
+
+#define DTLK_MAX_RETRIES (loops_per_sec/10000)
+
+ /* TTS Port Status Flags */
+#define TTS_READABLE 0x80 /* mask for bit which is nonzero if a
+ byte can be read from the TTS port */
+#define TTS_SPEAKING 0x40 /* mask for SYNC bit, which is nonzero
+ while DoubleTalk is producing
+ output with TTS, PCM or CVSD
+ synthesizers or tone generators
+ (that is, all but LPC) */
+#define TTS_SPEAKING2 0x20 /* mask for SYNC2 bit,
+ which falls to zero up to 0.4 sec
+ before speech stops */
+#define TTS_WRITABLE 0x10 /* mask for RDY bit, which when set to
+ 1, indicates the TTS port is ready
+ to accept a byte of data. The RDY
+ bit goes zero 2-3 usec after
+ writing, and goes 1 again 180-190
+ usec later. */
+#define TTS_ALMOST_FULL 0x08 /* mask for AF bit: When set to 1,
+ indicates that less than 300 free
+ bytes are available in the TTS
+ input buffer. AF is always 0 in the
+ PCM, TGN and CVSD modes. */
+#define TTS_ALMOST_EMPTY 0x04 /* mask for AE bit: When set to 1,
+ indicates that less than 300 bytes
+ of data remain in DoubleTalk's
+ input (TTS or PCM) buffer. AE is
+ always 1 in the TGN and CVSD
+ modes. */
+
+ /* LPC speak commands */
+#define LPC_5220_NORMAL 0x60 /* 5220 format decoding table, normal rate */
+#define LPC_5220_FAST 0x64 /* 5220 format decoding table, fast rate */
+#define LPC_D6_NORMAL 0x20 /* D6 format decoding table, normal rate */
+#define LPC_D6_FAST 0x24 /* D6 format decoding table, fast rate */
+
+ /* LPC Port Status Flags (valid only after one of the LPC
+ speak commands) */
+#define LPC_SPEAKING 0x80 /* mask for TS bit: When set to 1,
+ indicates the LPC synthesizer is
+ producing speech.*/
+#define LPC_BUFFER_LOW 0x40 /* mask for BL bit: When set to 1,
+ indicates that the hardware LPC
+ data buffer has less than 30 bytes
+ remaining. (Total internal buffer
+ size = 4096 bytes.) */
+#define LPC_BUFFER_EMPTY 0x20 /* mask for BE bit: When set to 1,
+ indicates that the LPC data buffer
+ ran out of data (error condition if
+ TS is also 1). */
+
+ /* data returned by Interrogate command */
+struct dtlk_settings
+{
+ unsigned short serial_number; /* 0-7Fh:0-7Fh */
+ unsigned char rom_version[24]; /* null terminated string */
+ unsigned char mode; /* 0=Character; 1=Phoneme; 2=Text */
+ unsigned char punc_level; /* nB; 0-7 */
+ unsigned char formant_freq; /* nF; 0-9 */
+ unsigned char pitch; /* nP; 0-99 */
+ unsigned char speed; /* nS; 0-9 */
+ unsigned char volume; /* nV; 0-9 */
+ unsigned char tone; /* nX; 0-2 */
+ unsigned char expression; /* nE; 0-9 */
+ unsigned char ext_dict_loaded; /* 1=exception dictionary loaded */
+ unsigned char ext_dict_status; /* 1=exception dictionary enabled */
+ unsigned char free_ram; /* # pages (truncated) remaining for
+ text buffer */
+ unsigned char articulation; /* nA; 0-9 */
+ unsigned char reverb; /* nR; 0-9 */
+ unsigned char eob; /* 7Fh value indicating end of
+ parameter block */
+ unsigned char has_indexing; /* nonzero if indexing is implemented */
+};
diff --git a/pfinet/linux-src/include/linux/efs_dir.h b/pfinet/linux-src/include/linux/efs_dir.h
new file mode 100644
index 00000000..33152413
--- /dev/null
+++ b/pfinet/linux-src/include/linux/efs_dir.h
@@ -0,0 +1,42 @@
+/*
+ * efs_dir.h
+ *
+ * Copyright (c) 1999 Al Smith
+ */
+
+#ifndef __EFS_DIR_H__
+#define __EFS_DIR_H__
+
+#define EFS_DIRBSIZE_BITS EFS_BLOCKSIZE_BITS
+#define EFS_DIRBSIZE (1 << EFS_DIRBSIZE_BITS)
+
+struct efs_dentry {
+ unsigned int inode;
+ unsigned char namelen;
+ char name[3];
+};
+
+#define EFS_DENTSIZE (sizeof(struct efs_dentry) - 3 + 1)
+#define EFS_MAXNAMELEN ((1 << (sizeof(char) * 8)) - 1)
+
+#define EFS_DIRBLK_HEADERSIZE 4
+#define EFS_DIRBLK_MAGIC 0xbeef /* moo */
+
+struct efs_dir {
+ unsigned short magic;
+ unsigned char firstused;
+ unsigned char slots;
+
+ unsigned char space[EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE];
+};
+
+#define EFS_MAXENTS \
+ ((EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE) / \
+ (EFS_DENTSIZE + sizeof(char)))
+
+#define EFS_SLOTAT(dir, slot) EFS_REALOFF((dir)->space[slot])
+
+#define EFS_REALOFF(offset) ((offset << 1))
+
+#endif /* __EFS_DIR_H__ */
+
diff --git a/pfinet/linux-src/include/linux/efs_fs.h b/pfinet/linux-src/include/linux/efs_fs.h
new file mode 100644
index 00000000..1e5fd23c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/efs_fs.h
@@ -0,0 +1,67 @@
+/*
+ * efs_fs.h
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
+ */
+
+#ifndef __EFS_FS_H__
+#define __EFS_FS_H__
+
+#define EFS_VERSION "1.0b"
+
+static const char cprt[] = "EFS: "EFS_VERSION" - (c) 1999 Al Smith <Al.Smith@aeschi.ch.eu.org>";
+
+#include <asm/uaccess.h>
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#if LINUX_VERSION_CODE < 0x20200
+#error This code is only for linux-2.2 and later.
+#endif
+
+/* 1 block is 512 bytes */
+#define EFS_BLOCKSIZE_BITS 9
+#define EFS_BLOCKSIZE (1 << EFS_BLOCKSIZE_BITS)
+
+#include <linux/efs_fs_i.h>
+#include <linux/efs_dir.h>
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifdef _EFS_USE_GENERIC
+#define INODE_INFO(i) (struct efs_inode_info *) &((i)->u.generic_ip)
+#define SUPER_INFO(s) (struct efs_sb_info *) &((s)->u.generic_sbp)
+#else
+#define INODE_INFO(i) &((i)->u.efs_i)
+#define SUPER_INFO(s) &((s)->u.efs_sb)
+#endif
+
+extern struct inode_operations efs_dir_inode_operations;
+extern struct inode_operations efs_file_inode_operations;
+extern struct inode_operations efs_symlink_inode_operations;
+
+extern int init_module(void);
+extern void cleanup_module(void);
+extern struct super_block *efs_read_super(struct super_block *, void *, int);
+extern void efs_put_super(struct super_block *);
+extern int efs_statfs(struct super_block *, struct statfs *, int);
+
+extern void efs_read_inode(struct inode *);
+extern efs_block_t efs_map_block(struct inode *, efs_block_t);
+
+extern struct dentry *efs_lookup(struct inode *, struct dentry *);
+extern int efs_bmap(struct inode *, int);
+
+extern int init_efs_fs(void);
+
+#endif /* __EFS_FS_H__ */
+
diff --git a/pfinet/linux-src/include/linux/efs_fs_i.h b/pfinet/linux-src/include/linux/efs_fs_i.h
new file mode 100644
index 00000000..453d706c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/efs_fs_i.h
@@ -0,0 +1,68 @@
+/*
+ * efs_fs_i.h
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from IRIX header files (c) 1988 Silicon Graphics
+ */
+
+#ifndef __EFS_FS_I_H__
+#define __EFS_FS_I_H__
+
+typedef int32_t efs_block_t;
+typedef uint32_t efs_ino_t;
+
+#define EFS_DIRECTEXTENTS 12
+
+/*
+ * layout of an extent, in memory and on disk. 8 bytes exactly.
+ */
+typedef union extent_u {
+ unsigned char raw[8];
+ struct extent_s {
+ unsigned int ex_magic:8; /* magic # (zero) */
+ unsigned int ex_bn:24; /* basic block */
+ unsigned int ex_length:8; /* numblocks in this extent */
+ unsigned int ex_offset:24; /* logical offset into file */
+ } cooked;
+} efs_extent;
+
+typedef struct edevs {
+ short odev;
+ short dev_filler; /* force ndev to start */
+ unsigned int ndev; /* on a 32-bit boundary */
+} efs_devs;
+
+/*
+ * extent based filesystem inode as it appears on disk. The efs inode
+ * is exactly 128 bytes long.
+ */
+struct efs_dinode {
+ u_short di_mode; /* mode and type of file */
+ short di_nlink; /* number of links to file */
+ u_short di_uid; /* owner's user id */
+ u_short di_gid; /* owner's group id */
+ int32_t di_size; /* number of bytes in file */
+ int32_t di_atime; /* time last accessed */
+ int32_t di_mtime; /* time last modified */
+ int32_t di_ctime; /* time created */
+ uint32_t di_gen; /* generation number */
+ short di_numextents; /* # of extents */
+ u_char di_version; /* version of inode */
+ u_char di_spare; /* spare - used by AFS */
+ union di_addr {
+ efs_extent di_extents[EFS_DIRECTEXTENTS];
+ efs_devs di_dev; /* device for IFCHR/IFBLK */
+ } di_u;
+};
+
+/* efs inode storage in memory */
+struct efs_inode_info {
+ int numextents;
+ int lastextent;
+
+ efs_extent extents[EFS_DIRECTEXTENTS];
+};
+
+#endif /* __EFS_FS_I_H__ */
+
diff --git a/pfinet/linux-src/include/linux/efs_fs_sb.h b/pfinet/linux-src/include/linux/efs_fs_sb.h
new file mode 100644
index 00000000..95476663
--- /dev/null
+++ b/pfinet/linux-src/include/linux/efs_fs_sb.h
@@ -0,0 +1,63 @@
+/*
+ * efs_fs_sb.h
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from IRIX header files (c) 1988 Silicon Graphics
+ */
+
+#ifndef __EFS_FS_SB_H__
+#define __EFS_FS_SB_H__
+
+/* statfs() magic number for EFS */
+#define EFS_SUPER_MAGIC 0x414A53
+
+/* EFS superblock magic numbers */
+#define EFS_MAGIC 0x072959
+#define EFS_NEWMAGIC 0x07295a
+
+#define IS_EFS_MAGIC(x) ((x == EFS_MAGIC) || (x == EFS_NEWMAGIC))
+
+#define EFS_SUPER 1
+#define EFS_ROOTINODE 2
+
+/* efs superblock on disk */
+struct efs_super {
+ int32_t fs_size; /* size of filesystem, in sectors */
+ int32_t fs_firstcg; /* bb offset to first cg */
+ int32_t fs_cgfsize; /* size of cylinder group in bb's */
+ short fs_cgisize; /* bb's of inodes per cylinder group */
+ short fs_sectors; /* sectors per track */
+ short fs_heads; /* heads per cylinder */
+ short fs_ncg; /* # of cylinder groups in filesystem */
+ short fs_dirty; /* fs needs to be fsck'd */
+ short fs_filler; /* force fs_time to start 2bytes later*/
+ int32_t fs_time; /* last super-block update */
+ int32_t fs_magic; /* magic number */
+ char fs_fname[6]; /* file system name */
+ char fs_fpack[6]; /* file system pack name */
+ int32_t fs_bmsize; /* size of bitmap in bytes */
+ int32_t fs_tfree; /* total free data blocks */
+ int32_t fs_tinode; /* total free inodes */
+ int32_t fs_bmblock; /* bitmap location. */
+ int32_t fs_replsb; /* Location of replicated superblock. */
+ int32_t fs_lastialloc; /* last allocated inode */
+ char fs_spare[20]; /* space for expansion - MUST BE ZERO */
+ int32_t fs_checksum; /* checksum of volume portion of fs */
+};
+
+/* efs superblock information in memory */
+struct efs_sb_info {
+ int32_t fs_magic; /* superblock magic number */
+ int32_t fs_start; /* first block of filesystem */
+ int32_t first_block; /* first data block in filesystem */
+ int32_t total_blocks; /* total number of blocks in filesystem */
+ int32_t group_size; /* # of blocks a group consists of */
+ int32_t data_free; /* # of free data blocks */
+ int32_t inode_free; /* # of free inodes */
+ short inode_blocks; /* # of blocks used for inodes in every grp */
+ short total_groups; /* # of groups */
+};
+
+#endif /* __EFS_FS_SB_H__ */
+
diff --git a/pfinet/linux-src/include/linux/efs_vh.h b/pfinet/linux-src/include/linux/efs_vh.h
new file mode 100644
index 00000000..b9d7e4dd
--- /dev/null
+++ b/pfinet/linux-src/include/linux/efs_vh.h
@@ -0,0 +1,70 @@
+/*
+ * efs_vh.h
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from IRIX header files (c) 1985 MIPS Computer Systems, Inc.
+ */
+
+#ifndef __EFS_VH_H__
+#define __EFS_VH_H__
+
+#define VHMAGIC 0xbe5a941 /* volume header magic number */
+#define NPARTAB 16 /* 16 unix partitions */
+#define NVDIR 15 /* max of 15 directory entries */
+#define BFNAMESIZE 16 /* max 16 chars in boot file name */
+#define VDNAMESIZE 8
+
+struct volume_directory {
+ char vd_name[VDNAMESIZE]; /* name */
+ int vd_lbn; /* logical block number */
+ int vd_nbytes; /* file length in bytes */
+};
+
+struct partition_table { /* one per logical partition */
+ int pt_nblks; /* # of logical blks in partition */
+ int pt_firstlbn; /* first lbn of partition */
+ int pt_type; /* use of partition */
+};
+
+struct volume_header {
+ int vh_magic; /* identifies volume header */
+ short vh_rootpt; /* root partition number */
+ short vh_swappt; /* swap partition number */
+ char vh_bootfile[BFNAMESIZE]; /* name of file to boot */
+ char pad[48]; /* device param space */
+ struct volume_directory vh_vd[NVDIR]; /* other vol hdr contents */
+ struct partition_table vh_pt[NPARTAB]; /* device partition layout */
+ int vh_csum; /* volume header checksum */
+ int vh_fill; /* fill out to 512 bytes */
+};
+
+/* partition type sysv is used for EFS format CD-ROM partitions */
+#define SGI_SYSV 0x05
+#define SGI_EFS 0x07
+#define IS_EFS(x) (((x) == SGI_EFS) || ((x) == SGI_SYSV))
+
+struct pt_types {
+ int pt_type;
+ char *pt_name;
+} sgi_pt_types[] = {
+ {0x00, "SGI vh"},
+ {0x01, "SGI trkrepl"},
+ {0x02, "SGI secrepl"},
+ {0x03, "SGI raw"},
+ {0x04, "SGI bsd"},
+ {SGI_SYSV, "SGI sysv"},
+ {0x06, "SGI vol"},
+ {SGI_EFS, "SGI efs"},
+ {0x08, "SGI lv"},
+ {0x09, "SGI rlv"},
+ {0x0A, "SGI xfs"},
+ {0x0B, "SGI xfslog"},
+ {0x0C, "SGI xlv"},
+ {0x82, "Linux swap"},
+ {0x83, "Linux native"},
+ {0, NULL}
+};
+
+#endif /* __EFS_VH_H__ */
+
diff --git a/pfinet/linux-src/include/linux/elf.h b/pfinet/linux-src/include/linux/elf.h
new file mode 100644
index 00000000..8e88496a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/elf.h
@@ -0,0 +1,597 @@
+#ifndef _LINUX_ELF_H
+#define _LINUX_ELF_H
+
+#include <linux/types.h>
+#include <asm/elf.h>
+
+/* 32-bit ELF base types. */
+typedef __u32 Elf32_Addr;
+typedef __u16 Elf32_Half;
+typedef __u32 Elf32_Off;
+typedef __s32 Elf32_Sword;
+typedef __u32 Elf32_Word;
+
+/* 64-bit ELF base types. */
+typedef __u64 Elf64_Addr;
+typedef __u16 Elf64_Half;
+typedef __s16 Elf64_SHalf;
+typedef __u64 Elf64_Off;
+typedef __s64 Elf64_Sword;
+typedef __u64 Elf64_Word;
+
+/* These constants are for the segment types stored in the image headers */
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+#define PT_LOPROC 0x70000000
+#define PT_HIPROC 0x7fffffff
+#define PT_MIPS_REGINFO 0x70000000
+
+/* Flags in the e_flags field of the header */
+#define EF_MIPS_NOREORDER 0x00000001
+#define EF_MIPS_PIC 0x00000002
+#define EF_MIPS_CPIC 0x00000004
+#define EF_MIPS_ARCH 0xf0000000
+
+/* These constants define the different elf file types */
+#define ET_NONE 0
+#define ET_REL 1
+#define ET_EXEC 2
+#define ET_DYN 3
+#define ET_CORE 4
+#define ET_LOPROC 0xff00
+#define ET_HIPROC 0xffff
+
+/* These constants define the various ELF target machines */
+#define EM_NONE 0
+#define EM_M32 1
+#define EM_SPARC 2
+#define EM_386 3
+#define EM_68K 4
+#define EM_88K 5
+#define EM_486 6 /* Perhaps disused */
+#define EM_860 7
+
+#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */
+
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */
+
+#define EM_PARISC 15 /* HPPA */
+
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+
+#define EM_PPC 20 /* PowerPC */
+
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+
+/*
+ * This is an interim value that we will use until the committee comes
+ * up with a final number.
+ */
+#define EM_ALPHA 0x9026
+
+
+/* This is the info that is needed to parse the dynamic section of the file */
+#define DT_NULL 0
+#define DT_NEEDED 1
+#define DT_PLTRELSZ 2
+#define DT_PLTGOT 3
+#define DT_HASH 4
+#define DT_STRTAB 5
+#define DT_SYMTAB 6
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_STRSZ 10
+#define DT_SYMENT 11
+#define DT_INIT 12
+#define DT_FINI 13
+#define DT_SONAME 14
+#define DT_RPATH 15
+#define DT_SYMBOLIC 16
+#define DT_REL 17
+#define DT_RELSZ 18
+#define DT_RELENT 19
+#define DT_PLTREL 20
+#define DT_DEBUG 21
+#define DT_TEXTREL 22
+#define DT_JMPREL 23
+#define DT_LOPROC 0x70000000
+#define DT_HIPROC 0x7fffffff
+#define DT_MIPS_RLD_VERSION 0x70000001
+#define DT_MIPS_TIME_STAMP 0x70000002
+#define DT_MIPS_ICHECKSUM 0x70000003
+#define DT_MIPS_IVERSION 0x70000004
+#define DT_MIPS_FLAGS 0x70000005
+ #define RHF_NONE 0
+ #define RHF_HARDWAY 1
+ #define RHF_NOTPOT 2
+#define DT_MIPS_BASE_ADDRESS 0x70000006
+#define DT_MIPS_CONFLICT 0x70000008
+#define DT_MIPS_LIBLIST 0x70000009
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a
+#define DT_MIPS_CONFLICTNO 0x7000000b
+#define DT_MIPS_LIBLISTNO 0x70000010
+#define DT_MIPS_SYMTABNO 0x70000011
+#define DT_MIPS_UNREFEXTNO 0x70000012
+#define DT_MIPS_GOTSYM 0x70000013
+#define DT_MIPS_HIPAGENO 0x70000014
+#define DT_MIPS_RLD_MAP 0x70000016
+
+/* This info is needed when parsing the symbol table */
+#define STB_LOCAL 0
+#define STB_GLOBAL 1
+#define STB_WEAK 2
+
+#define STT_NOTYPE 0
+#define STT_OBJECT 1
+#define STT_FUNC 2
+#define STT_SECTION 3
+#define STT_FILE 4
+
+#define ELF32_ST_BIND(x) ((x) >> 4)
+#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
+
+/* Symbolic values for the entries in the auxiliary table
+ put on the initial stack */
+#define AT_NULL 0 /* end of vector */
+#define AT_IGNORE 1 /* entry should be ignored */
+#define AT_EXECFD 2 /* file descriptor of program */
+#define AT_PHDR 3 /* program headers for program */
+#define AT_PHENT 4 /* size of program header entry */
+#define AT_PHNUM 5 /* number of program headers */
+#define AT_PAGESZ 6 /* system page size */
+#define AT_BASE 7 /* base address of interpreter */
+#define AT_FLAGS 8 /* flags */
+#define AT_ENTRY 9 /* entry point of program */
+#define AT_NOTELF 10 /* program is not ELF */
+#define AT_UID 11 /* real uid */
+#define AT_EUID 12 /* effective uid */
+#define AT_GID 13 /* real gid */
+#define AT_EGID 14 /* effective gid */
+#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
+#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
+
+typedef struct dynamic{
+ Elf32_Sword d_tag;
+ union{
+ Elf32_Sword d_val;
+ Elf32_Addr d_ptr;
+ } d_un;
+} Elf32_Dyn;
+
+typedef struct {
+ Elf64_Word d_tag; /* entry tag value */
+ union {
+ Elf64_Word d_val;
+ Elf64_Word d_ptr;
+ } d_un;
+} Elf64_Dyn;
+
+/* The following are used with relocations */
+#define ELF32_R_SYM(x) ((x) >> 8)
+#define ELF32_R_TYPE(x) ((x) & 0xff)
+
+#define R_386_NONE 0
+#define R_386_32 1
+#define R_386_PC32 2
+#define R_386_GOT32 3
+#define R_386_PLT32 4
+#define R_386_COPY 5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF 9
+#define R_386_GOTPC 10
+#define R_386_NUM 11
+
+#define R_MIPS_NONE 0
+#define R_MIPS_16 1
+#define R_MIPS_32 2
+#define R_MIPS_REL32 3
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5
+#define R_MIPS_LO16 6
+#define R_MIPS_GPREL16 7
+#define R_MIPS_LITERAL 8
+#define R_MIPS_GOT16 9
+#define R_MIPS_PC16 10
+#define R_MIPS_CALL16 11
+#define R_MIPS_GPREL32 12
+/* The remaining relocs are defined on Irix, although they are not
+ in the MIPS ELF ABI. */
+#define R_MIPS_UNUSED1 13
+#define R_MIPS_UNUSED2 14
+#define R_MIPS_UNUSED3 15
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+/*
+ * The following two relocation types are specified in the the MIPS ABI
+ * conformance guide version 1.2 but not yet in the psABI.
+ */
+#define R_MIPS_GOTHI16 22
+#define R_MIPS_GOTLO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+/*
+ * The following two relocation types are specified in the the MIPS ABI
+ * conformance guide version 1.2 but not yet in the psABI.
+ */
+#define R_MIPS_CALLHI16 30
+#define R_MIPS_CALLLO16 31
+/*
+ * This range is reserved for vendor specific relocations.
+ */
+#define R_MIPS_LOVENDOR 100
+#define R_MIPS_HIVENDOR 127
+
+
+/*
+ * Sparc ELF relocation types
+ */
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+
+/* Bits present in AT_HWCAP, primarily for Sparc32. */
+
+#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */
+#define HWCAP_SPARC_STBAR 2
+#define HWCAP_SPARC_SWAP 4
+#define HWCAP_SPARC_MULDIV 8
+#define HWCAP_SPARC_V9 16
+
+
+/*
+ * 68k ELF relocation types
+ */
+#define R_68K_NONE 0
+#define R_68K_32 1
+#define R_68K_16 2
+#define R_68K_8 3
+#define R_68K_PC32 4
+#define R_68K_PC16 5
+#define R_68K_PC8 6
+#define R_68K_GOT32 7
+#define R_68K_GOT16 8
+#define R_68K_GOT8 9
+#define R_68K_GOT32O 10
+#define R_68K_GOT16O 11
+#define R_68K_GOT8O 12
+#define R_68K_PLT32 13
+#define R_68K_PLT16 14
+#define R_68K_PLT8 15
+#define R_68K_PLT32O 16
+#define R_68K_PLT16O 17
+#define R_68K_PLT8O 18
+#define R_68K_COPY 19
+#define R_68K_GLOB_DAT 20
+#define R_68K_JMP_SLOT 21
+#define R_68K_RELATIVE 22
+
+/*
+ * Alpha ELF relocation types
+ */
+#define R_ALPHA_NONE 0 /* No reloc */
+#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
+#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
+#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
+#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
+#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
+#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
+#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
+#define R_ALPHA_OP_PUSH 12 /* OP stack push */
+#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */
+#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */
+#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */
+#define R_ALPHA_GPVALUE 16
+#define R_ALPHA_GPRELHIGH 17
+#define R_ALPHA_GPRELLOW 18
+#define R_ALPHA_IMMED_GP_16 19
+#define R_ALPHA_IMMED_GP_HI32 20
+#define R_ALPHA_IMMED_SCN_HI32 21
+#define R_ALPHA_IMMED_BR_HI32 22
+#define R_ALPHA_IMMED_LO32 23
+#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
+#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
+
+/* Legal values for e_flags field of Elf64_Ehdr. */
+
+#define EF_ALPHA_32BIT 1 /* All addresses are below 2GB */
+
+
+typedef struct elf32_rel {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+} Elf32_Rel;
+
+typedef struct elf64_rel {
+ Elf64_Addr r_offset; /* Location at which to apply the action */
+ Elf64_Word r_info; /* index and type of relocation */
+} Elf64_Rel;
+
+typedef struct elf32_rela{
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+typedef struct elf64_rela {
+ Elf64_Addr r_offset; /* Location at which to apply the action */
+ Elf64_Word r_info; /* index and type of relocation */
+ Elf64_Word r_addend; /* Constant addend used to compute value */
+} Elf64_Rela;
+
+typedef struct elf32_sym{
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf32_Half st_shndx;
+} Elf32_Sym;
+
+typedef struct elf64_sym {
+ Elf32_Word st_name; /* Symbol name, index in string tbl (yes, Elf32) */
+ unsigned char st_info; /* Type and binding attributes */
+ unsigned char st_other; /* No defined meaning, 0 */
+ Elf64_Half st_shndx; /* Associated section index */
+ Elf64_Addr st_value; /* Value of the symbol */
+ Elf64_Word st_size; /* Associated symbol size */
+} Elf64_Sym;
+
+
+#define EI_NIDENT 16
+
+typedef struct elf32_hdr{
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry; /* Entry point */
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+typedef struct elf64_hdr {
+ unsigned char e_ident[16]; /* ELF "magic number" */
+ Elf64_SHalf e_type;
+ Elf64_Half e_machine;
+ __s32 e_version;
+ Elf64_Addr e_entry; /* Entry point virtual address */
+ Elf64_Off e_phoff; /* Program header table file offset */
+ Elf64_Off e_shoff; /* Section header table file offset */
+ __s32 e_flags;
+ Elf64_SHalf e_ehsize;
+ Elf64_SHalf e_phentsize;
+ Elf64_SHalf e_phnum;
+ Elf64_SHalf e_shentsize;
+ Elf64_SHalf e_shnum;
+ Elf64_SHalf e_shstrndx;
+} Elf64_Ehdr;
+
+/* These constants define the permissions on sections in the program
+ header, p_flags. */
+#define PF_R 0x4
+#define PF_W 0x2
+#define PF_X 0x1
+
+typedef struct elf32_phdr{
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct elf64_phdr {
+ __s32 p_type;
+ __s32 p_flags;
+ Elf64_Off p_offset; /* Segment file offset */
+ Elf64_Addr p_vaddr; /* Segment virtual address */
+ Elf64_Addr p_paddr; /* Segment physical address */
+ Elf64_Word p_filesz; /* Segment size in file */
+ Elf64_Word p_memsz; /* Segment size in memory */
+ Elf64_Word p_align; /* Segment alignment, file & memory */
+} Elf64_Phdr;
+
+/* sh_type */
+#define SHT_NULL 0
+#define SHT_PROGBITS 1
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_RELA 4
+#define SHT_HASH 5
+#define SHT_DYNAMIC 6
+#define SHT_NOTE 7
+#define SHT_NOBITS 8
+#define SHT_REL 9
+#define SHT_SHLIB 10
+#define SHT_DYNSYM 11
+#define SHT_NUM 12
+#define SHT_LOPROC 0x70000000
+#define SHT_HIPROC 0x7fffffff
+#define SHT_LOUSER 0x80000000
+#define SHT_HIUSER 0xffffffff
+#define SHT_MIPS_LIST 0x70000000
+#define SHT_MIPS_CONFLICT 0x70000002
+#define SHT_MIPS_GPTAB 0x70000003
+#define SHT_MIPS_UCODE 0x70000004
+
+/* sh_flags */
+#define SHF_WRITE 0x1
+#define SHF_ALLOC 0x2
+#define SHF_EXECINSTR 0x4
+#define SHF_MASKPROC 0xf0000000
+#define SHF_MIPS_GPREL 0x10000000
+
+/* special section indexes */
+#define SHN_UNDEF 0
+#define SHN_LORESERVE 0xff00
+#define SHN_LOPROC 0xff00
+#define SHN_HIPROC 0xff1f
+#define SHN_ABS 0xfff1
+#define SHN_COMMON 0xfff2
+#define SHN_HIRESERVE 0xffff
+#define SHN_MIPS_ACCOMON 0xff00
+
+typedef struct {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+typedef struct elf64_shdr {
+ Elf32_Word sh_name; /* Section name, index in string tbl (yes Elf32) */
+ Elf32_Word sh_type; /* Type of section (yes Elf32) */
+ Elf64_Word sh_flags; /* Miscellaneous section attributes */
+ Elf64_Addr sh_addr; /* Section virtual addr at execution */
+ Elf64_Off sh_offset; /* Section file offset */
+ Elf64_Word sh_size; /* Size of section in bytes */
+ Elf32_Word sh_link; /* Index of another section (yes Elf32) */
+ Elf32_Word sh_info; /* Additional section information (yes Elf32) */
+ Elf64_Word sh_addralign; /* Section alignment */
+ Elf64_Word sh_entsize; /* Entry size if section holds table */
+} Elf64_Shdr;
+
+#define EI_MAG0 0 /* e_ident[] indexes */
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+#define EI_PAD 7
+
+#define ELFMAG0 0x7f /* EI_MAG */
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define ELFCLASSNONE 0 /* EI_CLASS */
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define ELFCLASSNUM 3
+
+#define ELFDATANONE 0 /* e_ident[EI_DATA] */
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#define EV_NONE 0 /* e_version, EI_VERSION */
+#define EV_CURRENT 1
+#define EV_NUM 2
+
+/* Notes used in ET_CORE */
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_PRPSINFO 3
+#define NT_TASKSTRUCT 4
+
+/* Note header in a PT_NOTE section */
+typedef struct elf32_note {
+ Elf32_Word n_namesz; /* Name size */
+ Elf32_Word n_descsz; /* Content size */
+ Elf32_Word n_type; /* Content type */
+} Elf32_Nhdr;
+
+/* Note header in a PT_NOTE section */
+/*
+ * For now we use the 32 bit version of the structure until we figure
+ * out whether we need anything better. Note - on the Alpha, "unsigned int"
+ * is only 32 bits.
+ */
+typedef struct elf64_note {
+ Elf32_Word n_namesz; /* Name size */
+ Elf32_Word n_descsz; /* Content size */
+ Elf32_Word n_type; /* Content type */
+} Elf64_Nhdr;
+
+#if ELF_CLASS == ELFCLASS32
+
+extern Elf32_Dyn _DYNAMIC [];
+#define elfhdr elf32_hdr
+#define elf_phdr elf32_phdr
+#define elf_note elf32_note
+
+#else
+
+extern Elf64_Dyn _DYNAMIC [];
+#define elfhdr elf64_hdr
+#define elf_phdr elf64_phdr
+#define elf_note elf64_note
+
+#endif
+
+
+#endif /* _LINUX_ELF_H */
diff --git a/pfinet/linux-src/include/linux/elfcore.h b/pfinet/linux-src/include/linux/elfcore.h
new file mode 100644
index 00000000..5c1cb05b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/elfcore.h
@@ -0,0 +1,88 @@
+#ifndef _LINUX_ELFCORE_H
+#define _LINUX_ELFCORE_H
+
+#include <linux/types.h>
+#include <linux/signal.h>
+#include <linux/time.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+
+struct elf_siginfo
+{
+ int si_signo; /* signal number */
+ int si_code; /* extra code */
+ int si_errno; /* errno */
+};
+
+#include <asm/elf.h>
+
+#ifndef __KERNEL__
+typedef elf_greg_t greg_t;
+typedef elf_gregset_t gregset_t;
+typedef elf_fpregset_t fpregset_t;
+#define NGREG ELF_NGREG
+#endif
+
+/*
+ * Definitions to generate Intel SVR4-like core files.
+ * These mostly have the same names as the SVR4 types with "elf_"
+ * tacked on the front to prevent clashes with linux definitions,
+ * and the typedef forms have been avoided. This is mostly like
+ * the SVR4 structure, but more Linuxy, with things that Linux does
+ * not support and which gdb doesn't really use excluded.
+ * Fields present but not used are marked with "XXX".
+ */
+struct elf_prstatus
+{
+#if 0
+ long pr_flags; /* XXX Process flags */
+ short pr_why; /* XXX Reason for process halt */
+ short pr_what; /* XXX More detailed reason */
+#endif
+ struct elf_siginfo pr_info; /* Info associated with signal */
+ short pr_cursig; /* Current signal */
+ unsigned long pr_sigpend; /* Set of pending signals */
+ unsigned long pr_sighold; /* Set of held signals */
+#if 0
+ struct sigaltstack pr_altstack; /* Alternate stack info */
+ struct sigaction pr_action; /* Signal action for current sig */
+#endif
+ pid_t pr_pid;
+ pid_t pr_ppid;
+ pid_t pr_pgrp;
+ pid_t pr_sid;
+ struct timeval pr_utime; /* User time */
+ struct timeval pr_stime; /* System time */
+ struct timeval pr_cutime; /* Cumulative user time */
+ struct timeval pr_cstime; /* Cumulative system time */
+#if 0
+ long pr_instr; /* Current instruction */
+#endif
+ elf_gregset_t pr_reg; /* GP registers */
+ int pr_fpvalid; /* True if math co-processor being used. */
+};
+
+#define ELF_PRARGSZ (80) /* Number of chars for args */
+
+struct elf_prpsinfo
+{
+ char pr_state; /* numeric process state */
+ char pr_sname; /* char for pr_state */
+ char pr_zomb; /* zombie */
+ char pr_nice; /* nice val */
+ unsigned long pr_flag; /* flags */
+ uid_t pr_uid;
+ gid_t pr_gid;
+ pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ /* Lots missing */
+ char pr_fname[16]; /* filename of executable */
+ char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
+};
+
+#ifndef __KERNEL__
+typedef struct elf_prstatus prstatus_t;
+typedef struct elf_prpsinfo prpsinfo_t;
+#define PRARGSZ ELF_PRARGSZ
+#endif
+
+#endif /* _LINUX_ELFCORE_H */
diff --git a/pfinet/linux-src/include/linux/epca.h b/pfinet/linux-src/include/linux/epca.h
new file mode 100644
index 00000000..50494814
--- /dev/null
+++ b/pfinet/linux-src/include/linux/epca.h
@@ -0,0 +1,170 @@
+#define XEMPORTS 0xC02
+#define XEPORTS 0xC22
+
+#define MAX_ALLOC 0x100
+
+#define MAXBOARDS 12
+#define FEPCODESEG 0x0200L
+#define FEPCODE 0x2000L
+#define BIOSCODE 0xf800L
+
+#define MISCGLOBAL 0x0C00L
+#define NPORT 0x0C22L
+#define MBOX 0x0C40L
+#define PORTBASE 0x0C90L
+
+/* Begin code defines used for epca_setup */
+
+#define INVALID_BOARD_TYPE 0x1
+#define INVALID_NUM_PORTS 0x2
+#define INVALID_MEM_BASE 0x4
+#define INVALID_PORT_BASE 0x8
+#define INVALID_BOARD_STATUS 0x10
+#define INVALID_ALTPIN 0x20
+
+/* End code defines used for epca_setup */
+
+
+#define FEPCLR 0x00
+#define FEPMEM 0x02
+#define FEPRST 0x04
+#define FEPINT 0x08
+#define FEPMASK 0x0e
+#define FEPWIN 0x80
+
+#define PCXE 0
+#define PCXEVE 1
+#define PCXEM 2
+#define EISAXEM 3
+#define PC64XE 4
+#define PCXI 5
+#define PCIXEM 7
+#define PCICX 8
+#define PCIXR 9
+#define PCIXRJ 10
+#define EPCA_NUM_TYPES 6
+
+
+static char *board_desc[] =
+{
+ "PC/Xe",
+ "PC/Xeve",
+ "PC/Xem",
+ "EISA/Xem",
+ "PC/64Xe",
+ "PC/Xi",
+ "unknown",
+ "PCI/Xem",
+ "PCI/CX",
+ "PCI/Xr",
+ "PCI/Xrj",
+};
+
+#define STARTC 021
+#define STOPC 023
+#define IAIXON 0x2000
+
+
+#define TXSTOPPED 0x1
+#define LOWWAIT 0x2
+#define EMPTYWAIT 0x4
+#define RXSTOPPED 0x8
+#define TXBUSY 0x10
+
+#define DISABLED 0
+#define ENABLED 1
+#define OFF 0
+#define ON 1
+
+#define FEPTIMEOUT 200000
+#define SERIAL_TYPE_NORMAL 1
+#define SERIAL_TYPE_CALLOUT 2
+#define SERIAL_TYPE_INFO 3
+#define EPCA_EVENT_HANGUP 1
+#define EPCA_MAGIC 0x5c6df104L
+
+struct channel
+{
+ long magic;
+ unchar boardnum;
+ unchar channelnum;
+ unchar omodem; /* FEP output modem status */
+ unchar imodem; /* FEP input modem status */
+ unchar modemfake; /* Modem values to be forced */
+ unchar modem; /* Force values */
+ unchar hflow;
+ unchar dsr;
+ unchar dcd;
+ unchar m_rts ; /* The bits used in whatever FEP */
+ unchar m_dcd ; /* is indiginous to this board to */
+ unchar m_dsr ; /* represent each of the physical */
+ unchar m_cts ; /* handshake lines */
+ unchar m_ri ;
+ unchar m_dtr ;
+ unchar stopc;
+ unchar startc;
+ unchar stopca;
+ unchar startca;
+ unchar fepstopc;
+ unchar fepstartc;
+ unchar fepstopca;
+ unchar fepstartca;
+ unchar txwin;
+ unchar rxwin;
+ ushort fepiflag;
+ ushort fepcflag;
+ ushort fepoflag;
+ ushort txbufhead;
+ ushort txbufsize;
+ ushort rxbufhead;
+ ushort rxbufsize;
+ int close_delay;
+ int count;
+ int blocked_open;
+ int event;
+ int asyncflags;
+ uint dev;
+ long session;
+ long pgrp;
+ ulong statusflags;
+ ulong c_iflag;
+ ulong c_cflag;
+ ulong c_lflag;
+ ulong c_oflag;
+ unchar *txptr;
+ unchar *rxptr;
+ unchar *tmp_buf;
+ struct board_info *board;
+ volatile struct board_chan *brdchan;
+ struct digi_struct digiext;
+ struct tty_struct *tty;
+ struct termios normal_termios;
+ struct termios callout_termios;
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+ struct tq_struct tqueue;
+ volatile struct global_data *mailbox;
+};
+
+struct board_info
+{
+ unchar status;
+ unchar type;
+ unchar altpin;
+ ushort numports;
+ unchar *port;
+ unchar *membase;
+ unchar *re_map_port;
+ unchar *re_map_membase;
+ ulong memory_seg;
+ void ( * memwinon ) (struct board_info *, unsigned int) ;
+ void ( * memwinoff ) (struct board_info *, unsigned int) ;
+ void ( * globalwinon ) (struct channel *) ;
+ void ( * txwinon ) (struct channel *) ;
+ void ( * rxwinon ) (struct channel *) ;
+ void ( * memoff ) (struct channel *) ;
+ void ( * assertgwinon ) (struct channel *) ;
+ void ( * assertmemoff ) (struct channel *) ;
+ unchar poller_inhibited ;
+};
+
diff --git a/pfinet/linux-src/include/linux/epcaconfig.h b/pfinet/linux-src/include/linux/epcaconfig.h
new file mode 100644
index 00000000..c840c673
--- /dev/null
+++ b/pfinet/linux-src/include/linux/epcaconfig.h
@@ -0,0 +1,8 @@
+#define NUMCARDS 1
+#define NBDEVS 2
+
+struct board_info static_boards[NUMCARDS]={
+ { ENABLED, 0, OFF, 2, (unchar*) 0x320, (unchar*) 0xd0000 },
+};
+
+/* DO NOT HAND EDIT THIS FILE! */
diff --git a/pfinet/linux-src/include/linux/errno.h b/pfinet/linux-src/include/linux/errno.h
new file mode 100644
index 00000000..ac212844
--- /dev/null
+++ b/pfinet/linux-src/include/linux/errno.h
@@ -0,0 +1,16 @@
+#ifndef _LINUX_ERRNO_H
+#define _LINUX_ERRNO_H
+
+#include <asm/errno.h>
+
+#ifdef __KERNEL__
+
+/* Should never be seen by user programs */
+#define ERESTARTSYS 512
+#define ERESTARTNOINTR 513
+#define ERESTARTNOHAND 514 /* restart if no handler.. */
+#define ENOIOCTLCMD 515 /* No ioctl command */
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/errqueue.h b/pfinet/linux-src/include/linux/errqueue.h
new file mode 100644
index 00000000..4a16756d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/errqueue.h
@@ -0,0 +1,42 @@
+#ifndef _LINUX_ERRQUEUE_H
+#define _LINUX_ERRQUEUE_H 1
+
+#include <linux/config.h>
+
+struct sock_extended_err
+{
+ __u32 ee_errno;
+ __u8 ee_origin;
+ __u8 ee_type;
+ __u8 ee_code;
+ __u8 ee_pad;
+ __u32 ee_info;
+ __u32 ee_data;
+};
+
+#define SO_EE_ORIGIN_NONE 0
+#define SO_EE_ORIGIN_LOCAL 1
+#define SO_EE_ORIGIN_ICMP 2
+#define SO_EE_ORIGIN_ICMP6 3
+
+#define SO_EE_OFFENDER(ee) ((struct sockaddr*)((ee)+1))
+
+#ifdef __KERNEL__
+#define SKB_EXT_ERR(skb) ((struct sock_exterr_skb *) ((skb)->cb))
+
+struct sock_exterr_skb
+{
+ union {
+ struct inet_skb_parm h4;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct inet6_skb_parm h6;
+#endif
+ } header;
+ struct sock_extended_err ee;
+ u16 addr_offset;
+ u16 port;
+};
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/etherdevice.h b/pfinet/linux-src/include/linux/etherdevice.h
new file mode 100644
index 00000000..9101855c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/etherdevice.h
@@ -0,0 +1,56 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. NET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the Ethernet handlers.
+ *
+ * Version: @(#)eth.h 1.0.4 05/13/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * Relocated to include/linux where it belongs by Alan Cox
+ * <gw4pts@gw4pts.ampr.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * WARNING: This move may well be temporary. This file will get merged with others RSN.
+ *
+ */
+#ifndef _LINUX_ETHERDEVICE_H
+#define _LINUX_ETHERDEVICE_H
+
+#include <linux/config.h>
+#include <linux/if_ether.h>
+
+#ifdef __KERNEL__
+extern int eth_header(struct sk_buff *skb, struct device *dev,
+ unsigned short type, void *daddr,
+ void *saddr, unsigned len);
+extern int eth_rebuild_header(struct sk_buff *skb);
+extern unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev);
+extern void eth_header_cache_update(struct hh_cache *hh, struct device *dev,
+ unsigned char * haddr);
+extern int eth_header_cache(struct neighbour *neigh,
+ struct hh_cache *hh);
+extern int eth_header_parse(struct sk_buff *skb,
+ unsigned char *haddr);
+extern struct device * init_etherdev(struct device *, int);
+
+#ifdef CONFIG_IP_ROUTER
+static __inline__ void eth_copy_and_sum (struct sk_buff *dest, unsigned char *src, int len, int base)
+{
+ memcpy (dest->data, src, len);
+}
+#else
+extern void eth_copy_and_sum(struct sk_buff *dest,
+ unsigned char *src, int length, int base);
+#endif
+
+#endif
+
+#endif /* _LINUX_ETHERDEVICE_H */
diff --git a/pfinet/linux-src/include/linux/ext2_fs.h b/pfinet/linux-src/include/linux/ext2_fs.h
new file mode 100644
index 00000000..840e7cad
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ext2_fs.h
@@ -0,0 +1,624 @@
+/*
+ * linux/include/linux/ext2_fs.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/include/linux/minix_fs.h
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT2_FS_H
+#define _LINUX_EXT2_FS_H
+
+#include <linux/types.h>
+
+/*
+ * The second extended filesystem constants/structures
+ */
+
+/*
+ * Define EXT2FS_DEBUG to produce debug messages
+ */
+#undef EXT2FS_DEBUG
+
+/*
+ * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
+ */
+#define EXT2_PREALLOCATE
+#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
+
+/*
+ * The second extended file system version
+ */
+#define EXT2FS_DATE "95/08/09"
+#define EXT2FS_VERSION "0.5b"
+
+/*
+ * Debug code
+ */
+#ifdef EXT2FS_DEBUG
+# define ext2_debug(f, a...) { \
+ printk ("EXT2-fs DEBUG (%s, %d): %s:", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ printk (f, ## a); \
+ }
+#else
+# define ext2_debug(f, a...) /**/
+#endif
+
+/*
+ * Special inodes numbers
+ */
+#define EXT2_BAD_INO 1 /* Bad blocks inode */
+#define EXT2_ROOT_INO 2 /* Root inode */
+#define EXT2_ACL_IDX_INO 3 /* ACL inode */
+#define EXT2_ACL_DATA_INO 4 /* ACL inode */
+#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
+#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
+
+/* First non-reserved inode for old ext2 filesystems */
+#define EXT2_GOOD_OLD_FIRST_INO 11
+
+/*
+ * The second extended file system magic number
+ */
+#define EXT2_SUPER_MAGIC 0xEF53
+
+/*
+ * Maximal count of links to a file
+ */
+#define EXT2_LINK_MAX 32000
+
+/*
+ * Macro-instructions used to manage several block sizes
+ */
+#define EXT2_MIN_BLOCK_SIZE 1024
+#define EXT2_MAX_BLOCK_SIZE 4096
+#define EXT2_MIN_BLOCK_LOG_SIZE 10
+#ifdef __KERNEL__
+# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
+#else
+# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+#endif
+#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
+#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
+#ifdef __KERNEL__
+# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
+#else
+# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
+#endif
+#ifdef __KERNEL__
+#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
+#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
+#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
+#else
+#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+ EXT2_GOOD_OLD_INODE_SIZE : \
+ (s)->s_inode_size)
+#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+ EXT2_GOOD_OLD_FIRST_INO : \
+ (s)->s_first_ino)
+#endif
+
+/*
+ * Macro-instructions used to manage fragments
+ */
+#define EXT2_MIN_FRAG_SIZE 1024
+#define EXT2_MAX_FRAG_SIZE 4096
+#define EXT2_MIN_FRAG_LOG_SIZE 10
+#ifdef __KERNEL__
+# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
+#else
+# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
+#endif
+
+/*
+ * ACL structures
+ */
+struct ext2_acl_header /* Header of Access Control Lists */
+{
+ __u32 aclh_size;
+ __u32 aclh_file_count;
+ __u32 aclh_acle_count;
+ __u32 aclh_first_acle;
+};
+
+struct ext2_acl_entry /* Access Control List Entry */
+{
+ __u32 acle_size;
+ __u16 acle_perms; /* Access permissions */
+ __u16 acle_type; /* Type of entry */
+ __u16 acle_tag; /* User or group identity */
+ __u16 acle_pad1;
+ __u32 acle_next; /* Pointer on next entry for the */
+ /* same inode or on next free entry */
+};
+
+/*
+ * Structure of a blocks group descriptor
+ */
+struct ext2_group_desc
+{
+ __u32 bg_block_bitmap; /* Blocks bitmap block */
+ __u32 bg_inode_bitmap; /* Inodes bitmap block */
+ __u32 bg_inode_table; /* Inodes table block */
+ __u16 bg_free_blocks_count; /* Free blocks count */
+ __u16 bg_free_inodes_count; /* Free inodes count */
+ __u16 bg_used_dirs_count; /* Directories count */
+ __u16 bg_pad;
+ __u32 bg_reserved[3];
+};
+
+/*
+ * Macro-instructions used to manage group descriptors
+ */
+#ifdef __KERNEL__
+# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
+# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
+# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits)
+#else
+# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
+#endif
+
+/*
+ * Constants relative to the data blocks
+ */
+#define EXT2_NDIR_BLOCKS 12
+#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
+#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
+#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
+#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
+
+/*
+ * Inode flags
+ */
+#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
+#define EXT2_UNRM_FL 0x00000002 /* Undelete */
+#define EXT2_COMPR_FL 0x00000004 /* Compress file */
+#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
+#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
+#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
+#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
+#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
+/* Reserved for compression usage... */
+#define EXT2_DIRTY_FL 0x00000100
+#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
+#define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */
+#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
+/* End compression flags --- maybe not all used */
+#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
+#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
+
+#define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
+
+/*
+ * ioctl commands
+ */
+#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
+#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
+#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
+#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
+
+/*
+ * Structure of an inode on the disk
+ */
+struct ext2_inode {
+ __u16 i_mode; /* File mode */
+ __u16 i_uid; /* Owner Uid */
+ __u32 i_size; /* Size in bytes */
+ __u32 i_atime; /* Access time */
+ __u32 i_ctime; /* Creation time */
+ __u32 i_mtime; /* Modification time */
+ __u32 i_dtime; /* Deletion Time */
+ __u16 i_gid; /* Group Id */
+ __u16 i_links_count; /* Links count */
+ __u32 i_blocks; /* Blocks count */
+ __u32 i_flags; /* File flags */
+ union {
+ struct {
+ __u32 l_i_reserved1;
+ } linux1;
+ struct {
+ __u32 h_i_translator;
+ } hurd1;
+ struct {
+ __u32 m_i_reserved1;
+ } masix1;
+ } osd1; /* OS dependent 1 */
+ __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+ __u32 i_version; /* File version (for NFS) */
+ __u32 i_file_acl; /* File ACL */
+ __u32 i_dir_acl; /* Directory ACL */
+ __u32 i_faddr; /* Fragment address */
+ union {
+ struct {
+ __u8 l_i_frag; /* Fragment number */
+ __u8 l_i_fsize; /* Fragment size */
+ __u16 i_pad1;
+ __u32 l_i_reserved2[2];
+ } linux2;
+ struct {
+ __u8 h_i_frag; /* Fragment number */
+ __u8 h_i_fsize; /* Fragment size */
+ __u16 h_i_mode_high;
+ __u16 h_i_uid_high;
+ __u16 h_i_gid_high;
+ __u32 h_i_author;
+ } hurd2;
+ struct {
+ __u8 m_i_frag; /* Fragment number */
+ __u8 m_i_fsize; /* Fragment size */
+ __u16 m_pad1;
+ __u32 m_i_reserved2[2];
+ } masix2;
+ } osd2; /* OS dependent 2 */
+};
+
+#define i_size_high i_dir_acl
+
+#if defined(__KERNEL__) || defined(__linux__)
+#define i_reserved1 osd1.linux1.l_i_reserved1
+#define i_frag osd2.linux2.l_i_frag
+#define i_fsize osd2.linux2.l_i_fsize
+#define i_reserved2 osd2.linux2.l_i_reserved2
+#endif
+
+#ifdef __hurd__
+#define i_translator osd1.hurd1.h_i_translator
+#define i_frag osd2.hurd2.h_i_frag;
+#define i_fsize osd2.hurd2.h_i_fsize;
+#define i_uid_high osd2.hurd2.h_i_uid_high
+#define i_gid_high osd2.hurd2.h_i_gid_high
+#define i_author osd2.hurd2.h_i_author
+#endif
+
+#ifdef __masix__
+#define i_reserved1 osd1.masix1.m_i_reserved1
+#define i_frag osd2.masix2.m_i_frag
+#define i_fsize osd2.masix2.m_i_fsize
+#define i_reserved2 osd2.masix2.m_i_reserved2
+#endif
+
+/*
+ * File system states
+ */
+#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
+#define EXT2_ERROR_FS 0x0002 /* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK_NORMAL 0x0001 /* Do some more checks */
+#define EXT2_MOUNT_CHECK_STRICT 0x0002 /* Do again more checks */
+#define EXT2_MOUNT_CHECK (EXT2_MOUNT_CHECK_NORMAL | \
+ EXT2_MOUNT_CHECK_STRICT)
+#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
+
+#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
+ EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
+
+/*
+ * Behaviour when detecting errors
+ */
+#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
+#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
+#define EXT2_ERRORS_PANIC 3 /* Panic */
+#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
+
+/*
+ * Structure of the super block
+ */
+struct ext2_super_block {
+ __u32 s_inodes_count; /* Inodes count */
+ __u32 s_blocks_count; /* Blocks count */
+ __u32 s_r_blocks_count; /* Reserved blocks count */
+ __u32 s_free_blocks_count; /* Free blocks count */
+ __u32 s_free_inodes_count; /* Free inodes count */
+ __u32 s_first_data_block; /* First Data Block */
+ __u32 s_log_block_size; /* Block size */
+ __s32 s_log_frag_size; /* Fragment size */
+ __u32 s_blocks_per_group; /* # Blocks per group */
+ __u32 s_frags_per_group; /* # Fragments per group */
+ __u32 s_inodes_per_group; /* # Inodes per group */
+ __u32 s_mtime; /* Mount time */
+ __u32 s_wtime; /* Write time */
+ __u16 s_mnt_count; /* Mount count */
+ __s16 s_max_mnt_count; /* Maximal mount count */
+ __u16 s_magic; /* Magic signature */
+ __u16 s_state; /* File system state */
+ __u16 s_errors; /* Behaviour when detecting errors */
+ __u16 s_minor_rev_level; /* minor revision level */
+ __u32 s_lastcheck; /* time of last check */
+ __u32 s_checkinterval; /* max. time between checks */
+ __u32 s_creator_os; /* OS */
+ __u32 s_rev_level; /* Revision level */
+ __u16 s_def_resuid; /* Default uid for reserved blocks */
+ __u16 s_def_resgid; /* Default gid for reserved blocks */
+ /*
+ * These fields are for EXT2_DYNAMIC_REV superblocks only.
+ *
+ * Note: the difference between the compatible feature set and
+ * the incompatible feature set is that if there is a bit set
+ * in the incompatible feature set that the kernel doesn't
+ * know about, it should refuse to mount the filesystem.
+ *
+ * e2fsck's requirements are more strict; if it doesn't know
+ * about a feature in either the compatible or incompatible
+ * feature set, it must abort and not try to meddle with
+ * things it doesn't understand...
+ */
+ __u32 s_first_ino; /* First non-reserved inode */
+ __u16 s_inode_size; /* size of inode structure */
+ __u16 s_block_group_nr; /* block group # of this superblock */
+ __u32 s_feature_compat; /* compatible feature set */
+ __u32 s_feature_incompat; /* incompatible feature set */
+ __u32 s_feature_ro_compat; /* readonly-compatible feature set */
+ __u8 s_uuid[16]; /* 128-bit uuid for volume */
+ char s_volume_name[16]; /* volume name */
+ char s_last_mounted[64]; /* directory where last mounted */
+ __u32 s_algorithm_usage_bitmap; /* For compression */
+ /*
+ * Performance hints. Directory preallocation should only
+ * happen if the EXT2_COMPAT_PREALLOC flag is on.
+ */
+ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
+ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
+ __u16 s_padding1;
+ __u32 s_reserved[204]; /* Padding to the end of the block */
+};
+
+#ifdef __KERNEL__
+#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
+#else
+/* Assume that user mode programs are passing in an ext2fs superblock, not
+ * a kernel struct super_block. This will allow us to call the feature-test
+ * macros from user land. */
+#define EXT2_SB(sb) (sb)
+#endif
+
+/*
+ * Codes for operating systems
+ */
+#define EXT2_OS_LINUX 0
+#define EXT2_OS_HURD 1
+#define EXT2_OS_MASIX 2
+#define EXT2_OS_FREEBSD 3
+#define EXT2_OS_LITES 4
+
+/*
+ * Revision levels
+ */
+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
+#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+
+#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
+#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
+
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+
+/*
+ * Feature set definitions
+ */
+
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_feature_compat & (mask) )
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_feature_incompat & (mask) )
+
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
+
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
+
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
+
+#define EXT2_FEATURE_COMPAT_SUPP 0
+#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
+#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+
+/*
+ * Default values for user and/or group using reserved blocks
+ */
+#define EXT2_DEF_RESUID 0
+#define EXT2_DEF_RESGID 0
+
+/*
+ * Structure of a directory entry
+ */
+#define EXT2_NAME_LEN 255
+
+struct ext2_dir_entry {
+ __u32 inode; /* Inode number */
+ __u16 rec_len; /* Directory entry length */
+ __u16 name_len; /* Name length */
+ char name[EXT2_NAME_LEN]; /* File name */
+};
+
+/*
+ * The new version of the directory entry. Since EXT2 structures are
+ * stored in intel byte order, and the name_len field could never be
+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
+ * file_type field.
+ */
+struct ext2_dir_entry_2 {
+ __u32 inode; /* Inode number */
+ __u16 rec_len; /* Directory entry length */
+ __u8 name_len; /* Name length */
+ __u8 file_type;
+ char name[EXT2_NAME_LEN]; /* File name */
+};
+
+/*
+ * Ext2 directory file types. Only the low 3 bits are used. The
+ * other bits are reserved for now.
+ */
+#define EXT2_FT_UNKNOWN 0
+#define EXT2_FT_REG_FILE 1
+#define EXT2_FT_DIR 2
+#define EXT2_FT_CHRDEV 3
+#define EXT2_FT_BLKDEV 4
+#define EXT2_FT_FIFO 5
+#define EXT2_FT_SOCK 6
+#define EXT2_FT_SYMLINK 7
+
+#define EXT2_FT_MAX 8
+
+/*
+ * EXT2_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define EXT2_DIR_PAD 4
+#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
+#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
+ ~EXT2_DIR_ROUND)
+
+#ifdef __KERNEL__
+
+/* Filesize hard limits for 64-bit file offsets */
+extern long long ext2_max_sizes[];
+
+/*
+ * Function prototypes
+ */
+
+/*
+ * Ok, these declarations are also in <linux/kernel.h> but none of the
+ * ext2 source programs needs to include it so they are duplicated here.
+ */
+# define NORET_TYPE /**/
+# define ATTRIB_NORET __attribute__((noreturn))
+# define NORET_AND noreturn,
+
+/* acl.c */
+extern int ext2_permission (struct inode *, int);
+
+/* balloc.c */
+extern int ext2_group_sparse(int group);
+extern int ext2_new_block (const struct inode *, unsigned long,
+ __u32 *, __u32 *, int *);
+extern void ext2_free_blocks (const struct inode *, unsigned long,
+ unsigned long);
+extern unsigned long ext2_count_free_blocks (struct super_block *);
+extern void ext2_check_blocks_bitmap (struct super_block *);
+extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
+ unsigned int block_group,
+ struct buffer_head ** bh);
+
+/* bitmap.c */
+extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
+
+/* dir.c */
+extern int ext2_check_dir_entry (const char *, struct inode *,
+ struct ext2_dir_entry_2 *, struct buffer_head *,
+ unsigned long);
+
+/* file.c */
+extern int ext2_read (struct inode *, struct file *, char *, int);
+extern int ext2_write (struct inode *, struct file *, char *, int);
+
+/* fsync.c */
+extern int ext2_sync_file (struct file *, struct dentry *);
+
+/* ialloc.c */
+extern struct inode * ext2_new_inode (const struct inode *, int, int *);
+extern void ext2_free_inode (struct inode *);
+extern unsigned long ext2_count_free_inodes (struct super_block *);
+extern void ext2_check_inodes_bitmap (struct super_block *);
+
+/* inode.c */
+extern int ext2_bmap (struct inode *, int);
+
+extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
+extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
+
+extern int ext2_getcluster (struct inode * inode, long block);
+extern void ext2_read_inode (struct inode *);
+extern void ext2_write_inode (struct inode *);
+extern void ext2_put_inode (struct inode *);
+extern void ext2_delete_inode (struct inode *);
+extern int ext2_sync_inode (struct inode *);
+extern int ext2_notify_change(struct dentry *, struct iattr *);
+extern void ext2_discard_prealloc (struct inode *);
+
+/* ioctl.c */
+extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+/* namei.c */
+extern void ext2_release (struct inode *, struct file *);
+extern struct dentry *ext2_lookup (struct inode *, struct dentry *);
+extern int ext2_create (struct inode *,struct dentry *,int);
+extern int ext2_mkdir (struct inode *,struct dentry *,int);
+extern int ext2_rmdir (struct inode *,struct dentry *);
+extern int ext2_unlink (struct inode *,struct dentry *);
+extern int ext2_symlink (struct inode *,struct dentry *,const char *);
+extern int ext2_link (struct dentry *, struct inode *, struct dentry *);
+extern int ext2_mknod (struct inode *, struct dentry *, int, int);
+extern int ext2_rename (struct inode *, struct dentry *,
+ struct inode *, struct dentry *);
+
+/* super.c */
+extern void ext2_error (struct super_block *, const char *, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
+ const char *, ...)
+ __attribute__ ((NORET_AND format (printf, 3, 4)));
+extern void ext2_warning (struct super_block *, const char *, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern void ext2_put_super (struct super_block *);
+extern void ext2_write_super (struct super_block *);
+extern int ext2_remount (struct super_block *, int *, char *);
+extern struct super_block * ext2_read_super (struct super_block *,void *,int);
+extern int init_ext2_fs(void);
+extern int ext2_statfs (struct super_block *, struct statfs *, int);
+
+/* truncate.c */
+extern void ext2_truncate (struct inode *);
+
+/*
+ * Inodes and files operations
+ */
+
+/* dir.c */
+extern struct inode_operations ext2_dir_inode_operations;
+
+/* file.c */
+extern struct inode_operations ext2_file_inode_operations;
+
+/* symlink.c */
+extern struct inode_operations ext2_symlink_inode_operations;
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_EXT2_FS_H */
diff --git a/pfinet/linux-src/include/linux/ext2_fs_i.h b/pfinet/linux-src/include/linux/ext2_fs_i.h
new file mode 100644
index 00000000..8f01f8ad
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ext2_fs_i.h
@@ -0,0 +1,42 @@
+/*
+ * linux/include/linux/ext2_fs_i.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/include/linux/minix_fs_i.h
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT2_FS_I
+#define _LINUX_EXT2_FS_I
+
+/*
+ * second extended file system inode data in memory
+ */
+struct ext2_inode_info {
+ __u32 i_data[15];
+ __u32 i_flags;
+ __u32 i_faddr;
+ __u8 i_frag_no;
+ __u8 i_frag_size;
+ __u16 i_osync;
+ __u32 i_file_acl;
+ __u32 i_dir_acl;
+ __u32 i_dtime;
+ __u32 i_version;
+ __u32 i_block_group;
+ __u32 i_next_alloc_block;
+ __u32 i_next_alloc_goal;
+ __u32 i_prealloc_block;
+ __u32 i_prealloc_count;
+ __u32 i_high_size;
+ int i_new_inode:1; /* Is a freshly allocated inode */
+};
+
+#endif /* _LINUX_EXT2_FS_I */
diff --git a/pfinet/linux-src/include/linux/ext2_fs_sb.h b/pfinet/linux-src/include/linux/ext2_fs_sb.h
new file mode 100644
index 00000000..20721632
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ext2_fs_sb.h
@@ -0,0 +1,66 @@
+/*
+ * linux/include/linux/ext2_fs_sb.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/include/linux/minix_fs_sb.h
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT2_FS_SB
+#define _LINUX_EXT2_FS_SB
+
+#include <linux/ext2_fs.h>
+
+/*
+ * The following is not needed anymore since the descriptors buffer
+ * heads are now dynamically allocated
+ */
+/* #define EXT2_MAX_GROUP_DESC 8 */
+
+#define EXT2_MAX_GROUP_LOADED 8
+
+/*
+ * second extended-fs super-block data in memory
+ */
+struct ext2_sb_info {
+ unsigned long s_frag_size; /* Size of a fragment in bytes */
+ unsigned long s_frags_per_block;/* Number of fragments per block */
+ unsigned long s_inodes_per_block;/* Number of inodes per block */
+ unsigned long s_frags_per_group;/* Number of fragments in a group */
+ unsigned long s_blocks_per_group;/* Number of blocks in a group */
+ unsigned long s_inodes_per_group;/* Number of inodes in a group */
+ unsigned long s_itb_per_group; /* Number of inode table blocks per group */
+ unsigned long s_db_per_group; /* Number of descriptor blocks per group */
+ unsigned long s_desc_per_block; /* Number of group descriptors per block */
+ unsigned long s_groups_count; /* Number of groups in the fs */
+ struct buffer_head * s_sbh; /* Buffer containing the super block */
+ struct ext2_super_block * s_es; /* Pointer to the super block in the buffer */
+ struct buffer_head ** s_group_desc;
+ unsigned short s_loaded_inode_bitmaps;
+ unsigned short s_loaded_block_bitmaps;
+ unsigned long s_inode_bitmap_number[EXT2_MAX_GROUP_LOADED];
+ struct buffer_head * s_inode_bitmap[EXT2_MAX_GROUP_LOADED];
+ unsigned long s_block_bitmap_number[EXT2_MAX_GROUP_LOADED];
+ struct buffer_head * s_block_bitmap[EXT2_MAX_GROUP_LOADED];
+ unsigned long s_mount_opt;
+ unsigned short s_resuid;
+ unsigned short s_resgid;
+ unsigned short s_mount_state;
+ unsigned short s_pad;
+ int s_addr_per_block_bits;
+ int s_desc_per_block_bits;
+ int s_inode_size;
+ int s_first_ino;
+ int s_feature_compat;
+ int s_feature_incompat;
+ int s_feature_ro_compat;
+};
+
+#endif /* _LINUX_EXT2_FS_SB */
diff --git a/pfinet/linux-src/include/linux/fat_cvf.h b/pfinet/linux-src/include/linux/fat_cvf.h
new file mode 100644
index 00000000..1c4df58f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/fat_cvf.h
@@ -0,0 +1,49 @@
+#ifndef _FAT_CVF
+#define _FAT_CVF
+
+#define CVF_USE_READPAGE 0x0001
+
+struct cvf_format
+{ int cvf_version;
+ char* cvf_version_text;
+ unsigned long flags;
+ int (*detect_cvf) (struct super_block*sb);
+ int (*mount_cvf) (struct super_block*sb,char*options);
+ int (*unmount_cvf) (struct super_block*sb);
+ struct buffer_head* (*cvf_bread) (struct super_block*sb,int block);
+ struct buffer_head* (*cvf_getblk) (struct super_block*sb,int block);
+ void (*cvf_brelse) (struct super_block *sb,struct buffer_head *bh);
+ void (*cvf_mark_buffer_dirty) (struct super_block *sb,
+ struct buffer_head *bh,
+ int dirty_val);
+ void (*cvf_set_uptodate) (struct super_block *sb,
+ struct buffer_head *bh,
+ int val);
+ int (*cvf_is_uptodate) (struct super_block *sb,struct buffer_head *bh);
+ void (*cvf_ll_rw_block) (struct super_block *sb,
+ int opr,
+ int nbreq,
+ struct buffer_head *bh[32]);
+ int (*fat_access) (struct super_block *sb,int nr,int new_value);
+ int (*cvf_statfs) (struct super_block *sb,struct statfs *buf, int bufsiz);
+ int (*cvf_bmap) (struct inode *inode,int block);
+ int (*cvf_smap) (struct inode *inode,int sector);
+ ssize_t (*cvf_file_read) ( struct file *, char *, size_t, loff_t *);
+ ssize_t (*cvf_file_write) ( struct file *, const char *, size_t, loff_t *);
+ int (*cvf_mmap) (struct file *, struct vm_area_struct *);
+ int (*cvf_readpage) (struct inode *, struct page *);
+ int (*cvf_writepage) (struct inode *, struct page *);
+ int (*cvf_dir_ioctl) (struct inode * inode, struct file * filp,
+ unsigned int cmd, unsigned long arg);
+ void (*zero_out_cluster) (struct inode*, int clusternr);
+};
+
+int register_cvf_format(struct cvf_format*cvf_format);
+int unregister_cvf_format(struct cvf_format*cvf_format);
+void dec_cvf_format_use_count_by_version(int version);
+int detect_cvf(struct super_block*sb,char*force);
+
+extern struct cvf_format *cvf_formats[];
+extern int cvf_format_use_count[];
+
+#endif
diff --git a/pfinet/linux-src/include/linux/fb.h b/pfinet/linux-src/include/linux/fb.h
new file mode 100644
index 00000000..f084ca03
--- /dev/null
+++ b/pfinet/linux-src/include/linux/fb.h
@@ -0,0 +1,492 @@
+#ifndef _LINUX_FB_H
+#define _LINUX_FB_H
+
+#include <asm/types.h>
+
+/* Definitions of frame buffers */
+
+#define FB_MAJOR 29
+
+#define FB_MODES_SHIFT 5 /* 32 modes per framebuffer */
+#define FB_NUM_MINORS 256 /* 256 Minors */
+#define FB_MAX (FB_NUM_MINORS / (1 << FB_MODES_SHIFT))
+#define GET_FB_IDX(node) (MINOR(node) >> FB_MODES_SHIFT)
+
+/* ioctls
+ 0x46 is 'F' */
+#define FBIOGET_VSCREENINFO 0x4600
+#define FBIOPUT_VSCREENINFO 0x4601
+#define FBIOGET_FSCREENINFO 0x4602
+#define FBIOGETCMAP 0x4604
+#define FBIOPUTCMAP 0x4605
+#define FBIOPAN_DISPLAY 0x4606
+/* 0x4607-0x460B are defined below */
+/* #define FBIOGET_MONITORSPEC 0x460C */
+/* #define FBIOPUT_MONITORSPEC 0x460D */
+/* #define FBIOSWITCH_MONIBIT 0x460E */
+#define FBIOGET_CON2FBMAP 0x460F
+#define FBIOPUT_CON2FBMAP 0x4610
+
+#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
+#define FB_TYPE_PLANES 1 /* Non interleaved planes */
+#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
+#define FB_TYPE_TEXT 3 /* Text/attributes */
+#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */
+
+#define FB_AUX_TEXT_MDA 0 /* Monochrome text */
+#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */
+#define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */
+#define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 reserved bytes */
+#define FB_AUX_TEXT_MGA_STEP8 4 /* other MGAs: text, attr, 6 reserved bytes */
+
+#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */
+#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */
+#define FB_VISUAL_TRUECOLOR 2 /* True color */
+#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
+#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
+#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
+
+#define FB_ACCEL_NONE 0 /* no hardware accelerator */
+#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */
+#define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */
+#define FB_ACCEL_S3_TRIO64 3 /* Cybervision64 (S3 Trio64) */
+#define FB_ACCEL_NCR_77C32BLT 4 /* RetinaZ3 (NCR 77C32BLT) */
+#define FB_ACCEL_S3_VIRGE 5 /* Cybervision64/3D (S3 ViRGE) */
+#define FB_ACCEL_ATI_MACH64GX 6 /* ATI Mach 64GX family */
+#define FB_ACCEL_DEC_TGA 7 /* DEC 21030 TGA */
+#define FB_ACCEL_ATI_MACH64CT 8 /* ATI Mach 64CT family */
+#define FB_ACCEL_ATI_MACH64VT 9 /* ATI Mach 64CT family VT class */
+#define FB_ACCEL_ATI_MACH64GT 10 /* ATI Mach 64CT family GT class */
+#define FB_ACCEL_SUN_CREATOR 11 /* Sun Creator/Creator3D */
+#define FB_ACCEL_SUN_CGSIX 12 /* Sun cg6 */
+#define FB_ACCEL_SUN_LEO 13 /* Sun leo/zx */
+#define FB_ACCEL_IMS_TWINTURBO 14 /* IMS Twin Turbo */
+#define FB_ACCEL_3DLABS_PERMEDIA2 15 /* 3Dlabs Permedia 2 */
+#define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W (Millenium) */
+#define FB_ACCEL_MATROX_MGA1064SG 17 /* Matrox MGA1064SG (Mystique) */
+#define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */
+#define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (Millenium II) */
+#define FB_ACCEL_MATROX_MGAG100 20 /* Matrox G100 (Productiva G100) */
+#define FB_ACCEL_MATROX_MGAG200 21 /* Matrox G200 (Myst, Mill, ...) */
+#define FB_ACCEL_SUN_CG14 22 /* Sun cgfourteen */
+#define FB_ACCEL_SUN_BWTWO 23 /* Sun bwtwo */
+#define FB_ACCEL_SUN_CGTHREE 24 /* Sun cgthree */
+#define FB_ACCEL_SUN_TCX 25 /* Sun tcx */
+
+struct fb_fix_screeninfo {
+ char id[16]; /* identification string eg "TT Builtin" */
+ char *smem_start; /* Start of frame buffer mem */
+ /* (physical address) */
+ __u32 smem_len; /* Length of frame buffer mem */
+ __u32 type; /* see FB_TYPE_* */
+ __u32 type_aux; /* Interleave for interleaved Planes */
+ __u32 visual; /* see FB_VISUAL_* */
+ __u16 xpanstep; /* zero if no hardware panning */
+ __u16 ypanstep; /* zero if no hardware panning */
+ __u16 ywrapstep; /* zero if no hardware ywrap */
+ __u32 line_length; /* length of a line in bytes */
+ char *mmio_start; /* Start of Memory Mapped I/O */
+ /* (physical address) */
+ __u32 mmio_len; /* Length of Memory Mapped I/O */
+ __u32 accel; /* Type of acceleration available */
+ __u16 reserved[3]; /* Reserved for future compatibility */
+};
+
+/* Interpretation of offset for color fields: All offsets are from the right,
+ * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
+ * can use the offset as right argument to <<). A pixel afterwards is a bit
+ * stream and is written to video memory as that unmodified. This implies
+ * big-endian byte order if bits_per_pixel is greater than 8.
+ */
+struct fb_bitfield {
+ __u32 offset; /* beginning of bitfield */
+ __u32 length; /* length of bitfield */
+ __u32 msb_right; /* != 0 : Most significant bit is */
+ /* right */
+};
+
+#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */
+
+#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/
+#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */
+#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */
+#define FB_ACTIVATE_MASK 15
+ /* values */
+#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */
+#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */
+#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */
+
+#define FB_ACCELF_TEXT 1 /* text mode acceleration */
+
+#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
+#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
+#define FB_SYNC_EXT 4 /* external sync */
+#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
+#define FB_SYNC_BROADCAST 16 /* broadcast video timings */
+ /* vtotal = 144d/288n/576i => PAL */
+ /* vtotal = 121d/242n/484i => NTSC */
+#define FB_SYNC_ON_GREEN 32 /* sync on green */
+
+#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
+#define FB_VMODE_INTERLACED 1 /* interlaced */
+#define FB_VMODE_DOUBLE 2 /* double scan */
+#define FB_VMODE_MASK 255
+
+#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */
+#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
+#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */
+
+struct fb_var_screeninfo {
+ __u32 xres; /* visible resolution */
+ __u32 yres;
+ __u32 xres_virtual; /* virtual resolution */
+ __u32 yres_virtual;
+ __u32 xoffset; /* offset from virtual to visible */
+ __u32 yoffset; /* resolution */
+
+ __u32 bits_per_pixel; /* guess what */
+ __u32 grayscale; /* != 0 Graylevels instead of colors */
+
+ struct fb_bitfield red; /* bitfield in fb mem if true color, */
+ struct fb_bitfield green; /* else only length is significant */
+ struct fb_bitfield blue;
+ struct fb_bitfield transp; /* transparency */
+
+ __u32 nonstd; /* != 0 Non standard pixel format */
+
+ __u32 activate; /* see FB_ACTIVATE_* */
+
+ __u32 height; /* height of picture in mm */
+ __u32 width; /* width of picture in mm */
+
+ __u32 accel_flags; /* acceleration flags (hints) */
+
+ /* Timing: All values in pixclocks, except pixclock (of course) */
+ __u32 pixclock; /* pixel clock in ps (pico seconds) */
+ __u32 left_margin; /* time from sync to picture */
+ __u32 right_margin; /* time from picture to sync */
+ __u32 upper_margin; /* time from sync to picture */
+ __u32 lower_margin;
+ __u32 hsync_len; /* length of horizontal sync */
+ __u32 vsync_len; /* length of vertical sync */
+ __u32 sync; /* see FB_SYNC_* */
+ __u32 vmode; /* see FB_VMODE_* */
+ __u32 reserved[6]; /* Reserved for future compatibility */
+};
+
+struct fb_cmap {
+ __u32 start; /* First entry */
+ __u32 len; /* Number of entries */
+ __u16 *red; /* Red values */
+ __u16 *green;
+ __u16 *blue;
+ __u16 *transp; /* transparency, can be NULL */
+};
+
+struct fb_con2fbmap {
+ __u32 console;
+ __u32 framebuffer;
+};
+
+struct fb_monspecs {
+ __u32 hfmin; /* hfreq lower limit (Hz) */
+ __u32 hfmax; /* hfreq upper limit (Hz) */
+ __u16 vfmin; /* vfreq lower limit (Hz) */
+ __u16 vfmax; /* vfreq upper limit (Hz) */
+ unsigned dpms : 1; /* supports DPMS */
+};
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+
+
+struct fb_info;
+struct fb_info_gen;
+struct vm_area_struct;
+struct file;
+
+ /*
+ * Frame buffer operations
+ */
+
+struct fb_ops {
+ /* open/release and usage marking */
+ int (*fb_open)(struct fb_info *info, int user);
+ int (*fb_release)(struct fb_info *info, int user);
+ /* get non settable parameters */
+ int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+ /* get settable parameters */
+ int (*fb_get_var)(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+ /* set settable parameters */
+ int (*fb_set_var)(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+ /* get colormap */
+ int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+ /* set colormap */
+ int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+ /* pan display */
+ int (*fb_pan_display)(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+ /* perform fb specific ioctl */
+ int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info);
+ /* perform fb specific mmap */
+ int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
+ /* switch to/from raster image mode */
+ int (*fb_rasterimg)(struct fb_info *info, int start);
+};
+
+
+ /*
+ * This is the interface between the low-level console driver and the
+ * low-level frame buffer device
+ */
+
+struct display {
+ /* Filled in by the frame buffer device */
+
+ struct fb_var_screeninfo var; /* variable infos. yoffset and vmode */
+ /* are updated by fbcon.c */
+ struct fb_cmap cmap; /* colormap */
+ char *screen_base; /* pointer to top of virtual screen */
+ /* (virtual address) */
+ int visual;
+ int type; /* see FB_TYPE_* */
+ int type_aux; /* Interleave for interleaved Planes */
+ u_short ypanstep; /* zero if no hardware ypan */
+ u_short ywrapstep; /* zero if no hardware ywrap */
+ u_long line_length; /* length of a line in bytes */
+ u_short can_soft_blank; /* zero if no hardware blanking */
+ u_short inverse; /* != 0 text black on white as default */
+ struct display_switch *dispsw; /* low level operations */
+ void *dispsw_data; /* optional dispsw helper data */
+
+#if 0
+ struct fb_fix_cursorinfo fcrsr;
+ struct fb_var_cursorinfo *vcrsr;
+ struct fb_cursorstate crsrstate;
+#endif
+
+ /* Filled in by the low-level console driver */
+
+ struct vc_data *conp; /* pointer to console data */
+ struct fb_info *fb_info; /* frame buffer for this console */
+ int vrows; /* number of virtual rows */
+ unsigned short cursor_x; /* current cursor position */
+ unsigned short cursor_y;
+ int fgcol; /* text colors */
+ int bgcol;
+ u_long next_line; /* offset to one line below */
+ u_long next_plane; /* offset to next plane */
+ u_char *fontdata; /* Font associated to this display */
+ unsigned short _fontheightlog;
+ unsigned short _fontwidthlog;
+ unsigned short _fontheight;
+ unsigned short _fontwidth;
+ int userfont; /* != 0 if fontdata kmalloc()ed */
+ u_short scrollmode; /* Scroll Method */
+ short yscroll; /* Hardware scrolling */
+ unsigned char fgshift, bgshift;
+ unsigned short charmask; /* 0xff or 0x1ff */
+};
+
+
+struct fb_info {
+ char modename[40]; /* default video mode */
+ kdev_t node;
+ int flags;
+#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */
+ struct fb_ops *fbops;
+ struct fb_monspecs monspecs;
+ struct display *disp; /* initial display variable */
+ struct vc_data *display_fg; /* Console visible on this display */
+ char fontname[40]; /* default font name */
+ int (*changevar)(int); /* tell console var has changed */
+ int (*switch_con)(int, struct fb_info*);
+ /* tell fb to switch consoles */
+ int (*updatevar)(int, struct fb_info*);
+ /* tell fb to update the vars */
+ void (*blank)(int, struct fb_info*); /* tell fb to (un)blank the screen */
+ /* arg = 0: unblank */
+ /* arg > 0: VESA level (arg-1) */
+
+ /* From here on everything is device dependent */
+};
+
+#ifdef MODULE
+#define FBINFO_FLAG_DEFAULT FBINFO_FLAG_MODULE
+#else
+#define FBINFO_FLAG_DEFAULT 0
+#endif
+
+ /*
+ * This structure abstracts from the underlying hardware. It is not
+ * mandatory but used by the `generic' frame buffer operations.
+ * Read drivers/video/skeletonfb.c for more information.
+ */
+
+struct fbgen_hwswitch {
+ void (*detect)(void);
+ int (*encode_fix)(struct fb_fix_screeninfo *fix, const void *par,
+ struct fb_info_gen *info);
+ int (*decode_var)(const struct fb_var_screeninfo *var, void *par,
+ struct fb_info_gen *info);
+ int (*encode_var)(struct fb_var_screeninfo *var, const void *par,
+ struct fb_info_gen *info);
+ void (*get_par)(void *par, struct fb_info_gen *info);
+ void (*set_par)(const void *par, struct fb_info_gen *info);
+ int (*getcolreg)(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp, struct fb_info *info);
+ int (*setcolreg)(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info);
+ int (*pan_display)(const struct fb_var_screeninfo *var,
+ struct fb_info_gen *info);
+ int (*blank)(int blank_mode, struct fb_info_gen *info);
+ void (*set_disp)(const void *par, struct display *disp,
+ struct fb_info_gen *info);
+};
+
+struct fb_info_gen {
+ struct fb_info info;
+
+ /* Entries for a generic frame buffer device */
+ /* Yes, this starts looking like C++ */
+ u_int parsize;
+ struct fbgen_hwswitch *fbhw;
+
+ /* From here on everything is device dependent */
+};
+
+ /*
+ * `Generic' versions of the frame buffer device operations
+ */
+
+extern int fbgen_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+extern int fbgen_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+extern int fbgen_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+extern int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+extern int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+extern int fbgen_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+extern int fbgen_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info);
+
+ /*
+ * Helper functions
+ */
+
+extern int fbgen_do_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info_gen *info);
+extern void fbgen_set_disp(int con, struct fb_info_gen *info);
+extern void fbgen_install_cmap(int con, struct fb_info_gen *info);
+extern int fbgen_update_var(int con, struct fb_info *info);
+extern int fbgen_switch(int con, struct fb_info *info);
+extern void fbgen_blank(int blank, struct fb_info *info);
+
+
+struct fb_videomode {
+ const char *name;
+ struct fb_var_screeninfo var;
+};
+
+
+/* drivers/char/fbmem.c */
+extern int register_framebuffer(struct fb_info *fb_info);
+extern int unregister_framebuffer(const struct fb_info *fb_info);
+extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
+ const struct fb_info *fb_info);
+extern int fbmon_dpms(const struct fb_info *fb_info);
+
+
+extern int num_registered_fb;
+extern struct fb_info *registered_fb[FB_MAX];
+extern char con2fb_map[MAX_NR_CONSOLES];
+
+/* drivers/video/fbcon.c */
+extern struct display fb_display[MAX_NR_CONSOLES];
+
+/* drivers/video/fbcmap.c */
+extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
+extern void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to,
+ int fsfromto);
+extern int fb_get_cmap(struct fb_cmap *cmap, int kspc,
+ int (*getcolreg)(u_int, u_int *, u_int *, u_int *,
+ u_int *, struct fb_info *),
+ struct fb_info *fb_info);
+extern int fb_set_cmap(struct fb_cmap *cmap, int kspc,
+ int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,
+ struct fb_info *),
+ struct fb_info *fb_info);
+extern struct fb_cmap *fb_default_cmap(int len);
+extern void fb_invert_cmaps(void);
+
+/* VESA Blanking Levels */
+#define VESA_NO_BLANKING 0
+#define VESA_VSYNC_SUSPEND 1
+#define VESA_HSYNC_SUSPEND 2
+#define VESA_POWERDOWN 3
+
+#endif /* __KERNEL__ */
+
+#if 1
+
+#define FBCMD_GET_CURRENTPAR 0xDEAD0005
+#define FBCMD_SET_CURRENTPAR 0xDEAD8005
+
+#endif
+
+
+#if 1 /* Preliminary */
+
+ /*
+ * Hardware Cursor
+ */
+
+#define FBIOGET_FCURSORINFO 0x4607
+#define FBIOGET_VCURSORINFO 0x4608
+#define FBIOPUT_VCURSORINFO 0x4609
+#define FBIOGET_CURSORSTATE 0x460A
+#define FBIOPUT_CURSORSTATE 0x460B
+
+
+struct fb_fix_cursorinfo {
+ __u16 crsr_width; /* width and height of the cursor in */
+ __u16 crsr_height; /* pixels (zero if no cursor) */
+ __u16 crsr_xsize; /* cursor size in display pixels */
+ __u16 crsr_ysize;
+ __u16 crsr_color1; /* colormap entry for cursor color1 */
+ __u16 crsr_color2; /* colormap entry for cursor color2 */
+};
+
+struct fb_var_cursorinfo {
+ __u16 width;
+ __u16 height;
+ __u16 xspot;
+ __u16 yspot;
+ __u8 data[1]; /* field with [height][width] */
+};
+
+struct fb_cursorstate {
+ __s16 xoffset;
+ __s16 yoffset;
+ __u16 mode;
+};
+
+#define FB_CURSOR_OFF 0
+#define FB_CURSOR_ON 1
+#define FB_CURSOR_FLASH 2
+
+#endif /* Preliminary */
+
+#endif /* _LINUX_FB_H */
diff --git a/pfinet/linux-src/include/linux/fcdevice.h b/pfinet/linux-src/include/linux/fcdevice.h
new file mode 100644
index 00000000..22a1e454
--- /dev/null
+++ b/pfinet/linux-src/include/linux/fcdevice.h
@@ -0,0 +1,40 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. NET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the Fibre Channel handlers.
+ *
+ * Version: @(#)fcdevice.h 1.0.0 09/26/98
+ *
+ * Authors: Vineet Abraham <vma@iol.unh.edu>
+ *
+ * Relocated to include/linux where it belongs by Alan Cox
+ * <gw4pts@gw4pts.ampr.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * WARNING: This move may well be temporary. This file will get merged with others RSN.
+ *
+ */
+#ifndef _LINUX_FCDEVICE_H
+#define _LINUX_FCDEVICE_H
+
+
+#include <linux/if_fc.h>
+
+#ifdef __KERNEL__
+extern int fc_header(struct sk_buff *skb, struct device *dev,
+ unsigned short type, void *daddr,
+ void *saddr, unsigned len);
+extern int fc_rebuild_header(struct sk_buff *skb);
+//extern unsigned short fc_type_trans(struct sk_buff *skb, struct device *dev);
+
+extern struct device * init_fcdev(struct device *, int);
+
+#endif
+
+#endif /* _LINUX_FCDEVICE_H */
diff --git a/pfinet/linux-src/include/linux/fcntl.h b/pfinet/linux-src/include/linux/fcntl.h
new file mode 100644
index 00000000..9de3512e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/fcntl.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_FCNTL_H
+#define _LINUX_FCNTL_H
+
+#include <asm/fcntl.h>
+
+#endif
diff --git a/pfinet/linux-src/include/linux/fd.h b/pfinet/linux-src/include/linux/fd.h
new file mode 100644
index 00000000..c0ed2792
--- /dev/null
+++ b/pfinet/linux-src/include/linux/fd.h
@@ -0,0 +1,378 @@
+#ifndef _LINUX_FD_H
+#define _LINUX_FD_H
+
+#include <linux/ioctl.h>
+
+/* New file layout: Now the ioctl definitions immediately follow the
+ * definitions of the structures that they use */
+
+/*
+ * Geometry
+ */
+struct floppy_struct {
+ unsigned int size, /* nr of sectors total */
+ sect, /* sectors per track */
+ head, /* nr of heads */
+ track, /* nr of tracks */
+ stretch; /* !=0 means double track steps */
+#define FD_STRETCH 1
+#define FD_SWAPSIDES 2
+
+ unsigned char gap, /* gap1 size */
+
+ rate, /* data rate. |= 0x40 for perpendicular */
+#define FD_2M 0x4
+#define FD_SIZECODEMASK 0x38
+#define FD_SIZECODE(floppy) (((((floppy)->rate&FD_SIZECODEMASK)>> 3)+ 2) %8)
+#define FD_SECTSIZE(floppy) ( (floppy)->rate & FD_2M ? \
+ 512 : 128 << FD_SIZECODE(floppy) )
+#define FD_PERP 0x40
+
+ spec1, /* stepping rate, head unload time */
+ fmt_gap; /* gap2 size */
+ const char * name; /* used only for predefined formats */
+};
+
+
+/* commands needing write access have 0x40 set */
+/* commands needing super user access have 0x80 set */
+
+#define FDCLRPRM _IO(2, 0x41)
+/* clear user-defined parameters */
+
+#define FDSETPRM _IOW(2, 0x42, struct floppy_struct)
+#define FDSETMEDIAPRM FDSETPRM
+/* set user-defined parameters for current media */
+
+#define FDDEFPRM _IOW(2, 0x43, struct floppy_struct)
+#define FDGETPRM _IOR(2, 0x04, struct floppy_struct)
+#define FDDEFMEDIAPRM FDDEFPRM
+#define FDGETMEDIAPRM FDGETPRM
+/* set/get disk parameters */
+
+
+#define FDMSGON _IO(2,0x45)
+#define FDMSGOFF _IO(2,0x46)
+/* issue/don't issue kernel messages on media type change */
+
+
+/*
+ * Formatting (obsolete)
+ */
+#define FD_FILL_BYTE 0xF6 /* format fill byte. */
+
+struct format_descr {
+ unsigned int device,head,track;
+};
+
+#define FDFMTBEG _IO(2,0x47)
+/* begin formatting a disk */
+#define FDFMTTRK _IOW(2,0x48, struct format_descr)
+/* format the specified track */
+#define FDFMTEND _IO(2,0x49)
+/* end formatting a disk */
+
+
+/*
+ * Error thresholds
+ */
+struct floppy_max_errors {
+ unsigned int
+ abort, /* number of errors to be reached before aborting */
+ read_track, /* maximal number of errors permitted to read an
+ * entire track at once */
+ reset, /* maximal number of errors before a reset is tried */
+ recal, /* maximal number of errors before a recalibrate is
+ * tried */
+
+ /*
+ * Threshold for reporting FDC errors to the console.
+ * Setting this to zero may flood your screen when using
+ * ultra cheap floppies ;-)
+ */
+ reporting;
+
+};
+
+#define FDSETEMSGTRESH _IO(2,0x4a)
+/* set fdc error reporting threshold */
+
+#define FDFLUSH _IO(2,0x4b)
+/* flush buffers for media; either for verifying media, or for
+ * handling a media change without closing the file descriptor */
+
+#define FDSETMAXERRS _IOW(2, 0x4c, struct floppy_max_errors)
+#define FDGETMAXERRS _IOR(2, 0x0e, struct floppy_max_errors)
+/* set/get abortion and read_track threshold. See also floppy_drive_params
+ * structure */
+
+
+typedef char floppy_drive_name[16];
+#define FDGETDRVTYP _IOR(2, 0x0f, floppy_drive_name)
+/* get drive type: 5 1/4 or 3 1/2 */
+
+
+/*
+ * Drive parameters (user modifiable)
+ */
+struct floppy_drive_params {
+ signed char cmos; /* CMOS type */
+
+ /* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms
+ * etc) and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
+ */
+ unsigned long max_dtr; /* Step rate, usec */
+ unsigned long hlt; /* Head load/settle time, msec */
+ unsigned long hut; /* Head unload time (remnant of
+ * 8" drives) */
+ unsigned long srt; /* Step rate, usec */
+
+ unsigned long spinup; /* time needed for spinup (expressed
+ * in jiffies) */
+ unsigned long spindown; /* timeout needed for spindown */
+ unsigned char spindown_offset; /* decides in which position the disk
+ * will stop */
+ unsigned char select_delay; /* delay to wait after select */
+ unsigned char rps; /* rotations per second */
+ unsigned char tracks; /* maximum number of tracks */
+ unsigned long timeout; /* timeout for interrupt requests */
+
+ unsigned char interleave_sect; /* if there are more sectors, use
+ * interleave */
+
+ struct floppy_max_errors max_errors;
+
+ char flags; /* various flags, including ftd_msg */
+/*
+ * Announce successful media type detection and media information loss after
+ * disk changes.
+ * Also used to enable/disable printing of overrun warnings.
+ */
+
+#define FTD_MSG 0x10
+#define FD_BROKEN_DCL 0x20
+#define FD_DEBUG 0x02
+#define FD_SILENT_DCL_CLEAR 0x4
+#define FD_INVERTED_DCL 0x80 /* must be 0x80, because of hardware
+ considerations */
+
+ char read_track; /* use readtrack during probing? */
+
+/*
+ * Auto-detection. Each drive type has eight formats which are
+ * used in succession to try to read the disk. If the FDC cannot lock onto
+ * the disk, the next format is tried. This uses the variable 'probing'.
+ */
+ short autodetect[8]; /* autodetected formats */
+
+ int checkfreq; /* how often should the drive be checked for disk
+ * changes */
+ int native_format; /* native format of this drive */
+};
+
+enum {
+ FD_NEED_TWADDLE_BIT, /* more magic */
+ FD_VERIFY_BIT, /* inquire for write protection */
+ FD_DISK_NEWCHANGE_BIT, /* change detected, and no action undertaken yet
+ * to clear media change status */
+ FD_UNUSED_BIT,
+ FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */
+ FD_DISK_WRITABLE_BIT /* disk is writable */
+};
+
+#define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params)
+#define FDGETDRVPRM _IOR(2, 0x11, struct floppy_drive_params)
+/* set/get drive parameters */
+
+
+/*
+ * Current drive state (not directly modifiable by user, readonly)
+ */
+struct floppy_drive_struct {
+ unsigned long flags;
+/* values for these flags */
+#define FD_NEED_TWADDLE (1 << FD_NEED_TWADDLE_BIT)
+#define FD_VERIFY (1 << FD_VERIFY_BIT)
+#define FD_DISK_NEWCHANGE (1 << FD_DISK_NEWCHANGE_BIT)
+#define FD_DISK_CHANGED (1 << FD_DISK_CHANGED_BIT)
+#define FD_DISK_WRITABLE (1 << FD_DISK_WRITABLE_BIT)
+
+ unsigned long spinup_date;
+ unsigned long select_date;
+ unsigned long first_read_date;
+ short probed_format;
+ short track; /* current track */
+ short maxblock; /* id of highest block read */
+ short maxtrack; /* id of highest half track read */
+ int generation; /* how many diskchanges? */
+
+/*
+ * (User-provided) media information is _not_ discarded after a media change
+ * if the corresponding keep_data flag is non-zero. Positive values are
+ * decremented after each probe.
+ */
+ int keep_data;
+
+ /* Prevent "aliased" accesses. */
+ int fd_ref;
+ int fd_device;
+ unsigned long last_checked; /* when was the drive last checked for a disk
+ * change? */
+
+ char *dmabuf;
+ int bufblocks;
+};
+
+#define FDGETDRVSTAT _IOR(2, 0x12, struct floppy_drive_struct)
+#define FDPOLLDRVSTAT _IOR(2, 0x13, struct floppy_drive_struct)
+/* get drive state: GET returns the cached state, POLL polls for new state */
+
+
+/*
+ * reset FDC
+ */
+enum reset_mode {
+ FD_RESET_IF_NEEDED, /* reset only if the reset flags is set */
+ FD_RESET_IF_RAWCMD, /* obsolete */
+ FD_RESET_ALWAYS /* reset always */
+};
+#define FDRESET _IO(2, 0x54)
+
+
+/*
+ * FDC state
+ */
+struct floppy_fdc_state {
+ int spec1; /* spec1 value last used */
+ int spec2; /* spec2 value last used */
+ int dtr;
+ unsigned char version; /* FDC version code */
+ unsigned char dor;
+ unsigned long address; /* io address */
+ unsigned int rawcmd:2;
+ unsigned int reset:1;
+ unsigned int need_configure:1;
+ unsigned int perp_mode:2;
+ unsigned int has_fifo:1;
+ unsigned int driver_version; /* version code for floppy driver */
+#define FD_DRIVER_VERSION 0x100
+/* user programs using the floppy API should use floppy_fdc_state to
+ * get the version number of the floppy driver that they are running
+ * on. If this version number is bigger than the one compiled into the
+ * user program (the FD_DRIVER_VERSION define), it should be prepared
+ * to bigger structures
+ */
+
+ unsigned char track[4];
+ /* Position of the heads of the 4 units attached to this FDC,
+ * as stored on the FDC. In the future, the position as stored
+ * on the FDC might not agree with the actual physical
+ * position of these drive heads. By allowing such
+ * disagreement, it will be possible to reset the FDC without
+ * incurring the expensive cost of repositioning all heads.
+ * Right now, these positions are hard wired to 0. */
+
+};
+
+#define FDGETFDCSTAT _IOR(2, 0x15, struct floppy_fdc_state)
+
+
+/*
+ * Asynchronous Write error tracking
+ */
+struct floppy_write_errors {
+ /* Write error logging.
+ *
+ * These fields can be cleared with the FDWERRORCLR ioctl.
+ * Only writes that were attempted but failed due to a physical media
+ * error are logged. write(2) calls that fail and return an error code
+ * to the user process are not counted.
+ */
+
+ unsigned int write_errors; /* number of physical write errors
+ * encountered */
+
+ /* position of first and last write errors */
+ unsigned long first_error_sector;
+ int first_error_generation;
+ unsigned long last_error_sector;
+ int last_error_generation;
+
+ unsigned int badness; /* highest retry count for a read or write
+ * operation */
+};
+
+#define FDWERRORCLR _IO(2, 0x56)
+/* clear write error and badness information */
+#define FDWERRORGET _IOR(2, 0x17, struct floppy_write_errors)
+/* get write error and badness information */
+
+
+/*
+ * Raw commands
+ */
+/* new interface flag: now we can do them in batches */
+#define FDHAVEBATCHEDRAWCMD
+
+struct floppy_raw_cmd {
+ unsigned int flags;
+#define FD_RAW_READ 1
+#define FD_RAW_WRITE 2
+#define FD_RAW_NO_MOTOR 4
+#define FD_RAW_DISK_CHANGE 4 /* out: disk change flag was set */
+#define FD_RAW_INTR 8 /* wait for an interrupt */
+#define FD_RAW_SPIN 0x10 /* spin up the disk for this command */
+#define FD_RAW_NO_MOTOR_AFTER 0x20 /* switch the motor off after command
+ * completion */
+#define FD_RAW_NEED_DISK 0x40 /* this command needs a disk to be present */
+#define FD_RAW_NEED_SEEK 0x80 /* this command uses an implied seek (soft) */
+
+/* more "in" flags */
+#define FD_RAW_MORE 0x100 /* more records follow */
+#define FD_RAW_STOP_IF_FAILURE 0x200 /* stop if we encounter a failure */
+#define FD_RAW_STOP_IF_SUCCESS 0x400 /* stop if command successful */
+#define FD_RAW_SOFTFAILURE 0x800 /* consider the return value for failure
+ * detection too */
+
+/* more "out" flags */
+#define FD_RAW_FAILURE 0x10000 /* command sent to fdc, fdc returned error */
+#define FD_RAW_HARDFAILURE 0x20000 /* fdc had to be reset, or timed out */
+
+ void *data;
+ char *kernel_data; /* location of data buffer in the kernel */
+ struct floppy_raw_cmd *next; /* used for chaining of raw cmd's
+ * within the kernel */
+ long length; /* in: length of dma transfer. out: remaining bytes */
+ long phys_length; /* physical length, if different from dma length */
+ int buffer_length; /* length of allocated buffer */
+
+ unsigned char rate;
+ unsigned char cmd_count;
+ unsigned char cmd[16];
+ unsigned char reply_count;
+ unsigned char reply[16];
+ int track;
+ int resultcode;
+
+ int reserved1;
+ int reserved2;
+};
+
+#define FDRAWCMD _IO(2, 0x58)
+/* send a raw command to the fdc. Structure size not included, because of
+ * batches */
+
+#define FDTWADDLE _IO(2, 0x59)
+/* flicker motor-on bit before reading a sector. Experimental */
+
+
+#define FDEJECT _IO(2, 0x5a)
+/* eject the disk */
+
+
+#ifdef __KERNEL__
+/* eject the boot floppy (if we need the drive for a different root floppy) */
+void floppy_eject(void);
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/fddidevice.h b/pfinet/linux-src/include/linux/fddidevice.h
new file mode 100644
index 00000000..a093ccf7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/fddidevice.h
@@ -0,0 +1,39 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the FDDI handlers.
+ *
+ * Version: @(#)fddidevice.h 1.0.0 08/12/96
+ *
+ * Author: Lawrence V. Stefani, <stefani@lkg.dec.com>
+ *
+ * fddidevice.h is based on previous trdevice.h work by
+ * Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_FDDIDEVICE_H
+#define _LINUX_FDDIDEVICE_H
+
+#include <linux/if_fddi.h>
+
+#ifdef __KERNEL__
+extern int fddi_header(struct sk_buff *skb,
+ struct device *dev,
+ unsigned short type,
+ void *daddr,
+ void *saddr,
+ unsigned len);
+extern int fddi_rebuild_header(struct sk_buff *skb);
+extern unsigned short fddi_type_trans(struct sk_buff *skb,
+ struct device *dev);
+#endif
+
+#endif /* _LINUX_FDDIDEVICE_H */
diff --git a/pfinet/linux-src/include/linux/fdreg.h b/pfinet/linux-src/include/linux/fdreg.h
new file mode 100644
index 00000000..1d9026ee
--- /dev/null
+++ b/pfinet/linux-src/include/linux/fdreg.h
@@ -0,0 +1,143 @@
+#ifndef _LINUX_FDREG_H
+#define _LINUX_FDREG_H
+/*
+ * This file contains some defines for the floppy disk controller.
+ * Various sources. Mostly "IBM Microcomputers: A Programmers
+ * Handbook", Sanches and Canton.
+ */
+
+#ifdef FDPATCHES
+
+#define FD_IOPORT fdc_state[fdc].address
+
+/* Fd controller regs. S&C, about page 340 */
+#define FD_STATUS (4 + FD_IOPORT )
+#define FD_DATA (5 + FD_IOPORT )
+
+/* Digital Output Register */
+#define FD_DOR (2 + FD_IOPORT )
+
+/* Digital Input Register (read) */
+#define FD_DIR (7 + FD_IOPORT )
+
+/* Diskette Control Register (write)*/
+#define FD_DCR (7 + FD_IOPORT )
+
+#else
+
+#define FD_STATUS 0x3f4
+#define FD_DATA 0x3f5
+#define FD_DOR 0x3f2 /* Digital Output Register */
+#define FD_DIR 0x3f7 /* Digital Input Register (read) */
+#define FD_DCR 0x3f7 /* Diskette Control Register (write)*/
+
+#endif
+
+/* Bits of main status register */
+#define STATUS_BUSYMASK 0x0F /* drive busy mask */
+#define STATUS_BUSY 0x10 /* FDC busy */
+#define STATUS_DMA 0x20 /* 0- DMA mode */
+#define STATUS_DIR 0x40 /* 0- cpu->fdc */
+#define STATUS_READY 0x80 /* Data reg ready */
+
+/* Bits of FD_ST0 */
+#define ST0_DS 0x03 /* drive select mask */
+#define ST0_HA 0x04 /* Head (Address) */
+#define ST0_NR 0x08 /* Not Ready */
+#define ST0_ECE 0x10 /* Equipment check error */
+#define ST0_SE 0x20 /* Seek end */
+#define ST0_INTR 0xC0 /* Interrupt code mask */
+
+/* Bits of FD_ST1 */
+#define ST1_MAM 0x01 /* Missing Address Mark */
+#define ST1_WP 0x02 /* Write Protect */
+#define ST1_ND 0x04 /* No Data - unreadable */
+#define ST1_OR 0x10 /* OverRun */
+#define ST1_CRC 0x20 /* CRC error in data or addr */
+#define ST1_EOC 0x80 /* End Of Cylinder */
+
+/* Bits of FD_ST2 */
+#define ST2_MAM 0x01 /* Missing Address Mark (again) */
+#define ST2_BC 0x02 /* Bad Cylinder */
+#define ST2_SNS 0x04 /* Scan Not Satisfied */
+#define ST2_SEH 0x08 /* Scan Equal Hit */
+#define ST2_WC 0x10 /* Wrong Cylinder */
+#define ST2_CRC 0x20 /* CRC error in data field */
+#define ST2_CM 0x40 /* Control Mark = deleted */
+
+/* Bits of FD_ST3 */
+#define ST3_HA 0x04 /* Head (Address) */
+#define ST3_DS 0x08 /* drive is double-sided */
+#define ST3_TZ 0x10 /* Track Zero signal (1=track 0) */
+#define ST3_RY 0x20 /* drive is ready */
+#define ST3_WP 0x40 /* Write Protect */
+#define ST3_FT 0x80 /* Drive Fault */
+
+/* Values for FD_COMMAND */
+#define FD_RECALIBRATE 0x07 /* move to track 0 */
+#define FD_SEEK 0x0F /* seek track */
+#define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */
+#define FD_WRITE 0xC5 /* write with MT, MFM */
+#define FD_SENSEI 0x08 /* Sense Interrupt Status */
+#define FD_SPECIFY 0x03 /* specify HUT etc */
+#define FD_FORMAT 0x4D /* format one track */
+#define FD_VERSION 0x10 /* get version code */
+#define FD_CONFIGURE 0x13 /* configure FIFO operation */
+#define FD_PERPENDICULAR 0x12 /* perpendicular r/w mode */
+#define FD_GETSTATUS 0x04 /* read ST3 */
+#define FD_DUMPREGS 0x0E /* dump the contents of the fdc regs */
+#define FD_READID 0xEA /* prints the header of a sector */
+#define FD_UNLOCK 0x14 /* Fifo config unlock */
+#define FD_LOCK 0x94 /* Fifo config lock */
+#define FD_RSEEK_OUT 0x8f /* seek out (i.e. to lower tracks) */
+#define FD_RSEEK_IN 0xcf /* seek in (i.e. to higher tracks) */
+
+/* the following commands are new in the 82078. They are not used in the
+ * floppy driver, except the first three. These commands may be useful for apps
+ * which use the FDRAWCMD interface. For doc, get the 82078 spec sheets at
+ * http://www-techdoc.intel.com/docs/periph/fd_contr/datasheets/ */
+
+#define FD_PARTID 0x18 /* part id ("extended" version cmd) */
+#define FD_SAVE 0x2e /* save fdc regs for later restore */
+#define FD_DRIVESPEC 0x8e /* drive specification: Access to the
+ * 2 Mbps data transfer rate for tape
+ * drives */
+
+#define FD_RESTORE 0x4e /* later restore */
+#define FD_POWERDOWN 0x27 /* configure FDC's powersave features */
+#define FD_FORMAT_N_WRITE 0xef /* format and write in one go. */
+#define FD_OPTION 0x33 /* ISO format (which is a clean way to
+ * pack more sectors on a track) */
+
+/* DMA commands */
+#define DMA_READ 0x46
+#define DMA_WRITE 0x4A
+
+/* FDC version return types */
+#define FDC_NONE 0x00
+#define FDC_UNKNOWN 0x10 /* DO NOT USE THIS TYPE EXCEPT IF IDENTIFICATION
+ FAILS EARLY */
+#define FDC_8272A 0x20 /* Intel 8272a, NEC 765 */
+#define FDC_765ED 0x30 /* Non-Intel 1MB-compatible FDC, can't detect */
+#define FDC_82072 0x40 /* Intel 82072; 8272a + FIFO + DUMPREGS */
+#define FDC_82072A 0x45 /* 82072A (on Sparcs) */
+#define FDC_82077_ORIG 0x51 /* Original version of 82077AA, sans LOCK */
+#define FDC_82077 0x52 /* 82077AA-1 */
+#define FDC_82078_UNKN 0x5f /* Unknown 82078 variant */
+#define FDC_82078 0x60 /* 44pin 82078 or 64pin 82078SL */
+#define FDC_82078_1 0x61 /* 82078-1 (2Mbps fdc) */
+#define FDC_S82078B 0x62 /* S82078B (first seen on Adaptec AVA-2825 VLB
+ * SCSI/EIDE/Floppy controller) */
+#define FDC_87306 0x63 /* National Semiconductor PC 87306 */
+
+/*
+ * Beware: the fdc type list is roughly sorted by increasing features.
+ * Presence of features is tested by comparing the FDC version id with the
+ * "oldest" version that has the needed feature.
+ * If during FDC detection, an obscure test fails late in the sequence, don't
+ * assign FDC_UNKNOWN. Else the FDC will be treated as a dumb 8272a, or worse.
+ * This is especially true if the tests are unneeded.
+ */
+
+#define FD_RESET_DELAY 20
+#endif
diff --git a/pfinet/linux-src/include/linux/file.h b/pfinet/linux-src/include/linux/file.h
new file mode 100644
index 00000000..05f388f0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/file.h
@@ -0,0 +1,71 @@
+/*
+ * Wrapper functions for accessing the file_struct fd array.
+ */
+
+#ifndef __LINUX_FILE_H
+#define __LINUX_FILE_H
+
+extern void __fput(struct file *);
+
+/*
+ * Check whether the specified task has the fd open. Since the task
+ * may not have a files_struct, we must test for p->files != NULL.
+ */
+extern inline struct file * fcheck_task(struct task_struct *p, unsigned int fd)
+{
+ struct file * file = NULL;
+
+ if (p->files && fd < p->files->max_fds)
+ file = p->files->fd[fd];
+ return file;
+}
+
+/*
+ * Check whether the specified fd has an open file.
+ */
+extern inline struct file * fcheck(unsigned int fd)
+{
+ struct file * file = NULL;
+
+ if (fd < current->files->max_fds)
+ file = current->files->fd[fd];
+ return file;
+}
+
+extern inline struct file * fget(unsigned int fd)
+{
+ struct file * file = fcheck(fd);
+
+ if (file)
+ file->f_count++;
+ return file;
+}
+
+/*
+ * Install a file pointer in the fd array.
+ */
+extern inline void fd_install(unsigned int fd, struct file *file)
+{
+ current->files->fd[fd] = file;
+}
+
+/*
+ * 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
+ *
+ * Since those functions where calling other functions, it was compleatly
+ * bogous to make them all "extern inline".
+ *
+ * The removal of this pseudo optimization saved me scandaleous:
+ *
+ * 3756 (i386 arch)
+ *
+ * precious bytes from my kernel, even without counting all the code compiled
+ * as module!
+ *
+ * I suspect there are many other similar "optimizations" across the
+ * kernel...
+ */
+extern void fput(struct file *file);
+extern void put_filp(struct file *file);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/filter.h b/pfinet/linux-src/include/linux/filter.h
new file mode 100644
index 00000000..58ad8b1b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/filter.h
@@ -0,0 +1,140 @@
+/*
+ * Linux Socket Filter Data Structures
+ */
+
+#ifndef __LINUX_FILTER_H__
+#define __LINUX_FILTER_H__
+
+/*
+ * Current version of the filter code architecture.
+ */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+/*
+ * Try and keep these values and structures similar to BSD, especially
+ * the BPF code definitions which need to match so you can share filters
+ */
+
+struct sock_filter /* Filter block */
+{
+ __u16 code; /* Actual filter code */
+ __u8 jt; /* Jump true */
+ __u8 jf; /* Jump false */
+ __u32 k; /* Generic multiuse field */
+};
+
+struct sock_fprog /* Required for SO_ATTACH_FILTER. */
+{
+ unsigned short len; /* Number of filter blocks */
+ struct sock_filter *filter;
+};
+
+#ifdef __KERNEL__
+struct sk_filter
+{
+ atomic_t refcnt;
+ unsigned int len; /* Number of filter blocks */
+ struct sock_filter insns[0];
+};
+
+extern __inline__ unsigned int sk_filter_len(struct sk_filter *fp)
+{
+ return fp->len*sizeof(struct sock_filter) + sizeof(*fp);
+}
+#endif
+
+/*
+ * Instruction classes
+ */
+
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+#ifndef BPF_MAXINSNS
+#define BPF_MAXINSNS 4096
+#endif
+
+/*
+ * Macros for filter block array initializers.
+ */
+#ifndef BPF_STMT
+#define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
+#endif
+#ifndef BPF_JUMP
+#define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
+#endif
+
+/*
+ * Number of scratch memory words for: BPF_ST and BPF_STX
+ */
+#define BPF_MEMWORDS 16
+
+/* RATIONALE. Negative offsets are invalid in BPF.
+ We use them to reference ancillary data.
+ Unlike introduction new instructions, it does not break
+ existing compilers/optimizers.
+ */
+#define SKF_AD_OFF (-0x1000)
+#define SKF_AD_PROTOCOL 0
+#define SKF_AD_PKTTYPE 4
+#define SKF_AD_IFINDEX 8
+#define SKF_AD_MAX 12
+#define SKF_NET_OFF (-0x100000)
+#define SKF_LL_OFF (-0x200000)
+
+#ifdef __KERNEL__
+extern int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
+extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
+#endif /* __KERNEL__ */
+
+#endif /* __LINUX_FILTER_H__ */
diff --git a/pfinet/linux-src/include/linux/firewall.h b/pfinet/linux-src/include/linux/firewall.h
new file mode 100644
index 00000000..1747f381
--- /dev/null
+++ b/pfinet/linux-src/include/linux/firewall.h
@@ -0,0 +1,61 @@
+#ifndef __LINUX_FIREWALL_H
+#define __LINUX_FIREWALL_H
+
+#include <linux/config.h>
+
+/*
+ * Definitions for loadable firewall modules
+ */
+
+#define FW_QUEUE 0
+#define FW_BLOCK 1
+#define FW_ACCEPT 2
+#define FW_REJECT (-1)
+#define FW_REDIRECT 3
+#define FW_MASQUERADE 4
+#define FW_SKIP 5
+
+struct firewall_ops
+{
+ struct firewall_ops *next;
+ int (*fw_forward)(struct firewall_ops *this, int pf,
+ struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+ int (*fw_input)(struct firewall_ops *this, int pf,
+ struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+ int (*fw_output)(struct firewall_ops *this, int pf,
+ struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+ /* Data falling in the second 486 cache line isn't used directly
+ during a firewall call and scan, only by insert/delete and other
+ unusual cases
+ */
+ int fw_pf; /* Protocol family */
+ int fw_priority; /* Priority of chosen firewalls */
+};
+
+#ifdef __KERNEL__
+extern int register_firewall(int pf, struct firewall_ops *fw);
+extern int unregister_firewall(int pf, struct firewall_ops *fw);
+extern void fwchain_init(void);
+#ifdef CONFIG_FIREWALL
+extern int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+#else
+extern __inline__ int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+{
+ return FW_ACCEPT;
+}
+
+extern __inline__ int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+{
+ return FW_ACCEPT;
+}
+
+extern __inline__ int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+{
+ return FW_ACCEPT;
+}
+
+#endif
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/fs.h b/pfinet/linux-src/include/linux/fs.h
new file mode 100644
index 00000000..2fd11f7b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/fs.h
@@ -0,0 +1,953 @@
+#ifndef _LINUX_FS_H
+#define _LINUX_FS_H
+
+/*
+ * This file has definitions for some important file table
+ * structures etc.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/limits.h>
+#include <linux/wait.h>
+#include <linux/types.h>
+#include <linux/vfs.h>
+#include <linux/net.h>
+#include <linux/kdev_t.h>
+#include <linux/ioctl.h>
+#include <linux/list.h>
+#include <linux/dcache.h>
+#include <linux/stat.h>
+
+#include <asm/atomic.h>
+#include <linux/bitops.h>
+#include <asm/cache.h>
+
+struct poll_table_struct;
+
+
+/*
+ * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
+ * the file limit at runtime and only root can increase the per-process
+ * nr_file rlimit, so it's safe to set up a ridiculously high absolute
+ * upper limit on files-per-process.
+ *
+ * Some programs (notably those using select()) may have to be
+ * recompiled to take full advantage of the new limits..
+ */
+
+/* Fixed constants first: */
+#undef NR_OPEN
+#define NR_OPEN (1024*1024) /* Absolute upper limit on fd num */
+#define INR_OPEN 1024 /* Initial setting for nfile rlimits */
+
+#define BLOCK_SIZE_BITS 10
+#define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
+
+/* And dynamically-tunable limits and defaults: */
+extern int max_inodes;
+extern int max_files, nr_files, nr_free_files;
+extern int max_super_blocks, nr_super_blocks;
+
+#define NR_FILE 4096 /* this can well be larger on a larger system */
+#define NR_RESERVED_FILES 10 /* reserved for root */
+#define NR_SUPER 256
+
+#define MAY_EXEC 1
+#define MAY_WRITE 2
+#define MAY_READ 4
+
+#define FMODE_READ 1
+#define FMODE_WRITE 2
+
+#define READ 0
+#define WRITE 1
+#define READA 2 /* read-ahead - don't block if no resources */
+#define WRITEA 3 /* write-ahead - don't block if no resources */
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define NIL_FILP ((struct file *)0)
+#define SEL_IN 1
+#define SEL_OUT 2
+#define SEL_EX 4
+
+/* public flags for file_system_type */
+#define FS_REQUIRES_DEV 1
+#define FS_NO_DCACHE 2 /* Only dcache the necessary things. */
+#define FS_NO_PRELIM 4 /* prevent preloading of dentries, even if
+ * FS_NO_DCACHE is not set.
+ */
+#define FS_IBASKET 8 /* FS does callback to free_ibasket() if space gets low. */
+
+/*
+ * These are the fs-independent mount-flags: up to 16 flags are supported
+ */
+#define MS_RDONLY 1 /* Mount read-only */
+#define MS_NOSUID 2 /* Ignore suid and sgid bits */
+#define MS_NODEV 4 /* Disallow access to device special files */
+#define MS_NOEXEC 8 /* Disallow program execution */
+#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
+#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
+#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
+#define S_QUOTA 128 /* Quota initialized for file/directory/symlink */
+#define S_APPEND 256 /* Append-only file */
+#define S_IMMUTABLE 512 /* Immutable file */
+#define MS_NOATIME 1024 /* Do not update access times. */
+#define MS_NODIRATIME 2048 /* Do not update directory access times */
+
+#define MS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
+ * as nfs_rename() will be cleaned up
+ */
+
+/*
+ * Flags that can be altered by MS_REMOUNT
+ */
+#define MS_RMT_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME)
+
+/*
+ * Magic mount flag number. Has to be or-ed to the flag values.
+ */
+#define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */
+#define MS_MGC_MSK 0xffff0000 /* magic flag number mask */
+
+/*
+ * Note that read-only etc flags are inode-specific: setting some file-system
+ * flags just means all the inodes inherit those flags by default. It might be
+ * possible to override it selectively if you really wanted to with some
+ * ioctl() that is not currently implemented.
+ *
+ * Exception: MS_RDONLY is always applied to the entire file system.
+ *
+ * Unfortunately, it is possible to change a filesystems flags with it mounted
+ * with files in use. This means that all of the inodes will not have their
+ * i_flags updated. Hence, i_flags no longer inherit the superblock mount
+ * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org
+ */
+#define __IS_FLG(inode,flg) (((inode)->i_sb && (inode)->i_sb->s_flags & (flg)) \
+ || (inode)->i_flags & (flg))
+
+#define IS_RDONLY(inode) (((inode)->i_sb) && ((inode)->i_sb->s_flags & MS_RDONLY))
+#define IS_NOSUID(inode) __IS_FLG(inode, MS_NOSUID)
+#define IS_NODEV(inode) __IS_FLG(inode, MS_NODEV)
+#define IS_NOEXEC(inode) __IS_FLG(inode, MS_NOEXEC)
+#define IS_SYNC(inode) __IS_FLG(inode, MS_SYNCHRONOUS)
+#define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK)
+
+#define IS_QUOTAINIT(inode) ((inode)->i_flags & S_QUOTA)
+#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
+#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
+#define IS_NOATIME(inode) __IS_FLG(inode, MS_NOATIME)
+#define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
+
+/* the read-only stuff doesn't really belong here, but any other place is
+ probably as bad and I don't want to create yet another include file. */
+
+#define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
+#define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */
+#define BLKRRPART _IO(0x12,95) /* re-read partition table */
+#define BLKGETSIZE _IO(0x12,96) /* return device size */
+#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
+#define BLKRASET _IO(0x12,98) /* Set read ahead for block device */
+#define BLKRAGET _IO(0x12,99) /* get current read ahead setting */
+#define BLKFRASET _IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */
+#define BLKFRAGET _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
+#define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
+#define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
+#define BLKSSZGET _IO(0x12,104) /* get block device sector size */
+
+#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
+#define FIBMAP _IO(0x00,1) /* bmap access */
+#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
+
+#ifdef __KERNEL__
+
+#include <asm/semaphore.h>
+#include <asm/byteorder.h>
+#include <asm/bitops.h>
+
+extern void update_atime (struct inode *inode);
+#define UPDATE_ATIME(inode) update_atime (inode)
+
+extern void buffer_init(unsigned long);
+extern void inode_init(void);
+extern void file_table_init(void);
+extern void dcache_init(void);
+
+typedef char buffer_block[BLOCK_SIZE];
+
+/* bh state bits */
+#define BH_Uptodate 0 /* 1 if the buffer contains valid data */
+#define BH_Dirty 1 /* 1 if the buffer is dirty */
+#define BH_Lock 2 /* 1 if the buffer is locked */
+#define BH_Req 3 /* 0 if the buffer has been invalidated */
+#define BH_Protected 6 /* 1 if the buffer is protected */
+#define BH_LowPrio 7 /* 1 if the buffer is lowprio */
+
+/*
+ * Try to keep the most commonly used fields in single cache lines (16
+ * bytes) to improve performance. This ordering should be
+ * particularly beneficial on 32-bit processors.
+ *
+ * We use the first 16 bytes for the data which is used in searches
+ * over the block hash lists (ie. getblk(), find_buffer() and
+ * friends).
+ *
+ * The second 16 bytes we use for lru buffer scans, as used by
+ * sync_buffers() and refill_freelist(). -- sct
+ */
+struct buffer_head {
+ /* First cache line: */
+ struct buffer_head * b_next; /* Hash queue list */
+ unsigned long b_blocknr; /* block number */
+ unsigned long b_size; /* block size */
+ kdev_t b_dev; /* device (B_FREE = free) */
+ kdev_t b_rdev; /* Real device */
+ unsigned long b_rsector; /* Real buffer location on disk */
+ struct buffer_head * b_this_page; /* circular list of buffers in one page */
+ unsigned long b_state; /* buffer state bitmap (see above) */
+ struct buffer_head * b_next_free;
+ unsigned int b_count; /* users using this block */
+
+ /* Non-performance-critical data follows. */
+ char * b_data; /* pointer to data block (1024 bytes) */
+ unsigned int b_list; /* List that this buffer appears */
+ unsigned long b_flushtime; /* Time when this (dirty) buffer
+ * should be written */
+ struct wait_queue * b_wait;
+ struct buffer_head ** b_pprev; /* doubly linked list of hash-queue */
+ struct buffer_head * b_prev_free; /* doubly linked list of buffers */
+ struct buffer_head * b_reqnext; /* request queue */
+
+ /*
+ * I/O completion
+ */
+ void (*b_end_io)(struct buffer_head *bh, int uptodate);
+ void *b_dev_id;
+};
+
+typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
+void init_buffer(struct buffer_head *bh, kdev_t dev, int block,
+ bh_end_io_t *handler, void *dev_id);
+
+static inline int buffer_uptodate(struct buffer_head * bh)
+{
+ return test_bit(BH_Uptodate, &bh->b_state);
+}
+
+static inline int buffer_dirty(struct buffer_head * bh)
+{
+ return test_bit(BH_Dirty, &bh->b_state);
+}
+
+static inline int buffer_locked(struct buffer_head * bh)
+{
+ return test_bit(BH_Lock, &bh->b_state);
+}
+
+static inline int buffer_req(struct buffer_head * bh)
+{
+ return test_bit(BH_Req, &bh->b_state);
+}
+
+static inline int buffer_protected(struct buffer_head * bh)
+{
+ return test_bit(BH_Protected, &bh->b_state);
+}
+
+#define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data))
+#define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags)
+
+#include <linux/pipe_fs_i.h>
+#include <linux/minix_fs_i.h>
+#include <linux/ext2_fs_i.h>
+#include <linux/hpfs_fs_i.h>
+#include <linux/ntfs_fs_i.h>
+#include <linux/msdos_fs_i.h>
+#include <linux/umsdos_fs_i.h>
+#include <linux/iso_fs_i.h>
+#include <linux/nfs_fs_i.h>
+#include <linux/sysv_fs_i.h>
+#include <linux/affs_fs_i.h>
+#include <linux/ufs_fs_i.h>
+#include <linux/efs_fs_i.h>
+#include <linux/coda_fs_i.h>
+#include <linux/romfs_fs_i.h>
+#include <linux/smb_fs_i.h>
+#include <linux/hfs_fs_i.h>
+#include <linux/adfs_fs_i.h>
+#include <linux/qnx4_fs_i.h>
+
+/*
+ * Attribute flags. These should be or-ed together to figure out what
+ * has been changed!
+ */
+#define ATTR_MODE 1
+#define ATTR_UID 2
+#define ATTR_GID 4
+#define ATTR_SIZE 8
+#define ATTR_ATIME 16
+#define ATTR_MTIME 32
+#define ATTR_CTIME 64
+#define ATTR_ATIME_SET 128
+#define ATTR_MTIME_SET 256
+#define ATTR_FORCE 512 /* Not a change, but a change it */
+#define ATTR_ATTR_FLAG 1024
+
+/*
+ * This is the Inode Attributes structure, used for notify_change(). It
+ * uses the above definitions as flags, to know which values have changed.
+ * Also, in this manner, a Filesystem can look at only the values it cares
+ * about. Basically, these are the attributes that the VFS layer can
+ * request to change from the FS layer.
+ *
+ * Derek Atkins <warlord@MIT.EDU> 94-10-20
+ */
+struct iattr {
+ unsigned int ia_valid;
+ umode_t ia_mode;
+ uid_t ia_uid;
+ gid_t ia_gid;
+ off_t ia_size;
+ time_t ia_atime;
+ time_t ia_mtime;
+ time_t ia_ctime;
+ unsigned int ia_attr_flags;
+};
+
+/*
+ * This is the inode attributes flag definitions
+ */
+#define ATTR_FLAG_SYNCRONOUS 1 /* Syncronous write */
+#define ATTR_FLAG_NOATIME 2 /* Don't update atime */
+#define ATTR_FLAG_APPEND 4 /* Append-only file */
+#define ATTR_FLAG_IMMUTABLE 8 /* Immutable file */
+#define ATTR_FLAG_NODIRATIME 16 /* Don't update atime for directory */
+
+/*
+ * Includes for diskquotas and mount structures.
+ */
+#include <linux/quota.h>
+#include <linux/mount.h>
+
+struct inode {
+ struct list_head i_hash;
+ struct list_head i_list;
+ struct list_head i_dentry;
+
+ unsigned long i_ino;
+ unsigned int i_count;
+ kdev_t i_dev;
+ umode_t i_mode;
+ nlink_t i_nlink;
+ uid_t i_uid;
+ gid_t i_gid;
+ kdev_t i_rdev;
+ off_t i_size;
+ time_t i_atime;
+ time_t i_mtime;
+ time_t i_ctime;
+ unsigned long i_blksize;
+ unsigned long i_blocks;
+ unsigned long i_version;
+ unsigned long i_nrpages;
+ struct semaphore i_sem;
+ struct semaphore i_atomic_write;
+ struct inode_operations *i_op;
+ struct super_block *i_sb;
+ struct wait_queue *i_wait;
+ struct file_lock *i_flock;
+ struct vm_area_struct *i_mmap;
+ struct page *i_pages;
+ struct dquot *i_dquot[MAXQUOTAS];
+
+ unsigned long i_state;
+
+ unsigned int i_flags;
+ unsigned char i_pipe;
+ unsigned char i_sock;
+
+ int i_writecount;
+ unsigned int i_attr_flags;
+ __u32 i_generation;
+ union {
+ struct pipe_inode_info pipe_i;
+ struct minix_inode_info minix_i;
+ struct ext2_inode_info ext2_i;
+ struct hpfs_inode_info hpfs_i;
+ struct ntfs_inode_info ntfs_i;
+ struct msdos_inode_info msdos_i;
+ struct umsdos_inode_info umsdos_i;
+ struct iso_inode_info isofs_i;
+ struct nfs_inode_info nfs_i;
+ struct sysv_inode_info sysv_i;
+ struct affs_inode_info affs_i;
+ struct ufs_inode_info ufs_i;
+ struct efs_inode_info efs_i;
+ struct romfs_inode_info romfs_i;
+ struct coda_inode_info coda_i;
+ struct smb_inode_info smbfs_i;
+ struct hfs_inode_info hfs_i;
+ struct adfs_inode_info adfs_i;
+ struct qnx4_inode_info qnx4_i;
+ struct socket socket_i;
+ void *generic_ip;
+ } u;
+};
+
+/* Inode state bits.. */
+#define I_DIRTY 1
+#define I_LOCK 2
+#define I_FREEING 4
+
+extern void __mark_inode_dirty(struct inode *);
+static inline void mark_inode_dirty(struct inode *inode)
+{
+ if (!(inode->i_state & I_DIRTY))
+ __mark_inode_dirty(inode);
+}
+
+struct fown_struct {
+ int pid; /* pid or -pgrp where SIGIO should be sent */
+ uid_t uid, euid; /* uid/euid of process setting the owner */
+ int signum; /* posix.1b rt signal to be delivered on IO */
+};
+
+struct file {
+ struct file *f_next, **f_pprev;
+ struct dentry *f_dentry;
+ struct file_operations *f_op;
+ mode_t f_mode;
+ loff_t f_pos;
+ unsigned int f_count, f_flags;
+ unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
+ struct fown_struct f_owner;
+ unsigned int f_uid, f_gid;
+ int f_error;
+
+ unsigned long f_version;
+
+ /* needed for tty driver, and maybe others */
+ void *private_data;
+};
+
+extern int init_private_file(struct file *, struct dentry *, int);
+
+#define FL_POSIX 1
+#define FL_FLOCK 2
+#define FL_BROKEN 4 /* broken flock() emulation */
+#define FL_ACCESS 8 /* for processes suspended by mandatory locking */
+#define FL_LOCKD 16 /* lock held by rpc.lockd */
+
+/*
+ * The POSIX file lock owner is determined by
+ * the "struct files_struct" in the thread group
+ * (or NULL for no owner - BSD locks).
+ *
+ * Lockd stuffs a "host" pointer into this.
+ */
+typedef struct files_struct *fl_owner_t;
+
+struct file_lock {
+ struct file_lock *fl_next; /* singly linked list for this inode */
+ struct file_lock *fl_nextlink; /* doubly linked list of all locks */
+ struct file_lock *fl_prevlink; /* used to simplify lock removal */
+ struct file_lock *fl_nextblock; /* circular list of blocked processes */
+ struct file_lock *fl_prevblock;
+ fl_owner_t fl_owner;
+ unsigned int fl_pid;
+ struct wait_queue *fl_wait;
+ struct file *fl_file;
+ unsigned char fl_flags;
+ unsigned char fl_type;
+ off_t fl_start;
+ off_t fl_end;
+
+ void (*fl_notify)(struct file_lock *); /* unblock callback */
+
+ union {
+ struct nfs_lock_info nfs_fl;
+ } fl_u;
+};
+
+extern struct file_lock *file_lock_table;
+
+#include <linux/fcntl.h>
+
+extern int fcntl_getlk(unsigned int fd, struct flock *l);
+extern int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l);
+
+/* fs/locks.c */
+extern void locks_remove_posix(struct file *, fl_owner_t id);
+extern void locks_remove_flock(struct file *);
+extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
+extern int posix_lock_file(struct file *, struct file_lock *, unsigned int);
+extern void posix_block_lock(struct file_lock *, struct file_lock *);
+extern void posix_unblock_lock(struct file_lock *);
+
+struct fasync_struct {
+ int magic;
+ int fa_fd;
+ struct fasync_struct *fa_next; /* singly linked list */
+ struct file *fa_file;
+};
+
+#define FASYNC_MAGIC 0x4601
+
+extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
+
+#include <linux/minix_fs_sb.h>
+#include <linux/ext2_fs_sb.h>
+#include <linux/hpfs_fs_sb.h>
+#include <linux/ntfs_fs_sb.h>
+#include <linux/msdos_fs_sb.h>
+#include <linux/iso_fs_sb.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/sysv_fs_sb.h>
+#include <linux/affs_fs_sb.h>
+#include <linux/ufs_fs_sb.h>
+#include <linux/efs_fs_sb.h>
+#include <linux/romfs_fs_sb.h>
+#include <linux/smb_fs_sb.h>
+#include <linux/hfs_fs_sb.h>
+#include <linux/adfs_fs_sb.h>
+#include <linux/qnx4_fs_sb.h>
+
+extern struct list_head super_blocks;
+
+#define sb_entry(list) list_entry((list), struct super_block, s_list)
+struct super_block {
+ struct list_head s_list; /* Keep this first */
+ kdev_t s_dev;
+ unsigned long s_blocksize;
+ unsigned char s_blocksize_bits;
+ unsigned char s_lock;
+ unsigned char s_rd_only;
+ unsigned char s_dirt;
+ struct file_system_type *s_type;
+ struct super_operations *s_op;
+ struct dquot_operations *dq_op;
+ unsigned long s_flags;
+ unsigned long s_magic;
+ unsigned long s_time;
+ struct dentry *s_root;
+ struct wait_queue *s_wait;
+
+ struct inode *s_ibasket;
+ short int s_ibasket_count;
+ short int s_ibasket_max;
+ struct list_head s_dirty; /* dirty inodes */
+
+ union {
+ struct minix_sb_info minix_sb;
+ struct ext2_sb_info ext2_sb;
+ struct hpfs_sb_info hpfs_sb;
+ struct ntfs_sb_info ntfs_sb;
+ struct msdos_sb_info msdos_sb;
+ struct isofs_sb_info isofs_sb;
+ struct nfs_sb_info nfs_sb;
+ struct sysv_sb_info sysv_sb;
+ struct affs_sb_info affs_sb;
+ struct ufs_sb_info ufs_sb;
+ struct efs_sb_info efs_sb;
+ struct romfs_sb_info romfs_sb;
+ struct smb_sb_info smbfs_sb;
+ struct hfs_sb_info hfs_sb;
+ struct adfs_sb_info adfs_sb;
+ struct qnx4_sb_info qnx4_sb;
+ void *generic_sbp;
+ } u;
+ /*
+ * The next field is for VFS *only*. No filesystems have any business
+ * even looking at it. You had been warned.
+ */
+ struct semaphore s_vfs_rename_sem; /* Kludge */
+};
+
+/*
+ * VFS helper functions..
+ */
+extern int vfs_rmdir(struct inode *, struct dentry *);
+extern int vfs_unlink(struct inode *, struct dentry *);
+extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+
+/*
+ * This is the "filldir" function type, used by readdir() to let
+ * the kernel specify what kind of dirent layout it wants to have.
+ * This allows the kernel to read directories into kernel space or
+ * to have different dirent layouts depending on the binary type.
+ */
+typedef int (*filldir_t)(void *, const char *, int, off_t, ino_t);
+
+struct file_operations {
+ loff_t (*llseek) (struct file *, loff_t, int);
+ ssize_t (*read) (struct file *, char *, size_t, loff_t *);
+ ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
+ int (*readdir) (struct file *, void *, filldir_t);
+ unsigned int (*poll) (struct file *, struct poll_table_struct *);
+ int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
+ int (*mmap) (struct file *, struct vm_area_struct *);
+ int (*open) (struct inode *, struct file *);
+ int (*flush) (struct file *);
+ int (*release) (struct inode *, struct file *);
+ int (*fsync) (struct file *, struct dentry *);
+ int (*fasync) (int, struct file *, int);
+ int (*check_media_change) (kdev_t dev);
+ int (*revalidate) (kdev_t dev);
+ int (*lock) (struct file *, int, struct file_lock *);
+};
+
+struct inode_operations {
+ struct file_operations * default_file_ops;
+ int (*create) (struct inode *,struct dentry *,int);
+ struct dentry * (*lookup) (struct inode *,struct dentry *);
+ int (*link) (struct dentry *,struct inode *,struct dentry *);
+ int (*unlink) (struct inode *,struct dentry *);
+ int (*symlink) (struct inode *,struct dentry *,const char *);
+ int (*mkdir) (struct inode *,struct dentry *,int);
+ int (*rmdir) (struct inode *,struct dentry *);
+ int (*mknod) (struct inode *,struct dentry *,int,int);
+ int (*rename) (struct inode *, struct dentry *,
+ struct inode *, struct dentry *);
+ int (*readlink) (struct dentry *, char *,int);
+ struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int);
+ int (*readpage) (struct file *, struct page *);
+ int (*writepage) (struct file *, struct page *);
+ int (*bmap) (struct inode *,int);
+ void (*truncate) (struct inode *);
+ int (*permission) (struct inode *, int);
+ int (*smap) (struct inode *,int);
+ int (*updatepage) (struct file *, struct page *, unsigned long, unsigned int, int);
+ int (*revalidate) (struct dentry *);
+};
+
+struct super_operations {
+ void (*read_inode) (struct inode *);
+ void (*write_inode) (struct inode *);
+ void (*put_inode) (struct inode *);
+ void (*delete_inode) (struct inode *);
+ int (*notify_change) (struct dentry *, struct iattr *);
+ void (*put_super) (struct super_block *);
+ void (*write_super) (struct super_block *);
+ int (*statfs) (struct super_block *, struct statfs *, int);
+ int (*remount_fs) (struct super_block *, int *, char *);
+ void (*clear_inode) (struct inode *);
+ void (*umount_begin) (struct super_block *);
+};
+
+struct dquot_operations {
+ void (*initialize) (struct inode *, short);
+ void (*drop) (struct inode *);
+ int (*alloc_block) (const struct inode *, unsigned long, uid_t, char);
+ int (*alloc_inode) (const struct inode *, unsigned long, uid_t);
+ void (*free_block) (const struct inode *, unsigned long);
+ void (*free_inode) (const struct inode *, unsigned long);
+ int (*transfer) (struct dentry *, struct iattr *, uid_t);
+};
+
+struct file_system_type {
+ const char *name;
+ int fs_flags;
+ struct super_block *(*read_super) (struct super_block *, void *, int);
+ struct file_system_type * next;
+};
+
+extern int register_filesystem(struct file_system_type *);
+extern int unregister_filesystem(struct file_system_type *);
+
+/* Return value for VFS lock functions - tells locks.c to lock conventionally
+ * REALLY kosha for root NFS and nfs_lock
+ */
+#define LOCK_USE_CLNT 1
+
+#define FLOCK_VERIFY_READ 1
+#define FLOCK_VERIFY_WRITE 2
+
+extern int locks_mandatory_locked(struct inode *inode);
+extern int locks_mandatory_area(int read_write, struct inode *inode,
+ struct file *filp, loff_t offset,
+ size_t count);
+
+extern inline int locks_verify_locked(struct inode *inode)
+{
+ /* Candidates for mandatory locking have the setgid bit set
+ * but no group execute bit - an otherwise meaningless combination.
+ */
+ if (IS_MANDLOCK(inode) &&
+ (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ return (locks_mandatory_locked(inode));
+ return (0);
+}
+
+extern inline int locks_verify_area(int read_write, struct inode *inode,
+ struct file *filp, loff_t offset,
+ size_t count)
+{
+ /* Candidates for mandatory locking have the setgid bit set
+ * but no group execute bit - an otherwise meaningless combination.
+ */
+ if (IS_MANDLOCK(inode) &&
+ (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ return (locks_mandatory_area(read_write, inode, filp, offset,
+ count));
+ return (0);
+}
+
+
+/* fs/open.c */
+
+asmlinkage int sys_open(const char *, int, int);
+asmlinkage int sys_close(unsigned int); /* yes, it's really unsigned */
+extern int do_truncate(struct dentry *, unsigned long);
+extern int get_unused_fd(void);
+extern void put_unused_fd(unsigned int);
+
+extern struct file *filp_open(const char *, int, int);
+extern int filp_close(struct file *, fl_owner_t id);
+
+extern char * getname(const char * filename);
+#define __getname() ((char *) __get_free_page(GFP_KERNEL))
+#define putname(name) free_page((unsigned long)(name))
+
+extern void kill_fasync(struct fasync_struct *fa, int sig);
+extern int register_blkdev(unsigned int, const char *, struct file_operations *);
+extern int unregister_blkdev(unsigned int major, const char * name);
+extern int blkdev_open(struct inode * inode, struct file * filp);
+extern int blkdev_release (struct inode * inode);
+extern struct file_operations def_blk_fops;
+extern struct inode_operations blkdev_inode_operations;
+
+/* fs/devices.c */
+extern int register_chrdev(unsigned int, const char *, struct file_operations *);
+extern int unregister_chrdev(unsigned int major, const char * name);
+extern int chrdev_open(struct inode * inode, struct file * filp);
+extern struct file_operations def_chr_fops;
+extern struct inode_operations chrdev_inode_operations;
+extern char * bdevname(kdev_t dev);
+extern char * cdevname(kdev_t dev);
+extern char * kdevname(kdev_t dev);
+
+
+extern void init_fifo(struct inode * inode);
+extern struct inode_operations fifo_inode_operations;
+
+/* Invalid inode operations -- fs/bad_inode.c */
+extern void make_bad_inode(struct inode * inode);
+extern int is_bad_inode(struct inode * inode);
+
+extern struct file_operations connecting_fifo_fops;
+extern struct file_operations read_fifo_fops;
+extern struct file_operations write_fifo_fops;
+extern struct file_operations rdwr_fifo_fops;
+extern struct file_operations read_pipe_fops;
+extern struct file_operations write_pipe_fops;
+extern struct file_operations rdwr_pipe_fops;
+
+extern struct file_system_type *get_fs_type(const char *name);
+
+extern int fs_may_remount_ro(struct super_block *);
+extern int fs_may_mount(kdev_t dev);
+
+extern struct file *inuse_filps;
+
+extern void refile_buffer(struct buffer_head * buf);
+extern void set_writetime(struct buffer_head * buf, int flag);
+extern int try_to_free_buffers(struct page *);
+extern void cache_drop_behind(struct buffer_head *bh);
+
+extern int nr_buffers;
+extern int buffermem;
+extern int nr_buffer_heads;
+
+#define BUF_CLEAN 0
+#define BUF_LOCKED 1 /* Buffers scheduled for write */
+#define BUF_DIRTY 2 /* Dirty buffers, not yet scheduled for write */
+#define NR_LIST 3
+
+void mark_buffer_uptodate(struct buffer_head * bh, int on);
+
+extern inline void mark_buffer_clean(struct buffer_head * bh)
+{
+ if (test_and_clear_bit(BH_Dirty, &bh->b_state)) {
+ if (bh->b_list == BUF_DIRTY)
+ refile_buffer(bh);
+ }
+}
+
+extern inline void mark_buffer_highprio(struct buffer_head * bh)
+{
+ clear_bit(BH_LowPrio, &bh->b_state);
+}
+
+extern inline void mark_buffer_lowprio(struct buffer_head * bh)
+{
+ /*
+ * dirty buffers cannot be marked lowprio.
+ */
+ if (!buffer_dirty(bh))
+ set_bit(BH_LowPrio, &bh->b_state);
+}
+
+static inline int buffer_lowprio(struct buffer_head * bh)
+{
+ return test_bit(BH_LowPrio, &bh->b_state);
+}
+
+extern inline void mark_buffer_dirty(struct buffer_head * bh, int flag)
+{
+ if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {
+ set_writetime(bh, flag);
+ if (bh->b_list != BUF_DIRTY)
+ refile_buffer(bh);
+ }
+ /*
+ * if a buffer gets marked dirty then it has to lose
+ * it's lowprio state.
+ */
+ mark_buffer_highprio(bh);
+}
+
+extern inline void mark_buffer_dirty_lowprio(struct buffer_head * bh)
+{
+ if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {
+ if (bh->b_list != BUF_DIRTY)
+ refile_buffer(bh);
+ /*
+ * Mark it lowprio only if it was not dirty before!
+ */
+ set_bit(BH_LowPrio, &bh->b_state);
+ }
+}
+
+extern int check_disk_change(kdev_t dev);
+extern int invalidate_inodes(struct super_block * sb);
+extern void invalidate_inode_pages(struct inode *);
+extern void invalidate_buffers(kdev_t dev);
+extern int floppy_is_wp(int minor);
+extern void sync_inodes(kdev_t dev);
+extern void write_inode_now(struct inode *inode);
+extern void sync_dev(kdev_t dev);
+extern int fsync_dev(kdev_t dev);
+extern void sync_supers(kdev_t dev);
+extern int bmap(struct inode * inode,int block);
+extern int notify_change(struct dentry *, struct iattr *);
+extern int permission(struct inode * inode,int mask);
+extern int get_write_access(struct inode *inode);
+extern void put_write_access(struct inode *inode);
+extern struct dentry * open_namei(const char * pathname, int flag, int mode);
+extern struct dentry * do_mknod(const char * filename, int mode, dev_t dev);
+extern int do_pipe(int *);
+
+/* fs/dcache.c -- generic fs support functions */
+extern int is_subdir(struct dentry *, struct dentry *);
+extern ino_t find_inode_number(struct dentry *, struct qstr *);
+
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define ERR_PTR(err) ((void *)((long)(err)))
+#define PTR_ERR(ptr) ((long)(ptr))
+#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000))
+
+/*
+ * The bitmask for a lookup event:
+ * - follow links at the end
+ * - require a directory
+ * - ending slashes ok even for nonexistent files
+ * - internal "there are more path compnents" flag
+ */
+#define LOOKUP_FOLLOW (1)
+#define LOOKUP_DIRECTORY (2)
+#define LOOKUP_SLASHOK (4)
+#define LOOKUP_CONTINUE (8)
+
+extern struct dentry * lookup_dentry(const char *, struct dentry *, unsigned int);
+extern struct dentry * __namei(const char *, unsigned int);
+
+#define namei(pathname) __namei(pathname, 1)
+#define lnamei(pathname) __namei(pathname, 0)
+
+extern void iput(struct inode *);
+extern struct inode * igrab(struct inode *inode);
+extern ino_t iunique(struct super_block *, ino_t);
+extern struct inode * iget(struct super_block *, unsigned long);
+extern void clear_inode(struct inode *);
+extern struct inode * get_empty_inode(void);
+
+extern void insert_inode_hash(struct inode *);
+extern void remove_inode_hash(struct inode *);
+extern struct file * get_empty_filp(void);
+extern struct buffer_head * get_hash_table(kdev_t, int, int);
+extern struct buffer_head * getblk(kdev_t, int, int);
+extern struct buffer_head * find_buffer(kdev_t dev, int block, int size);
+extern void ll_rw_block(int, int, struct buffer_head * bh[]);
+extern int is_read_only(kdev_t);
+extern int is_device_idle(kdev_t);
+extern void __brelse(struct buffer_head *);
+extern inline void brelse(struct buffer_head *buf)
+{
+ if (buf)
+ __brelse(buf);
+}
+extern void __bforget(struct buffer_head *buf);
+extern inline void bforget(struct buffer_head *buf)
+{
+ if (buf)
+ __bforget(buf);
+}
+extern void set_blocksize(kdev_t dev, int size);
+extern unsigned int get_hardblocksize(kdev_t dev);
+extern struct buffer_head * bread(kdev_t dev, int block, int size);
+extern struct buffer_head * buffer_ready (kdev_t dev, int block, int size);
+extern void bread_ahead (kdev_t dev, int block, int size);
+extern struct buffer_head * breada(kdev_t dev,int block, int size,
+ unsigned int pos, unsigned int filesize);
+extern struct buffer_head * breada_blocks(kdev_t dev,int block,
+ int size, int blocks);
+
+extern int brw_page(int, struct page *, kdev_t, int [], int, int);
+
+extern int generic_readpage(struct file *, struct page *);
+extern int generic_file_mmap(struct file *, struct vm_area_struct *);
+extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
+extern ssize_t generic_file_write(struct file *, const char*, size_t, loff_t*);
+
+extern struct super_block *get_super(kdev_t dev);
+extern void put_super(kdev_t dev);
+unsigned long generate_cluster(kdev_t dev, int b[], int size);
+unsigned long generate_cluster_swab32(kdev_t dev, int b[], int size);
+extern kdev_t ROOT_DEV;
+
+extern void show_buffers(void);
+extern void mount_root(void);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+extern kdev_t real_root_dev;
+extern int change_root(kdev_t new_root_dev,const char *put_old);
+#endif
+
+extern ssize_t char_read(struct file *, char *, size_t, loff_t *);
+extern ssize_t block_read(struct file *, char *, size_t, loff_t *);
+extern int read_ahead[];
+
+extern ssize_t char_write(struct file *, const char *, size_t, loff_t *);
+extern ssize_t block_write(struct file *, const char *, size_t, loff_t *);
+
+extern int block_fsync(struct file *, struct dentry *dir);
+extern int file_fsync(struct file *, struct dentry *dir);
+
+extern int inode_change_ok(struct inode *, struct iattr *);
+extern void inode_setattr(struct inode *, struct iattr *);
+
+extern __u32 inode_generation_count;
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/ftape-header-segment.h b/pfinet/linux-src/include/linux/ftape-header-segment.h
new file mode 100644
index 00000000..4732218f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ftape-header-segment.h
@@ -0,0 +1,122 @@
+#ifndef _FTAPE_HEADER_SEGMENT_H
+#define _FTAPE_HEADER_SEGMENT_H
+
+/*
+ * Copyright (C) 1996-1997 Claus-Justus Heine.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *
+ * $Source: /homes/cvs/ftape-stacked/include/linux/ftape-header-segment.h,v $
+ * $Revision: 1.2 $
+ * $Date: 1997/10/05 19:19:28 $
+ *
+ * This file defines some offsets into the header segment of a
+ * floppy tape cartridge. For use with the QIC-40/80/3010/3020
+ * floppy-tape driver "ftape" for Linux.
+ */
+
+#define FT_SIGNATURE 0 /* must be 0xaa55aa55 */
+#define FT_FMT_CODE 4
+#define FT_REV_LEVEL 5 /* only for QIC-80 since. Rev. L (== 0x0c) */
+#define FT_HSEG_1 6 /* first header segment, except for format code 6 */
+#define FT_HSEG_2 8 /* second header segment, except for format code 6 */
+#define FT_FRST_SEG 10 /* first data segment, except for format code 6 */
+#define FT_LAST_SEG 12 /* last data segment, except for format code 6 */
+#define FT_FMT_DATE 14 /* date and time of most recent format, see below */
+#define FT_WR_DATE 18 /* date and time of most recent write or format */
+#define FT_SPT 24 /* segments per track */
+#define FT_TPC 26 /* tracks per cartridge */
+#define FT_FHM 27 /* floppy drive head (maximum of it) */
+#define FT_FTM 28 /* floppy track max. */
+#define FT_FSM 29 /* floppy sector max. (128) */
+#define FT_LABEL 30 /* floppy tape label */
+#define FT_LABEL_DATE 74 /* date and time the tape label was written */
+#define FT_LABEL_SZ (FT_LABEL_DATE - FT_LABEL)
+#define FT_CMAP_START 78 /* starting segment of compression map */
+#define FT_FMT_ERROR 128 /* must be set to 0xff if remainder gets lost during
+ * tape format
+ */
+#define FT_SEG_CNT 130 /* number of seg. written, formatted or verified
+ * through lifetime of tape (why not read?)
+ */
+#define FT_INIT_DATE 138 /* date and time of initial tape format */
+#define FT_FMT_CNT 142 /* number of times tape has been formatted */
+#define FT_FSL_CNT 144 /* number of segments in failed sector log */
+#define FT_MK_CODE 146 /* id string of tape manufacturer */
+#define FT_LOT_CODE 190 /* tape manufacturer lot code */
+#define FT_6_HSEG_1 234 /* first header segment for format code 6 */
+#define FT_6_HSEG_2 238 /* second header segment for format code 6 */
+#define FT_6_FRST_SEG 242 /* first data segment for format code 6 */
+#define FT_6_LAST_SEG 246 /* last data segment for format code 6 */
+
+#define FT_FSL 256
+#define FT_HEADER_END 256 /* space beyond this point:
+ * format codes 2, 3 and 5:
+ * - failed sector log until byte 2047
+ * - bad sector map in the reamining part of segment
+ * format codes 4 and 6:
+ * - bad sector map starts hear
+ */
+
+
+/* value to be stored at the FT_SIGNATURE offset
+ */
+#define FT_HSEG_MAGIC 0xaa55aa55
+#define FT_D2G_MAGIC 0x82288228 /* Ditto 2GB */
+
+/* data and time encoding: */
+#define FT_YEAR_SHIFT 25
+#define FT_YEAR_MASK 0xfe000000
+#define FT_YEAR_0 1970
+#define FT_YEAR_MAX 127
+#define FT_YEAR(year) ((((year)-FT_YEAR_0)<<FT_YEAR_SHIFT)&FT_YEAR_MASK)
+
+#define FT_TIME_SHIFT 0
+#define FT_TIME_MASK 0x01FFFFFF
+#define FT_TIME_MAX 0x01ea6dff /* last second of a year */
+#define FT_TIME(mo,d,h,m,s) \
+ ((((s)+60*((m)+60*((h)+24*((d)+31*(mo))))) & FT_TIME_MASK))
+
+#define FT_TIME_STAMP(y,mo,d,h,m,s) (FT_YEAR(y) | FT_TIME(mo,d,h,m,s))
+
+/* values for the format code field */
+typedef enum {
+ fmt_normal = 2, /* QIC-80 post Rev. B 205Ft or 307Ft tape */
+ fmt_1100ft = 3, /* QIC-80 post Rev. B 1100Ft tape */
+ fmt_var = 4, /* QIC-80 post Rev. B variabel length format */
+ fmt_425ft = 5, /* QIC-80 post Rev. B 425Ft tape */
+ fmt_big = 6 /* QIC-3010/3020 variable length tape with more
+ * than 2^16 segments per tape
+ */
+} ft_format_type;
+
+/* definitions for the failed sector log */
+#define FT_FSL_SIZE (2 * FT_SECTOR_SIZE - FT_HEADER_END)
+#define FT_FSL_MAX_ENTRIES (FT_FSL_SIZE/sizeof(__u32))
+
+typedef struct ft_fsl_entry {
+ __u16 segment;
+ __u16 date;
+} __attribute__ ((packed)) ft_fsl_entry;
+
+
+/* date encoding for the failed sector log
+ * month: 1..12, day: 1..31, year: 1970..2097
+ */
+#define FT_FSL_TIME_STAMP(y,m,d) \
+ (((((y) - FT_YEAR_0)<<9)&0xfe00) | (((m)<<5)&0x01e0) | ((d)&0x001f))
+
+#endif /* _FTAPE_HEADER_SEGMENT_H */
diff --git a/pfinet/linux-src/include/linux/ftape-vendors.h b/pfinet/linux-src/include/linux/ftape-vendors.h
new file mode 100644
index 00000000..ec1a81f0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ftape-vendors.h
@@ -0,0 +1,137 @@
+#ifndef _FTAPE_VENDORS_H
+#define _FTAPE_VENDORS_H
+
+/*
+ * Copyright (C) 1993-1996 Bas Laarhoven,
+ * (C) 1996-1997 Claus-Justus Heine.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *
+ * $Source: /homes/cvs/ftape-stacked/include/linux/ftape-vendors.h,v $
+ * $Revision: 1.6 $
+ * $Date: 1997/10/09 15:38:11 $
+ *
+ * This file contains the supported drive types with their
+ * QIC-117 spec. vendor code and drive dependent configuration
+ * information.
+ */
+
+typedef enum {
+ unknown_wake_up = 0,
+ no_wake_up,
+ wake_up_colorado,
+ wake_up_mountain,
+ wake_up_insight,
+} wake_up_types;
+
+typedef struct {
+ wake_up_types wake_up; /* see wake_up_types */
+ char *name; /* Text describing the drive */
+} wakeup_method;
+
+/* Note: order of entries in WAKEUP_METHODS must be so that a variable
+ * of type wake_up_types can be used as an index in the array.
+ */
+#define WAKEUP_METHODS { \
+ { unknown_wake_up, "Unknown" }, \
+ { no_wake_up, "None" }, \
+ { wake_up_colorado, "Colorado" }, \
+ { wake_up_mountain, "Mountain" }, \
+ { wake_up_insight, "Motor-on" }, \
+}
+
+typedef struct {
+ unsigned int vendor_id; /* vendor id from drive */
+ int speed; /* maximum tape transport speed (ips) */
+ wake_up_types wake_up; /* see wake_up_types */
+ char *name; /* Text describing the drive */
+} vendor_struct;
+
+#define UNKNOWN_VENDOR (-1)
+
+#define QIC117_VENDORS { \
+/* see _vendor_struct */ \
+ { 0x00000, 82, wake_up_colorado, "Colorado DJ-10 (old)" }, \
+ { 0x00047, 90, wake_up_colorado, "Colorado DJ-10/DJ-20" }, \
+ { 0x011c2, 84, wake_up_colorado, "Colorado 700" }, \
+ { 0x011c3, 90, wake_up_colorado, "Colorado 1400" }, \
+ { 0x011c4, 84, wake_up_colorado, "Colorado DJ-10/DJ-20 (new)" }, \
+ { 0x011c5, 84, wake_up_colorado, "HP Colorado T1000" }, \
+ { 0x011c6, 90, wake_up_colorado, "HP Colorado T3000" }, \
+ { 0x00005, 45, wake_up_mountain, "Archive 5580i" }, \
+ { 0x10005, 50, wake_up_insight, "Insight 80Mb, Irwin 80SX" }, \
+ { 0x00140, 74, wake_up_mountain, "Archive S.Hornet [Identity/Escom]" }, \
+ { 0x00146, 72, wake_up_mountain, "Archive 31250Q [Escom]" }, \
+ { 0x0014a, 100, wake_up_mountain, "Archive XL9250i [Conner/Escom]" }, \
+ { 0x0014c, 98, wake_up_mountain, "Conner C250MQT" }, \
+ { 0x0014e, 80, wake_up_mountain, "Conner C250MQ" }, \
+ { 0x00150, 80, wake_up_mountain, "Conner TSM420R/TST800R" }, \
+ { 0x00152, 80, wake_up_mountain, "Conner TSM850R" }, \
+ { 0x00156, 80, wake_up_mountain, "Conner TSM850R/1700R/TST3200R" }, \
+ { 0x00180, 0, wake_up_mountain, "Summit SE 150" }, \
+ { 0x00181, 85, wake_up_mountain, "Summit SE 250, Mountain FS8000" }, \
+ { 0x001c1, 82, no_wake_up, "Wangtek 3040F" }, \
+ { 0x001c8, 64, no_wake_up, "Wangtek 3080F" }, \
+ { 0x001c8, 64, wake_up_colorado, "Wangtek 3080F" }, \
+ { 0x001ca, 67, no_wake_up, "Wangtek 3080F (new)" }, \
+ { 0x001cc, 77, wake_up_colorado, "Wangtek 3200 / Teac 700" }, \
+ { 0x001cd, 75, wake_up_colorado, "Reveal TB1400" }, \
+ { 0x00380, 85, wake_up_colorado, "Exabyte Eagle-96" }, \
+ { 0x00381, 85, wake_up_colorado, "Exabyte Eagle TR-3" }, \
+ { 0x00382, 85, wake_up_colorado, "Exabyte Eagle TR-3" }, \
+ { 0x003ce, 77, wake_up_colorado, "Teac 800" }, \
+ { 0x003cf, 0, wake_up_colorado, "Teac FT3010TR" }, \
+ { 0x08880, 64, no_wake_up, "Iomega 250, Ditto 800" }, \
+ { 0x08880, 64, wake_up_colorado, "Iomega 250, Ditto 800" }, \
+ { 0x08880, 64, wake_up_insight, "Iomega 250, Ditto 800" }, \
+ { 0x08881, 80, wake_up_colorado, "Iomega 700" }, \
+ { 0x08882, 80, wake_up_colorado, "Iomega 3200" }, \
+ { 0x08883, 80, wake_up_colorado, "Iomega DITTO 2GB" }, \
+ { 0x00021, 70, no_wake_up, "AIWA CT-803" }, \
+ { 0x004c0, 80, no_wake_up, "AIWA TD-S1600" }, \
+ { 0x00021, 0, wake_up_mountain, "COREtape QIC80" }, \
+ { 0x00441, 0, wake_up_mountain, "ComByte DoublePlay" }, \
+ { 0x00481, 127, wake_up_mountain, "PERTEC MyTape 800" }, \
+ { 0x00483, 130, wake_up_mountain, "PERTEC MyTape 3200" }, \
+ { UNKNOWN_VENDOR, 0, no_wake_up, "unknown" } \
+}
+
+#define QIC117_MAKE_CODES { \
+ { 0, "Unassigned" }, \
+ { 1, "Alloy Computer Products" }, \
+ { 2, "3M" }, \
+ { 3, "Tandberg Data" }, \
+ { 4, "Colorado" }, \
+ { 5, "Archive/Conner" }, \
+ { 6, "Mountain/Summit Memory Systems" }, \
+ { 7, "Wangtek/Rexon/Tecmar" }, \
+ { 8, "Sony" }, \
+ { 9, "Cipher Data Products" }, \
+ { 10, "Irwin Magnetic Systems" }, \
+ { 11, "Braemar" }, \
+ { 12, "Verbatim" }, \
+ { 13, "Core International" }, \
+ { 14, "Exabyte" }, \
+ { 15, "Teac" }, \
+ { 16, "Gigatek" }, \
+ { 17, "ComByte" }, \
+ { 18, "PERTEC Memories" }, \
+ { 19, "Aiwa" }, \
+ { 71, "Colorado" }, \
+ { 546, "Iomega Inc" }, \
+}
+
+#endif /* _FTAPE_VENDORS_H */
diff --git a/pfinet/linux-src/include/linux/ftape.h b/pfinet/linux-src/include/linux/ftape.h
new file mode 100644
index 00000000..a26f2e51
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ftape.h
@@ -0,0 +1,212 @@
+#ifndef _FTAPE_H
+#define _FTAPE_H
+
+/*
+ * Copyright (C) 1994-1996 Bas Laarhoven,
+ * (C) 1996-1997 Claus-Justus Heine.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *
+ * $Source: /homes/cvs/ftape-stacked/include/linux/ftape.h,v $
+ * $Revision: 1.17.6.4 $
+ * $Date: 1997/11/25 01:52:54 $
+ *
+ * This file contains global definitions, typedefs and macro's
+ * for the QIC-40/80/3010/3020 floppy-tape driver for Linux.
+ */
+
+#define FTAPE_VERSION "ftape v3.04d 25/11/97"
+
+/* this makes the Kernel version numbers readable */
+#define KERNEL_VER(major,minor,sublvl) (((major)<<16)+((minor)<<8)+(sublvl))
+
+#ifdef __KERNEL__
+#include <linux/sched.h>
+#include <linux/mm.h>
+#endif
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/config.h>
+#if LINUX_VERSION_CODE <= KERNEL_VER(1,2,13)
+typedef daddr_t __kernel_daddr_t; /* needed for mtio.h */
+#endif
+#include <linux/mtio.h>
+
+#define FT_SECTOR(x) (x+1) /* sector offset into real sector */
+#define FT_SECTOR_SIZE 1024
+#define FT_SECTORS_PER_SEGMENT 32
+#define FT_ECC_SECTORS 3
+#define FT_SEGMENT_SIZE ((FT_SECTORS_PER_SEGMENT - FT_ECC_SECTORS) * FT_SECTOR_SIZE)
+#define FT_BUFF_SIZE (FT_SECTORS_PER_SEGMENT * FT_SECTOR_SIZE)
+
+/*
+ * bits of the minor device number that define drive selection
+ * methods. Could be used one day to access multiple tape
+ * drives on the same controller.
+ */
+#define FTAPE_SEL_A 0
+#define FTAPE_SEL_B 1
+#define FTAPE_SEL_C 2
+#define FTAPE_SEL_D 3
+#define FTAPE_SEL_MASK 3
+#define FTAPE_SEL(unit) ((unit) & FTAPE_SEL_MASK)
+#define FTAPE_NO_REWIND 4 /* mask for minor nr */
+
+/* the following two may be reported when MTIOCGET is requested ... */
+typedef union {
+ struct {
+ __u8 error;
+ __u8 command;
+ } error;
+ long space;
+} ft_drive_error;
+typedef union {
+ struct {
+ __u8 drive_status;
+ __u8 drive_config;
+ __u8 tape_status;
+ } status;
+ long space;
+} ft_drive_status;
+
+#ifdef __KERNEL__
+
+#define FT_RQM_DELAY 12
+#define FT_MILLISECOND 1
+#define FT_SECOND 1000
+#define FT_FOREVER -1
+#ifndef HZ
+#error "HZ undefined."
+#endif
+#define FT_USPT (1000000/HZ) /* microseconds per tick */
+
+/* This defines the number of retries that the driver will allow
+ * before giving up (and letting a higher level handle the error).
+ */
+#ifdef TESTING
+#define FT_SOFT_RETRIES 1 /* number of low level retries */
+#define FT_RETRIES_ON_ECC_ERROR 3 /* ecc error when correcting segment */
+#else
+#define FT_SOFT_RETRIES 6 /* number of low level retries (triple) */
+#define FT_RETRIES_ON_ECC_ERROR 3 /* ecc error when correcting segment */
+#endif
+
+#ifndef THE_FTAPE_MAINTAINER
+#define THE_FTAPE_MAINTAINER "the ftape maintainer"
+#endif
+
+/* Initialize missing configuration parameters.
+ */
+#ifndef CONFIG_FT_NR_BUFFERS
+# define CONFIG_FT_NR_BUFFERS 3
+#endif
+#ifndef CONFIG_FT_FDC_THR
+# define CONFIG_FT_FDC_THR 8
+#endif
+#ifndef CONFIG_FT_FDC_MAX_RATE
+# define CONFIG_FT_FDC_MAX_RATE 2000
+#endif
+#ifndef CONFIG_FT_FDC_BASE
+# define CONFIG_FT_FDC_BASE 0
+#endif
+#ifndef CONFIG_FT_FDC_IRQ
+# define CONFIG_FT_FDC_IRQ 0
+#endif
+#ifndef CONFIG_FT_FDC_DMA
+# define CONFIG_FT_FDC_DMA 0
+#endif
+
+/* Turn some booleans into numbers.
+ */
+#ifdef CONFIG_FT_PROBE_FC10
+# undef CONFIG_FT_PROBE_FC10
+# define CONFIG_FT_PROBE_FC10 1
+#else
+# define CONFIG_FT_PROBE_FC10 0
+#endif
+#ifdef CONFIG_FT_MACH2
+# undef CONFIG_FT_MACH2
+# define CONFIG_FT_MACH2 1
+#else
+# define CONFIG_FT_MACH2 0
+#endif
+
+/* Insert default settings
+ */
+#if CONFIG_FT_PROBE_FC10 == 1
+# if CONFIG_FT_FDC_BASE == 0
+# undef CONFIG_FT_FDC_BASE
+# define CONFIG_FT_FDC_BASE 0x180
+# endif
+# if CONFIG_FT_FDC_IRQ == 0
+# undef CONFIG_FT_FDC_IRQ
+# define CONFIG_FT_FDC_IRQ 9
+# endif
+# if CONFIG_FT_FDC_DMA == 0
+# undef CONFIG_FT_FDC_DMA
+# define CONFIG_FT_FDC_DMA 3
+# endif
+#elif CONFIG_FT_MACH2 == 1 /* CONFIG_FT_PROBE_FC10 == 1 */
+# if CONFIG_FT_FDC_BASE == 0
+# undef CONFIG_FT_FDC_BASE
+# define CONFIG_FT_FDC_BASE 0x1E0
+# endif
+# if CONFIG_FT_FDC_IRQ == 0
+# undef CONFIG_FT_FDC_IRQ
+# define CONFIG_FT_FDC_IRQ 6
+# endif
+# if CONFIG_FT_FDC_DMA == 0
+# undef CONFIG_FT_FDC_DMA
+# define CONFIG_FT_FDC_DMA 2
+# endif
+#elif CONFIG_FT_ALT_FDC == 1 /* CONFIG_FT_MACH2 */
+# if CONFIG_FT_FDC_BASE == 0
+# undef CONFIG_FT_FDC_BASE
+# define CONFIG_FT_FDC_BASE 0x370
+# endif
+# if CONFIG_FT_FDC_IRQ == 0
+# undef CONFIG_FT_FDC_IRQ
+# define CONFIG_FT_FDC_IRQ 6
+# endif
+# if CONFIG_FT_FDC_DMA == 0
+# undef CONFIG_FT_FDC_DMA
+# define CONFIG_FT_FDC_DMA 2
+# endif
+#else /* CONFIG_FT_ALT_FDC */
+# if CONFIG_FT_FDC_BASE == 0
+# undef CONFIG_FT_FDC_BASE
+# define CONFIG_FT_FDC_BASE 0x3f0
+# endif
+# if CONFIG_FT_FDC_IRQ == 0
+# undef CONFIG_FT_FDC_IRQ
+# define CONFIG_FT_FDC_IRQ 6
+# endif
+# if CONFIG_FT_FDC_DMA == 0
+# undef CONFIG_FT_FDC_DMA
+# define CONFIG_FT_FDC_DMA 2
+# endif
+#endif /* standard FDC */
+
+/* some useful macro's
+ */
+#define ABS(a) ((a) < 0 ? -(a) : (a))
+#define NR_ITEMS(x) (int)(sizeof(x)/ sizeof(*x))
+
+extern int ftape_init(void);
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/genhd.h b/pfinet/linux-src/include/linux/genhd.h
new file mode 100644
index 00000000..45a6dc35
--- /dev/null
+++ b/pfinet/linux-src/include/linux/genhd.h
@@ -0,0 +1,267 @@
+#ifndef _LINUX_GENHD_H
+#define _LINUX_GENHD_H
+
+/*
+ * genhd.h Copyright (C) 1992 Drew Eckhardt
+ * Generic hard disk header file by
+ * Drew Eckhardt
+ *
+ * <drew@colorado.edu>
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/unaligned.h>
+
+#define CONFIG_MSDOS_PARTITION 1
+
+#ifdef __alpha__
+#define CONFIG_OSF_PARTITION 1
+#endif
+
+#if defined(__sparc__) || defined(CONFIG_SMD_DISKLABEL)
+#define CONFIG_SUN_PARTITION 1
+#endif
+
+#if defined(CONFIG_SGI)
+#define CONFIG_SGI_PARTITION 1
+#endif
+
+/* These three have identical behaviour; use the second one if DOS fdisk gets
+ confused about extended/logical partitions starting past cylinder 1023. */
+#define DOS_EXTENDED_PARTITION 5
+#define LINUX_EXTENDED_PARTITION 0x85
+#define WIN98_EXTENDED_PARTITION 0x0f
+
+#define LINUX_SWAP_PARTITION 0x82
+#define LINUX_RAID_PARTITION 0xfd /* autodetect RAID partition */
+#define LINUX_OLD_RAID_PARTITION 0x86
+
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+#define SOLARIS_X86_PARTITION LINUX_SWAP_PARTITION
+#endif
+
+#define DM6_PARTITION 0x54 /* has DDO: use xlated geom & offset */
+#define EZD_PARTITION 0x55 /* EZ-DRIVE: same as DM6 (we think) */
+#define DM6_AUX1PARTITION 0x51 /* no DDO: use xlated geom */
+#define DM6_AUX3PARTITION 0x53 /* no DDO: use xlated geom */
+
+
+struct partition {
+ unsigned char boot_ind; /* 0x80 - active */
+ unsigned char head; /* starting head */
+ unsigned char sector; /* starting sector */
+ unsigned char cyl; /* starting cylinder */
+ unsigned char sys_ind; /* What partition type */
+ unsigned char end_head; /* end head */
+ unsigned char end_sector; /* end sector */
+ unsigned char end_cyl; /* end cylinder */
+ unsigned int start_sect; /* starting sector counting from 0 */
+ unsigned int nr_sects; /* nr of sectors in partition */
+} __attribute__((packed));
+
+struct hd_struct {
+ long start_sect;
+ long nr_sects;
+ int type; /* RAID or normal */
+};
+
+/*
+ * partition types Linux cares about.
+ *
+ * currently there are 'normal' and RAID types.
+ */
+
+static inline unsigned int ptype (unsigned char raw_type)
+{
+ switch (raw_type) {
+ case LINUX_OLD_RAID_PARTITION:
+ return LINUX_OLD_RAID_PARTITION;
+ case LINUX_RAID_PARTITION:
+ return LINUX_RAID_PARTITION;
+ default:
+ }
+ return 0;
+}
+
+/*
+ * the maximum length a given partition name can take (eg. "scd11")
+ */
+#define MAX_DISKNAME_LEN 32
+
+struct gendisk {
+ int major; /* major number of driver */
+ const char *major_name; /* name of major driver */
+ int minor_shift; /* number of times minor is shifted to
+ get real minor */
+ int max_p; /* maximum partitions per device */
+ int max_nr; /* maximum number of real devices */
+
+ void (*init)(struct gendisk *); /* Initialization called before we do our thing */
+ struct hd_struct *part; /* partition table */
+ int *sizes; /* device size in blocks, copied to blk_size[] */
+ int nr_real; /* number of real devices */
+
+ void *real_devices; /* internal use */
+ struct gendisk *next;
+};
+
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+
+#define SOLARIS_X86_NUMSLICE 8
+#define SOLARIS_X86_VTOC_SANE (0x600DDEEEUL)
+
+struct solaris_x86_slice {
+ ushort s_tag; /* ID tag of partition */
+ ushort s_flag; /* permision flags */
+ daddr_t s_start; /* start sector no of partition */
+ long s_size; /* # of blocks in partition */
+};
+
+struct solaris_x86_vtoc {
+ unsigned long v_bootinfo[3]; /* info needed by mboot (unsupported) */
+ unsigned long v_sanity; /* to verify vtoc sanity */
+ unsigned long v_version; /* layout version */
+ char v_volume[8]; /* volume name */
+ ushort v_sectorsz; /* sector size in bytes */
+ ushort v_nparts; /* number of partitions */
+ unsigned long v_reserved[10]; /* free space */
+ struct solaris_x86_slice
+ v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */
+ time_t timestamp[SOLARIS_X86_NUMSLICE]; /* timestamp (unsupported) */
+ char v_asciilabel[128]; /* for compatibility */
+};
+
+#endif /* CONFIG_SOLARIS_X86_PARTITION */
+
+#ifdef CONFIG_BSD_DISKLABEL
+/*
+ * BSD disklabel support by Yossi Gottlieb <yogo@math.tau.ac.il>
+ * updated by Marc Espie <Marc.Espie@openbsd.org>
+ */
+#define FREEBSD_PARTITION 0xa5 /* FreeBSD Partition ID */
+#define OPENBSD_PARTITION 0xa6 /* OpenBSD Partition ID */
+#define NETBSD_PARTITION 0xa9 /* NetBSD Partition ID */
+#define BSDI_PARTITION 0xb7 /* BSDI Partition ID */
+
+/* Ours is not to wonder why.. */
+#define BSD_PARTITION FREEBSD_PARTITION
+
+/* check against BSD src/sys/sys/disklabel.h for consistency */
+
+#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
+#define BSD_MAXPARTITIONS 8
+#define OPENBSD_MAXPARTITIONS 16
+#define BSD_FS_UNUSED 0 /* disklabel unused partition entry ID */
+struct bsd_disklabel {
+ __u32 d_magic; /* the magic number */
+ __s16 d_type; /* drive type */
+ __s16 d_subtype; /* controller/d_type specific */
+ char d_typename[16]; /* type name, e.g. "eagle" */
+ char d_packname[16]; /* pack identifier */
+ __u32 d_secsize; /* # of bytes per sector */
+ __u32 d_nsectors; /* # of data sectors per track */
+ __u32 d_ntracks; /* # of tracks per cylinder */
+ __u32 d_ncylinders; /* # of data cylinders per unit */
+ __u32 d_secpercyl; /* # of data sectors per cylinder */
+ __u32 d_secperunit; /* # of data sectors per unit */
+ __u16 d_sparespertrack; /* # of spare sectors per track */
+ __u16 d_sparespercyl; /* # of spare sectors per cylinder */
+ __u32 d_acylinders; /* # of alt. cylinders per unit */
+ __u16 d_rpm; /* rotational speed */
+ __u16 d_interleave; /* hardware sector interleave */
+ __u16 d_trackskew; /* sector 0 skew, per track */
+ __u16 d_cylskew; /* sector 0 skew, per cylinder */
+ __u32 d_headswitch; /* head switch time, usec */
+ __u32 d_trkseek; /* track-to-track seek, usec */
+ __u32 d_flags; /* generic flags */
+#define NDDATA 5
+ __u32 d_drivedata[NDDATA]; /* drive-type specific information */
+#define NSPARE 5
+ __u32 d_spare[NSPARE]; /* reserved for future use */
+ __u32 d_magic2; /* the magic number (again) */
+ __u16 d_checksum; /* xor of data incl. partitions */
+
+ /* filesystem and partition information: */
+ __u16 d_npartitions; /* number of partitions in following */
+ __u32 d_bbsize; /* size of boot area at sn0, bytes */
+ __u32 d_sbsize; /* max size of fs superblock, bytes */
+ struct bsd_partition { /* the partition table */
+ __u32 p_size; /* number of sectors in partition */
+ __u32 p_offset; /* starting sector */
+ __u32 p_fsize; /* filesystem basic fragment size */
+ __u8 p_fstype; /* filesystem type, see below */
+ __u8 p_frag; /* filesystem fragments per block */
+ __u16 p_cpg; /* filesystem cylinders per group */
+ } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
+};
+
+#endif /* CONFIG_BSD_DISKLABEL */
+
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+/*
+ * Unixware slices support by Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
+ * and Krzysztof G. Baranowski <kgb@knm.org.pl>
+ */
+
+#define UNIXWARE_PARTITION 0x63 /* Partition ID, same as */
+ /* GNU_HURD and SCO Unix */
+#define UNIXWARE_DISKMAGIC (0xCA5E600DUL) /* The disk magic number */
+#define UNIXWARE_DISKMAGIC2 (0x600DDEEEUL) /* The slice table magic nr */
+#define UNIXWARE_NUMSLICE 16
+#define UNIXWARE_FS_UNUSED 0 /* Unused slice entry ID */
+
+struct unixware_slice {
+ __u16 s_label; /* label */
+ __u16 s_flags; /* permission flags */
+ __u32 start_sect; /* starting sector */
+ __u32 nr_sects; /* number of sectors in slice */
+};
+
+struct unixware_disklabel {
+ __u32 d_type; /* drive type */
+ __u32 d_magic; /* the magic number */
+ __u32 d_version; /* version number */
+ char d_serial[12]; /* serial number of the device */
+ __u32 d_ncylinders; /* # of data cylinders per device */
+ __u32 d_ntracks; /* # of tracks per cylinder */
+ __u32 d_nsectors; /* # of data sectors per track */
+ __u32 d_secsize; /* # of bytes per sector */
+ __u32 d_part_start; /* # of first sector of this partition */
+ __u32 d_unknown1[12]; /* ? */
+ __u32 d_alt_tbl; /* byte offset of alternate table */
+ __u32 d_alt_len; /* byte length of alternate table */
+ __u32 d_phys_cyl; /* # of physical cylinders per device */
+ __u32 d_phys_trk; /* # of physical tracks per cylinder */
+ __u32 d_phys_sec; /* # of physical sectors per track */
+ __u32 d_phys_bytes; /* # of physical bytes per sector */
+ __u32 d_unknown2; /* ? */
+ __u32 d_unknown3; /* ? */
+ __u32 d_pad[8]; /* pad */
+
+ struct unixware_vtoc {
+ __u32 v_magic; /* the magic number */
+ __u32 v_version; /* version number */
+ char v_name[8]; /* volume name */
+ __u16 v_nslices; /* # of slices */
+ __u16 v_unknown1; /* ? */
+ __u32 v_reserved[10]; /* reserved */
+ struct unixware_slice
+ v_slice[UNIXWARE_NUMSLICE]; /* slice headers */
+ } vtoc;
+
+}; /* 408 */
+
+#endif /* CONFIG_UNIXWARE_DISKLABEL */
+
+extern struct gendisk *gendisk_head; /* linked list of disks */
+
+/*
+ * disk_name() is used by genhd.c and md.c.
+ * It formats the devicename of the indicated disk
+ * into the supplied buffer, and returns a pointer
+ * to that same buffer (for convenience).
+ */
+char *disk_name (struct gendisk *hd, int minor, char *buf);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/ghash.h b/pfinet/linux-src/include/linux/ghash.h
new file mode 100644
index 00000000..278f6c2f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ghash.h
@@ -0,0 +1,218 @@
+/*
+ * include/linux/ghash.h -- generic hashing with fuzzy retrieval
+ *
+ * (C) 1997 Thomas Schoebel-Theuer
+ *
+ * The algorithms implemented here seem to be a completely new invention,
+ * and I'll publish the fundamentals in a paper.
+ */
+
+#ifndef _GHASH_H
+#define _GHASH_H
+/* HASHSIZE _must_ be a power of two!!! */
+
+
+#define DEF_HASH_FUZZY_STRUCTS(NAME,HASHSIZE,TYPE) \
+\
+struct NAME##_table {\
+ TYPE * hashtable[HASHSIZE];\
+ TYPE * sorted_list;\
+ int nr_entries;\
+};\
+\
+struct NAME##_ptrs {\
+ TYPE * next_hash;\
+ TYPE * prev_hash;\
+ TYPE * next_sorted;\
+ TYPE * prev_sorted;\
+};
+
+#define DEF_HASH_FUZZY(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\
+\
+LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
+{\
+ int ix = HASHFN(elem->KEY);\
+ TYPE ** base = &tbl->hashtable[ix];\
+ TYPE * ptr = *base;\
+ TYPE * prev = NULL;\
+\
+ tbl->nr_entries++;\
+ while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\
+ base = &ptr->PTRS.next_hash;\
+ prev = ptr;\
+ ptr = *base;\
+ }\
+ elem->PTRS.next_hash = ptr;\
+ elem->PTRS.prev_hash = prev;\
+ if(ptr) {\
+ ptr->PTRS.prev_hash = elem;\
+ }\
+ *base = elem;\
+\
+ ptr = prev;\
+ if(!ptr) {\
+ ptr = tbl->sorted_list;\
+ prev = NULL;\
+ } else {\
+ prev = ptr->PTRS.prev_sorted;\
+ }\
+ while(ptr) {\
+ TYPE * next = ptr->PTRS.next_hash;\
+ if(next && KEYCMP(next->KEY, elem->KEY)) {\
+ prev = ptr;\
+ ptr = next;\
+ } else if(KEYCMP(ptr->KEY, elem->KEY)) {\
+ prev = ptr;\
+ ptr = ptr->PTRS.next_sorted;\
+ } else\
+ break;\
+ }\
+ elem->PTRS.next_sorted = ptr;\
+ elem->PTRS.prev_sorted = prev;\
+ if(ptr) {\
+ ptr->PTRS.prev_sorted = elem;\
+ }\
+ if(prev) {\
+ prev->PTRS.next_sorted = elem;\
+ } else {\
+ tbl->sorted_list = elem;\
+ }\
+}\
+\
+LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
+{\
+ TYPE * next = elem->PTRS.next_hash;\
+ TYPE * prev = elem->PTRS.prev_hash;\
+\
+ tbl->nr_entries--;\
+ if(next)\
+ next->PTRS.prev_hash = prev;\
+ if(prev)\
+ prev->PTRS.next_hash = next;\
+ else {\
+ int ix = HASHFN(elem->KEY);\
+ tbl->hashtable[ix] = next;\
+ }\
+\
+ next = elem->PTRS.next_sorted;\
+ prev = elem->PTRS.prev_sorted;\
+ if(next)\
+ next->PTRS.prev_sorted = prev;\
+ if(prev)\
+ prev->PTRS.next_sorted = next;\
+ else\
+ tbl->sorted_list = next;\
+}\
+\
+LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
+{\
+ int ix = hashfn(pos);\
+ TYPE * ptr = tbl->hashtable[ix];\
+ while(ptr && KEYCMP(ptr->KEY, pos))\
+ ptr = ptr->PTRS.next_hash;\
+ if(ptr && !KEYEQ(ptr->KEY, pos))\
+ ptr = NULL;\
+ return ptr;\
+}\
+\
+LINKAGE TYPE * find_##NAME##_hash_fuzzy(struct NAME##_table * tbl, KEYTYPE pos)\
+{\
+ int ix;\
+ int offset;\
+ TYPE * ptr;\
+ TYPE * next;\
+\
+ ptr = tbl->sorted_list;\
+ if(!ptr || KEYCMP(pos, ptr->KEY))\
+ return NULL;\
+ ix = HASHFN(pos);\
+ offset = HASHSIZE;\
+ do {\
+ offset >>= 1;\
+ next = tbl->hashtable[(ix+offset) & ((HASHSIZE)-1)];\
+ if(next && (KEYCMP(next->KEY, pos) || KEYEQ(next->KEY, pos))\
+ && KEYCMP(ptr->KEY, next->KEY))\
+ ptr = next;\
+ } while(offset);\
+\
+ for(;;) {\
+ next = ptr->PTRS.next_hash;\
+ if(next) {\
+ if(KEYCMP(next->KEY, pos)) {\
+ ptr = next;\
+ continue;\
+ }\
+ }\
+ next = ptr->PTRS.next_sorted;\
+ if(next && KEYCMP(next->KEY, pos)) {\
+ ptr = next;\
+ continue;\
+ }\
+ return ptr;\
+ }\
+ return NULL;\
+}
+
+#define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) \
+\
+struct NAME##_table {\
+ TYPE * hashtable[HASHSIZE];\
+ int nr_entries;\
+};\
+\
+struct NAME##_ptrs {\
+ TYPE * next_hash;\
+ TYPE * prev_hash;\
+};
+
+#define DEF_HASH(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\
+\
+LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
+{\
+ int ix = HASHFN(elem->KEY);\
+ TYPE ** base = &tbl->hashtable[ix];\
+ TYPE * ptr = *base;\
+ TYPE * prev = NULL;\
+\
+ tbl->nr_entries++;\
+ while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\
+ base = &ptr->PTRS.next_hash;\
+ prev = ptr;\
+ ptr = *base;\
+ }\
+ elem->PTRS.next_hash = ptr;\
+ elem->PTRS.prev_hash = prev;\
+ if(ptr) {\
+ ptr->PTRS.prev_hash = elem;\
+ }\
+ *base = elem;\
+}\
+\
+LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
+{\
+ TYPE * next = elem->PTRS.next_hash;\
+ TYPE * prev = elem->PTRS.prev_hash;\
+\
+ tbl->nr_entries--;\
+ if(next)\
+ next->PTRS.prev_hash = prev;\
+ if(prev)\
+ prev->PTRS.next_hash = next;\
+ else {\
+ int ix = HASHFN(elem->KEY);\
+ tbl->hashtable[ix] = next;\
+ }\
+}\
+\
+LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
+{\
+ int ix = hashfn(pos);\
+ TYPE * ptr = tbl->hashtable[ix];\
+ while(ptr && KEYCMP(ptr->KEY, pos))\
+ ptr = ptr->PTRS.next_hash;\
+ if(ptr && !KEYEQ(ptr->KEY, pos))\
+ ptr = NULL;\
+ return ptr;\
+}
+
+#endif
diff --git a/pfinet/linux-src/include/linux/hayesesp.h b/pfinet/linux-src/include/linux/hayesesp.h
new file mode 100644
index 00000000..2ed3903a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hayesesp.h
@@ -0,0 +1,127 @@
+#ifndef HAYESESP_H
+#define HAYESESP_H
+
+struct hayes_esp_config {
+ short flow_on;
+ short flow_off;
+ short rx_trigger;
+ short tx_trigger;
+ short pio_threshold;
+ unsigned char rx_timeout;
+ char dma_channel;
+};
+
+#ifdef __KERNEL__
+
+#define ESP_DMA_CHANNEL 0
+#define ESP_RX_TRIGGER 768
+#define ESP_TX_TRIGGER 768
+#define ESP_FLOW_OFF 1016
+#define ESP_FLOW_ON 944
+#define ESP_RX_TMOUT 128
+#define ESP_PIO_THRESHOLD 32
+
+#define ESP_IN_MAJOR 57 /* major dev # for dial in */
+#define ESP_OUT_MAJOR 58 /* major dev # for dial out */
+#define ESPC_SCALE 3
+#define UART_ESI_BASE 0x00
+#define UART_ESI_SID 0x01
+#define UART_ESI_RX 0x02
+#define UART_ESI_TX 0x02
+#define UART_ESI_CMD1 0x04
+#define UART_ESI_CMD2 0x05
+#define UART_ESI_STAT1 0x04
+#define UART_ESI_STAT2 0x05
+#define UART_ESI_RWS 0x07
+
+#define UART_IER_DMA_TMOUT 0x80
+#define UART_IER_DMA_TC 0x08
+
+#define ESI_SET_IRQ 0x04
+#define ESI_SET_DMA_TMOUT 0x05
+#define ESI_SET_SRV_MASK 0x06
+#define ESI_SET_ERR_MASK 0x07
+#define ESI_SET_FLOW_CNTL 0x08
+#define ESI_SET_FLOW_CHARS 0x09
+#define ESI_SET_FLOW_LVL 0x0a
+#define ESI_SET_TRIGGER 0x0b
+#define ESI_SET_RX_TIMEOUT 0x0c
+#define ESI_SET_FLOW_TMOUT 0x0d
+#define ESI_WRITE_UART 0x0e
+#define ESI_READ_UART 0x0f
+#define ESI_SET_MODE 0x10
+#define ESI_GET_ERR_STAT 0x12
+#define ESI_GET_UART_STAT 0x13
+#define ESI_GET_RX_AVAIL 0x14
+#define ESI_GET_TX_AVAIL 0x15
+#define ESI_START_DMA_RX 0x16
+#define ESI_START_DMA_TX 0x17
+#define ESI_ISSUE_BREAK 0x1a
+#define ESI_FLUSH_RX 0x1b
+#define ESI_FLUSH_TX 0x1c
+#define ESI_SET_BAUD 0x1d
+#define ESI_SET_ENH_IRQ 0x1f
+#define ESI_SET_REINTR 0x20
+#define ESI_SET_PRESCALAR 0x23
+#define ESI_NO_COMMAND 0xff
+
+#define ESP_STAT_RX_TIMEOUT 0x01
+#define ESP_STAT_DMA_RX 0x02
+#define ESP_STAT_DMA_TX 0x04
+#define ESP_STAT_NEVER_DMA 0x08
+#define ESP_STAT_USE_PIO 0x10
+
+#define ESP_EVENT_WRITE_WAKEUP 0
+#define ESP_MAGIC 0x53ee
+#define ESP_XMIT_SIZE 4096
+
+struct esp_struct {
+ int magic;
+ int port;
+ int irq;
+ int flags; /* defined in tty.h */
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int stat_flags;
+ int custom_divisor;
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ int IER; /* Interrupt Enable Register */
+ int MCR; /* Modem control register */
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ struct tq_struct tqueue;
+ struct tq_struct tqueue_hangup;
+ struct termios normal_termios;
+ struct termios callout_termios;
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+ struct wait_queue *delta_msr_wait;
+ struct wait_queue *break_wait;
+ struct async_icount icount; /* kernel counters for the 4 input interrupts */
+ struct hayes_esp_config config; /* port configuration */
+ struct esp_struct *next_port; /* For the linked list */
+};
+
+struct esp_pio_buffer {
+ unsigned char data[1024];
+ struct esp_pio_buffer *next;
+};
+
+#endif /* __KERNEL__ */
+
+
+#endif /* ESP_H */
+
diff --git a/pfinet/linux-src/include/linux/hdlcdrv.h b/pfinet/linux-src/include/linux/hdlcdrv.h
new file mode 100644
index 00000000..11cd8c6a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hdlcdrv.h
@@ -0,0 +1,383 @@
+/*
+ * hdlcdrv.h -- HDLC packet radio network driver.
+ * The Linux soundcard driver for 1200 baud and 9600 baud packet radio
+ * (C) 1996-1998 by Thomas Sailer, HB9JNX/AE4WA
+ */
+
+#ifndef _HDLCDRV_H
+#define _HDLCDRV_H
+
+/* -------------------------------------------------------------------- */
+/*
+ * structs for the IOCTL commands
+ */
+
+struct hdlcdrv_params {
+ int iobase;
+ int irq;
+ int dma;
+ int dma2;
+ int seriobase;
+ int pariobase;
+ int midiiobase;
+};
+
+struct hdlcdrv_channel_params {
+ int tx_delay; /* the transmitter keyup delay in 10ms units */
+ int tx_tail; /* the transmitter keyoff delay in 10ms units */
+ int slottime; /* the slottime in 10ms; usually 10 = 100ms */
+ int ppersist; /* the p-persistence 0..255 */
+ int fulldup; /* some driver do not support full duplex, setting */
+ /* this just makes them send even if DCD is on */
+};
+
+struct hdlcdrv_old_channel_state {
+ int ptt;
+ int dcd;
+ int ptt_keyed;
+};
+
+struct hdlcdrv_channel_state {
+ int ptt;
+ int dcd;
+ int ptt_keyed;
+ unsigned long tx_packets;
+ unsigned long tx_errors;
+ unsigned long rx_packets;
+ unsigned long rx_errors;
+};
+
+struct hdlcdrv_ioctl {
+ int cmd;
+ union {
+ struct hdlcdrv_params mp;
+ struct hdlcdrv_channel_params cp;
+ struct hdlcdrv_channel_state cs;
+ struct hdlcdrv_old_channel_state ocs;
+ unsigned int calibrate;
+ unsigned char bits;
+ char modename[128];
+ char drivername[32];
+ } data;
+};
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * ioctl values
+ */
+#define HDLCDRVCTL_GETMODEMPAR 0
+#define HDLCDRVCTL_SETMODEMPAR 1
+#define HDLCDRVCTL_MODEMPARMASK 2 /* not handled by hdlcdrv */
+#define HDLCDRVCTL_GETCHANNELPAR 10
+#define HDLCDRVCTL_SETCHANNELPAR 11
+#define HDLCDRVCTL_OLDGETSTAT 20
+#define HDLCDRVCTL_CALIBRATE 21
+#define HDLCDRVCTL_GETSTAT 22
+
+/*
+ * these are mainly for debugging purposes
+ */
+#define HDLCDRVCTL_GETSAMPLES 30
+#define HDLCDRVCTL_GETBITS 31
+
+/*
+ * not handled by hdlcdrv, but by its depending drivers
+ */
+#define HDLCDRVCTL_GETMODE 40
+#define HDLCDRVCTL_SETMODE 41
+#define HDLCDRVCTL_MODELIST 42
+#define HDLCDRVCTL_DRIVERNAME 43
+
+/*
+ * mask of needed modem parameters, returned by HDLCDRVCTL_MODEMPARMASK
+ */
+#define HDLCDRV_PARMASK_IOBASE (1<<0)
+#define HDLCDRV_PARMASK_IRQ (1<<1)
+#define HDLCDRV_PARMASK_DMA (1<<2)
+#define HDLCDRV_PARMASK_DMA2 (1<<3)
+#define HDLCDRV_PARMASK_SERIOBASE (1<<4)
+#define HDLCDRV_PARMASK_PARIOBASE (1<<5)
+#define HDLCDRV_PARMASK_MIDIIOBASE (1<<6)
+
+/* -------------------------------------------------------------------- */
+
+#ifdef __KERNEL__
+
+#include <linux/netdevice.h>
+#include <linux/if.h>
+#include <asm/spinlock.h>
+
+#define HDLCDRV_MAGIC 0x5ac6e778
+#define HDLCDRV_IFNAMELEN 6
+#define HDLCDRV_HDLCBUFFER 32 /* should be a power of 2 for speed reasons */
+#define HDLCDRV_BITBUFFER 256 /* should be a power of 2 for speed reasons */
+#undef HDLCDRV_LOOPBACK /* define for HDLC debugging purposes */
+#define HDLCDRV_DEBUG
+
+/* maximum packet length, excluding CRC */
+#define HDLCDRV_MAXFLEN 400
+
+
+struct hdlcdrv_hdlcbuffer {
+ spinlock_t lock;
+ unsigned rd, wr;
+ unsigned short buf[HDLCDRV_HDLCBUFFER];
+};
+
+#ifdef HDLCDRV_DEBUG
+struct hdlcdrv_bitbuffer {
+ unsigned int rd;
+ unsigned int wr;
+ unsigned int shreg;
+ unsigned char buffer[HDLCDRV_BITBUFFER];
+};
+
+extern inline void hdlcdrv_add_bitbuffer(struct hdlcdrv_bitbuffer *buf,
+ unsigned int bit)
+{
+ unsigned char new;
+
+ new = buf->shreg & 1;
+ buf->shreg >>= 1;
+ buf->shreg |= (!!bit) << 7;
+ if (new) {
+ buf->buffer[buf->wr] = buf->shreg;
+ buf->wr = (buf->wr+1) % sizeof(buf->buffer);
+ buf->shreg = 0x80;
+ }
+}
+
+extern inline void hdlcdrv_add_bitbuffer_word(struct hdlcdrv_bitbuffer *buf,
+ unsigned int bits)
+{
+ buf->buffer[buf->wr] = bits & 0xff;
+ buf->wr = (buf->wr+1) % sizeof(buf->buffer);
+ buf->buffer[buf->wr] = (bits >> 8) & 0xff;
+ buf->wr = (buf->wr+1) % sizeof(buf->buffer);
+
+}
+#endif /* HDLCDRV_DEBUG */
+
+/* -------------------------------------------------------------------- */
+/*
+ * Information that need to be kept for each driver.
+ */
+
+struct hdlcdrv_ops {
+ /*
+ * first some informations needed by the hdlcdrv routines
+ */
+ const char *drvname;
+ const char *drvinfo;
+ /*
+ * the routines called by the hdlcdrv routines
+ */
+ int (*open)(struct device *);
+ int (*close)(struct device *);
+ int (*ioctl)(struct device *, struct ifreq *,
+ struct hdlcdrv_ioctl *, int);
+};
+
+struct hdlcdrv_state {
+ int magic;
+
+ char ifname[HDLCDRV_IFNAMELEN];
+
+ const struct hdlcdrv_ops *ops;
+
+ struct {
+ int bitrate;
+ } par;
+
+ struct hdlcdrv_pttoutput {
+ int dma2;
+ int seriobase;
+ int pariobase;
+ int midiiobase;
+ unsigned int flags;
+ } ptt_out;
+
+ struct hdlcdrv_channel_params ch_params;
+
+ struct hdlcdrv_hdlcrx {
+ struct hdlcdrv_hdlcbuffer hbuf;
+ int in_hdlc_rx;
+ /* 0 = sync hunt, != 0 receiving */
+ int rx_state;
+ unsigned int bitstream;
+ unsigned int bitbuf;
+ int numbits;
+ unsigned char dcd;
+
+ int len;
+ unsigned char *bp;
+ unsigned char buffer[HDLCDRV_MAXFLEN+2];
+ } hdlcrx;
+
+ struct hdlcdrv_hdlctx {
+ struct hdlcdrv_hdlcbuffer hbuf;
+ int in_hdlc_tx;
+ /*
+ * 0 = send flags
+ * 1 = send txtail (flags)
+ * 2 = send packet
+ */
+ int tx_state;
+ int numflags;
+ unsigned int bitstream;
+ unsigned char ptt;
+ int calibrate;
+ int slotcnt;
+
+ unsigned int bitbuf;
+ int numbits;
+
+ int len;
+ unsigned char *bp;
+ unsigned char buffer[HDLCDRV_MAXFLEN+2];
+ } hdlctx;
+
+#ifdef HDLCDRV_DEBUG
+ struct hdlcdrv_bitbuffer bitbuf_channel;
+ struct hdlcdrv_bitbuffer bitbuf_hdlc;
+#endif /* HDLCDRV_DEBUG */
+
+#if LINUX_VERSION_CODE < 0x20119
+ struct enet_statistics stats;
+#else
+ struct net_device_stats stats;
+#endif
+ int ptt_keyed;
+
+ struct sk_buff_head send_queue; /* Packets awaiting transmission */
+};
+
+
+/* -------------------------------------------------------------------- */
+
+extern inline int hdlcdrv_hbuf_full(struct hdlcdrv_hdlcbuffer *hb)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&hb->lock, flags);
+ ret = !((HDLCDRV_HDLCBUFFER - 1 + hb->rd - hb->wr) % HDLCDRV_HDLCBUFFER);
+ spin_unlock_irqrestore(&hb->lock, flags);
+ return ret;
+}
+
+/* -------------------------------------------------------------------- */
+
+extern inline int hdlcdrv_hbuf_empty(struct hdlcdrv_hdlcbuffer *hb)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&hb->lock, flags);
+ ret = (hb->rd == hb->wr);
+ spin_unlock_irqrestore(&hb->lock, flags);
+ return ret;
+}
+
+/* -------------------------------------------------------------------- */
+
+extern inline unsigned short hdlcdrv_hbuf_get(struct hdlcdrv_hdlcbuffer *hb)
+{
+ unsigned long flags;
+ unsigned short val;
+ unsigned newr;
+
+ spin_lock_irqsave(&hb->lock, flags);
+ if (hb->rd == hb->wr)
+ val = 0;
+ else {
+ newr = (hb->rd+1) % HDLCDRV_HDLCBUFFER;
+ val = hb->buf[hb->rd];
+ hb->rd = newr;
+ }
+ spin_unlock_irqrestore(&hb->lock, flags);
+ return val;
+}
+
+/* -------------------------------------------------------------------- */
+
+extern inline void hdlcdrv_hbuf_put(struct hdlcdrv_hdlcbuffer *hb,
+ unsigned short val)
+{
+ unsigned newp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hb->lock, flags);
+ newp = (hb->wr+1) % HDLCDRV_HDLCBUFFER;
+ if (newp != hb->rd) {
+ hb->buf[hb->wr] = val & 0xffff;
+ hb->wr = newp;
+ }
+ spin_unlock_irqrestore(&hb->lock, flags);
+}
+
+/* -------------------------------------------------------------------- */
+
+extern inline void hdlcdrv_putbits(struct hdlcdrv_state *s, unsigned int bits)
+{
+ hdlcdrv_hbuf_put(&s->hdlcrx.hbuf, bits);
+}
+
+extern inline unsigned int hdlcdrv_getbits(struct hdlcdrv_state *s)
+{
+ unsigned int ret;
+
+ if (hdlcdrv_hbuf_empty(&s->hdlctx.hbuf)) {
+ if (s->hdlctx.calibrate > 0)
+ s->hdlctx.calibrate--;
+ else
+ s->hdlctx.ptt = 0;
+ ret = 0;
+ } else
+ ret = hdlcdrv_hbuf_get(&s->hdlctx.hbuf);
+#ifdef HDLCDRV_LOOPBACK
+ hdlcdrv_hbuf_put(&s->hdlcrx.hbuf, ret);
+#endif /* HDLCDRV_LOOPBACK */
+ return ret;
+}
+
+extern inline void hdlcdrv_channelbit(struct hdlcdrv_state *s, unsigned int bit)
+{
+#ifdef HDLCDRV_DEBUG
+ hdlcdrv_add_bitbuffer(&s->bitbuf_channel, bit);
+#endif /* HDLCDRV_DEBUG */
+}
+
+extern inline void hdlcdrv_setdcd(struct hdlcdrv_state *s, int dcd)
+{
+ s->hdlcrx.dcd = !!dcd;
+}
+
+extern inline int hdlcdrv_ptt(struct hdlcdrv_state *s)
+{
+ return s->hdlctx.ptt || (s->hdlctx.calibrate > 0);
+}
+
+/* -------------------------------------------------------------------- */
+
+void hdlcdrv_receiver(struct device *, struct hdlcdrv_state *);
+void hdlcdrv_transmitter(struct device *, struct hdlcdrv_state *);
+void hdlcdrv_arbitrate(struct device *, struct hdlcdrv_state *);
+int hdlcdrv_register_hdlcdrv(struct device *dev, const struct hdlcdrv_ops *ops,
+ unsigned int privsize, char *ifname,
+ unsigned int baseaddr, unsigned int irq,
+ unsigned int dma);
+int hdlcdrv_unregister_hdlcdrv(struct device *dev);
+
+/* -------------------------------------------------------------------- */
+
+
+
+#endif /* __KERNEL__ */
+
+/* -------------------------------------------------------------------- */
+
+#endif /* _HDLCDRV_H */
+
+/* -------------------------------------------------------------------- */
diff --git a/pfinet/linux-src/include/linux/hdreg.h b/pfinet/linux-src/include/linux/hdreg.h
new file mode 100644
index 00000000..e467ae9b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hdreg.h
@@ -0,0 +1,282 @@
+#ifndef _LINUX_HDREG_H
+#define _LINUX_HDREG_H
+
+/*
+ * This file contains some defines for the AT-hd-controller.
+ * Various sources.
+ */
+
+#define HD_IRQ 14 /* the standard disk interrupt */
+
+/* ide.c has its own port definitions in "ide.h" */
+
+/* Hd controller regs. Ref: IBM AT Bios-listing */
+#define HD_DATA 0x1f0 /* _CTL when writing */
+#define HD_ERROR 0x1f1 /* see err-bits */
+#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
+#define HD_SECTOR 0x1f3 /* starting sector */
+#define HD_LCYL 0x1f4 /* starting cylinder */
+#define HD_HCYL 0x1f5 /* high byte of starting cyl */
+#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
+#define HD_STATUS 0x1f7 /* see status-bits */
+#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
+#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
+#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
+
+#define HD_CMD 0x3f6 /* used for resets */
+#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
+
+/* remainder is shared between hd.c, ide.c, ide-cd.c, and the hdparm utility */
+
+/* Bits of HD_STATUS */
+#define ERR_STAT 0x01
+#define INDEX_STAT 0x02
+#define ECC_STAT 0x04 /* Corrected error */
+#define DRQ_STAT 0x08
+#define SEEK_STAT 0x10
+#define WRERR_STAT 0x20
+#define READY_STAT 0x40
+#define BUSY_STAT 0x80
+
+/* Values for HD_COMMAND */
+#define WIN_RESTORE 0x10
+#define WIN_READ 0x20
+#define WIN_WRITE 0x30
+#define WIN_WRITE_VERIFY 0x3C
+#define WIN_VERIFY 0x40
+#define WIN_FORMAT 0x50
+#define WIN_INIT 0x60
+#define WIN_SEEK 0x70
+#define WIN_DIAGNOSE 0x90
+#define WIN_SPECIFY 0x91 /* set drive geometry translation */
+#define WIN_SETIDLE1 0xE3
+#define WIN_SETIDLE2 0x97
+
+#define WIN_STANDBYNOW1 0xE0
+#define WIN_STANDBYNOW2 0x94
+#define WIN_SLEEPNOW1 0xE6
+#define WIN_SLEEPNOW2 0x99
+#define WIN_CHECKPOWERMODE1 0xE5
+#define WIN_CHECKPOWERMODE2 0x98
+
+#define WIN_DOORLOCK 0xde /* lock door on removable drives */
+#define WIN_DOORUNLOCK 0xdf /* unlock door on removable drives */
+
+#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode */
+#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
+#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
+#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
+#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */
+#define WIN_SETFEATURES 0xEF /* set special drive features */
+#define WIN_READDMA 0xc8 /* read sectors using DMA transfers */
+#define WIN_WRITEDMA 0xca /* write sectors using DMA transfers */
+
+#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
+#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
+
+#define WIN_SMART 0xb0 /* self-monitoring and reporting */
+
+/* Additional drive command codes used by ATAPI devices. */
+#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
+#define WIN_SRST 0x08 /* ATAPI soft reset command */
+#define WIN_PACKETCMD 0xa0 /* Send a packet command. */
+
+/* WIN_SMART sub-commands */
+
+#define SMART_READ_VALUES 0xd0
+#define SMART_READ_THRESHOLDS 0xd1
+#define SMART_AUTOSAVE 0xd2
+#define SMART_SAVE 0xd3
+#define SMART_IMMEDIATE_OFFLINE 0xd4
+#define SMART_ENABLE 0xd8
+#define SMART_DISABLE 0xd9
+#define SMART_STATUS 0xda
+#define SMART_AUTO_OFFLINE 0xdb
+
+/* WIN_SECURITY sub-commands */
+#define SECURITY_SET_PASSWORD 0xBA /* 0xF1 */
+#define SECURITY_UNLOCK 0xBB /* 0xF2 */
+#define SECURITY_ERASE_PREPARE 0xBC /* 0xF3 */
+#define SECURITY_ERASE_UNIT 0xBD /* 0xF4 */
+#define SECURITY_FREEZE_LOCK 0xBE /* 0xF5 */
+#define SECURITY_DISABLE_PASSWORD 0xBF /* 0xF6 */
+
+/* Bits for HD_ERROR */
+#define MARK_ERR 0x01 /* Bad address mark */
+#define TRK0_ERR 0x02 /* couldn't find track 0 */
+#define ABRT_ERR 0x04 /* Command aborted */
+#define MCR_ERR 0x08 /* media change request */
+#define ID_ERR 0x10 /* ID field not found */
+#define ECC_ERR 0x40 /* Uncorrectable ECC error */
+#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
+#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
+
+struct hd_geometry {
+ unsigned char heads;
+ unsigned char sectors;
+ unsigned short cylinders;
+ unsigned long start;
+};
+
+/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */
+#define HDIO_GETGEO 0x0301 /* get device geometry */
+#define HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */
+#define HDIO_GET_MULTCOUNT 0x0304 /* get current IDE blockmode setting */
+#define HDIO_OBSOLETE_IDENTITY 0x0307 /* OBSOLETE, DO NOT USE: returns 142 bytes */
+#define HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */
+#define HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */
+#define HDIO_GET_NOWERR 0x030a /* get ignore-write-error flag */
+#define HDIO_GET_DMA 0x030b /* get use-dma flag */
+#define HDIO_GET_NICE 0x030c /* get nice flags */
+#define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
+#define HDIO_DRIVE_CMD 0x031f /* execute a special drive command */
+
+/* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */
+#define HDIO_SET_MULTCOUNT 0x0321 /* change IDE blockmode */
+#define HDIO_SET_UNMASKINTR 0x0322 /* permit other irqs during I/O */
+#define HDIO_SET_KEEPSETTINGS 0x0323 /* keep ioctl settings on reset */
+#define HDIO_SET_32BIT 0x0324 /* change io_32bit flags */
+#define HDIO_SET_NOWERR 0x0325 /* change ignore-write-error flag */
+#define HDIO_SET_DMA 0x0326 /* change use-dma flag */
+#define HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */
+#define HDIO_SCAN_HWIF 0x0328 /* register and (re)scan interface */
+#define HDIO_SET_NICE 0x0329 /* set nice flags */
+#define HDIO_UNREGISTER_HWIF 0x032a /* unregister interface */
+
+/* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
+struct hd_driveid {
+ unsigned short config; /* lots of obsolete bit flags */
+ unsigned short cyls; /* "physical" cyls */
+ unsigned short reserved2; /* reserved (word 2) */
+ unsigned short heads; /* "physical" heads */
+ unsigned short track_bytes; /* unformatted bytes per track */
+ unsigned short sector_bytes; /* unformatted bytes per sector */
+ unsigned short sectors; /* "physical" sectors per track */
+ unsigned short vendor0; /* vendor unique */
+ unsigned short vendor1; /* vendor unique */
+ unsigned short vendor2; /* vendor unique */
+ unsigned char serial_no[20]; /* 0 = not_specified */
+ unsigned short buf_type;
+ unsigned short buf_size; /* 512 byte increments; 0 = not_specified */
+ unsigned short ecc_bytes; /* for r/w long cmds; 0 = not_specified */
+ unsigned char fw_rev[8]; /* 0 = not_specified */
+ unsigned char model[40]; /* 0 = not_specified */
+ unsigned char max_multsect; /* 0=not_implemented */
+ unsigned char vendor3; /* vendor unique */
+ unsigned short dword_io; /* 0=not_implemented; 1=implemented */
+ unsigned char vendor4; /* vendor unique */
+ unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw 3:IORDYsup*/
+ unsigned short reserved50; /* reserved (word 50) */
+ unsigned char vendor5; /* vendor unique */
+ unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
+ unsigned char vendor6; /* vendor unique */
+ unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
+ unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
+ unsigned short cur_cyls; /* logical cylinders */
+ unsigned short cur_heads; /* logical heads */
+ unsigned short cur_sectors; /* logical sectors per track */
+ unsigned short cur_capacity0; /* logical total sectors on drive */
+ unsigned short cur_capacity1; /* (2 words, misaligned int) */
+ unsigned char multsect; /* current multiple sector count */
+ unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
+ unsigned int lba_capacity; /* total number of sectors */
+ unsigned short dma_1word; /* single-word dma info */
+ unsigned short dma_mword; /* multiple-word dma info */
+ unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
+ unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
+ unsigned short eide_dma_time; /* recommended mword dma cycle time (ns) */
+ unsigned short eide_pio; /* min cycle time (ns), no IORDY */
+ unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
+ unsigned short word69;
+ unsigned short word70;
+ /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
+ unsigned short word71;
+ unsigned short word72;
+ unsigned short word73;
+ unsigned short word74;
+ unsigned short word75;
+ unsigned short word76;
+ unsigned short word77;
+ unsigned short word78;
+ unsigned short word79;
+ unsigned short word80;
+ unsigned short word81;
+ unsigned short command_sets; /* bits 0:Smart 1:Security 2:Removable 3:PM */
+ unsigned short word83; /* bits 14:Smart Enabled 13:0 zero */
+ unsigned short word84;
+ unsigned short word85;
+ unsigned short word86;
+ unsigned short word87;
+ unsigned short dma_ultra;
+ unsigned short word89; /* reserved (word 89) */
+ unsigned short word90; /* reserved (word 90) */
+ unsigned short word91; /* reserved (word 91) */
+ unsigned short word92; /* reserved (word 92) */
+ unsigned short word93; /* reserved (word 93) */
+ unsigned short word94; /* reserved (word 94) */
+ unsigned short word95; /* reserved (word 95) */
+ unsigned short word96; /* reserved (word 96) */
+ unsigned short word97; /* reserved (word 97) */
+ unsigned short word98; /* reserved (word 98) */
+ unsigned short word99; /* reserved (word 99) */
+ unsigned short word100; /* reserved (word 100) */
+ unsigned short word101; /* reserved (word 101) */
+ unsigned short word102; /* reserved (word 102) */
+ unsigned short word103; /* reserved (word 103) */
+ unsigned short word104; /* reserved (word 104) */
+ unsigned short word105; /* reserved (word 105) */
+ unsigned short word106; /* reserved (word 106) */
+ unsigned short word107; /* reserved (word 107) */
+ unsigned short word108; /* reserved (word 108) */
+ unsigned short word109; /* reserved (word 109) */
+ unsigned short word110; /* reserved (word 110) */
+ unsigned short word111; /* reserved (word 111) */
+ unsigned short word112; /* reserved (word 112) */
+ unsigned short word113; /* reserved (word 113) */
+ unsigned short word114; /* reserved (word 114) */
+ unsigned short word115; /* reserved (word 115) */
+ unsigned short word116; /* reserved (word 116) */
+ unsigned short word117; /* reserved (word 117) */
+ unsigned short word118; /* reserved (word 118) */
+ unsigned short word119; /* reserved (word 119) */
+ unsigned short word120; /* reserved (word 120) */
+ unsigned short word121; /* reserved (word 121) */
+ unsigned short word122; /* reserved (word 122) */
+ unsigned short word123; /* reserved (word 123) */
+ unsigned short word124; /* reserved (word 124) */
+ unsigned short word125; /* reserved (word 125) */
+ unsigned short word126; /* reserved (word 126) */
+ unsigned short word127; /* reserved (word 127) */
+ unsigned short security; /* bits 0:support 1:enabled 2:locked 3:frozen */
+ unsigned short reserved[127];
+};
+
+/*
+ * IDE "nice" flags. These are used on a per drive basis to determine
+ * when to be nice and give more bandwidth to the other devices which
+ * share the same IDE bus.
+ */
+#define IDE_NICE_DSC_OVERLAP (0) /* per the DSC overlap protocol */
+#define IDE_NICE_ATAPI_OVERLAP (1) /* not supported yet */
+#define IDE_NICE_0 (2) /* when sure that it won't affect us */
+#define IDE_NICE_1 (3) /* when probably won't affect us much */
+#define IDE_NICE_2 (4) /* when we know it's on our expense */
+
+#ifdef __KERNEL__
+/*
+ * These routines are used for kernel command line parameters from main.c:
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_BLK_DEV_HD
+void hd_setup(char *, int *);
+#endif /* CONFIG_BLK_DEV_HD */
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+int ide_register(int io_port, int ctl_port, int irq);
+void ide_unregister(unsigned int);
+#endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_HDREG_H */
diff --git a/pfinet/linux-src/include/linux/hfmodem.h b/pfinet/linux-src/include/linux/hfmodem.h
new file mode 100644
index 00000000..7b35f116
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hfmodem.h
@@ -0,0 +1,256 @@
+/*****************************************************************************/
+
+/*
+ * hfmodem.h -- Linux soundcard HF FSK driver.
+ *
+ * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Swiss Federal Institute of Technology (ETH), Electronics Lab
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * This is the Linux realtime sound output driver
+ */
+
+/*****************************************************************************/
+
+#ifndef _HFMODEM_H
+#define _HFMODEM_H
+/* --------------------------------------------------------------------- */
+
+#include <linux/version.h>
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#if LINUX_VERSION_CODE >= 0x20100
+#include <linux/poll.h>
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#define HFMODEM_MINOR 145
+
+#define HFMODEM_SRATE 8000
+#define HFMODEM_MAXBITS 4800 /* required for GTOR 300 baud mode */
+#define HFMODEM_MINBAUD 40
+#define HFMODEM_MAXBAUD 400
+#define HFMODEM_MAXCORRLEN ((HFMODEM_SRATE+HFMODEM_MINBAUD-1)/HFMODEM_MINBAUD)
+
+/* --------------------------------------------------------------------- */
+
+typedef unsigned long hfmodem_time_t;
+typedef int hfmodem_soft_t;
+typedef unsigned long hfmodem_id_t;
+
+/* --------------------------------------------------------------------- */
+
+struct hfmodem_ioctl_fsk_tx_request {
+ hfmodem_time_t tstart;
+ hfmodem_time_t tinc;
+ int inv;
+ hfmodem_id_t id;
+ unsigned int nbits;
+ unsigned char *data;
+ unsigned int freq[2];
+};
+
+struct hfmodem_ioctl_fsk_rx_request {
+ hfmodem_time_t tstart;
+ hfmodem_time_t tinc;
+ unsigned int baud;
+ hfmodem_id_t id;
+ unsigned int nbits;
+ hfmodem_soft_t *data;
+ unsigned int freq[2];
+};
+
+struct hfmodem_ioctl_mixer_params {
+ int src;
+ int igain;
+ int ogain;
+};
+
+struct hfmodem_ioctl_sample_params {
+ __s16 *data;
+ int len;
+};
+
+#define HFMODEM_IOCTL_FSKTXREQUEST _IOW('H', 0, struct hfmodem_ioctl_fsk_tx_request)
+#define HFMODEM_IOCTL_FSKRXREQUEST _IOW('H', 1, struct hfmodem_ioctl_fsk_rx_request)
+#define HFMODEM_IOCTL_CLEARRQ _IO('H', 3)
+#define HFMODEM_IOCTL_GETCURTIME _IOR('H', 4, hfmodem_time_t)
+#define HFMODEM_IOCTL_WAITRQ _IOR('H', 5, hfmodem_id_t)
+#define HFMODEM_IOCTL_MIXERPARAMS _IOW('H', 6, struct hfmodem_ioctl_mixer_params)
+#define HFMODEM_IOCTL_SAMPLESTART _IOW('H', 7, struct hfmodem_ioctl_sample_params)
+#define HFMODEM_IOCTL_SAMPLEFINISHED _IO('H', 8)
+
+/* --------------------------------------------------------------------- */
+#ifdef __KERNEL__
+
+#include <linux/parport.h>
+
+#define DMA_MODE_AUTOINIT 0x10
+
+#define NR_DEVICE 1
+
+#define HFMODEM_FRAGSAMPLES (HFMODEM_SRATE/100)
+#define HFMODEM_FRAGSIZE (HFMODEM_FRAGSAMPLES*2)
+#define HFMODEM_NUMFRAGS 8
+#define HFMODEM_EXCESSFRAGS 3
+
+#define HFMODEM_NUMRXSLOTS 20
+#define HFMODEM_NUMTXSLOTS 4
+
+#define HFMODEM_CORRELATOR_CACHE 8
+
+enum slot_st { ss_unused = 0, ss_ready, ss_oper, ss_retired };
+typedef int hfmodem_conv_t;
+
+struct hfmodem_state {
+ const struct hfmodem_scops *scops;
+
+ /* io params */
+ struct {
+ unsigned int base_addr;
+ unsigned int dma;
+ unsigned int irq;
+ } io;
+
+ struct {
+ unsigned int seriobase;
+ unsigned int pariobase;
+ unsigned int midiiobase;
+ unsigned int flags;
+ struct pardevice *pardev;
+ } ptt_out;
+
+ struct {
+ __s16 *buf;
+ unsigned int lastfrag;
+ unsigned int fragptr;
+ unsigned int last_dmaptr;
+ int ptt_frames;
+ } dma;
+
+ struct {
+ unsigned int last_tvusec;
+ unsigned long long time_cnt;
+ hfmodem_time_t lasttime;
+#ifdef __i386__
+ unsigned int starttime_lo, starttime_hi;
+#endif /* __i386__ */
+ } clk;
+
+ int active;
+ struct wait_queue *wait;
+
+ struct {
+ __s16 *kbuf;
+ __s16 *ubuf;
+ __s16 *kptr;
+ unsigned int size;
+ int rem;
+ } sbuf;
+
+ struct {
+ hfmodem_time_t last_time;
+ unsigned int tx_phase;
+
+ struct hfmodem_l1_rxslot {
+ enum slot_st state;
+ hfmodem_time_t tstart, tinc;
+ hfmodem_soft_t *data;
+ hfmodem_soft_t *userdata;
+ unsigned int nbits;
+ unsigned int cntbits;
+ hfmodem_id_t id;
+ unsigned int corrlen;
+ hfmodem_conv_t scale;
+ unsigned int corr_cache;
+ } rxslots[HFMODEM_NUMRXSLOTS];
+
+ struct hfmodem_l1_txslot {
+ enum slot_st state;
+ hfmodem_time_t tstart, tinc;
+ unsigned char *data;
+ unsigned int nbits;
+ unsigned int cntbits;
+ hfmodem_id_t id;
+ unsigned char inv;
+ unsigned int phinc;
+ unsigned int phase_incs[2];
+ } txslots[HFMODEM_NUMTXSLOTS];
+ } l1;
+};
+
+struct hfmodem_correlator_cache {
+ int refcnt;
+ int lru;
+ unsigned short phase_incs[2];
+ hfmodem_conv_t correlator[2][2][HFMODEM_MAXCORRLEN];
+};
+
+struct hfmodem_scops {
+ unsigned int extent;
+
+ void (*init)(struct hfmodem_state *dev);
+ void (*prepare_input)(struct hfmodem_state *dev);
+ void (*trigger_input)(struct hfmodem_state *dev);
+ void (*prepare_output)(struct hfmodem_state *dev);
+ void (*trigger_output)(struct hfmodem_state *dev);
+ void (*stop)(struct hfmodem_state *dev);
+ unsigned int (*intack)(struct hfmodem_state *dev);
+ void (*mixer)(struct hfmodem_state *dev, int src, int igain, int ogain);
+};
+
+/* --------------------------------------------------------------------- */
+
+extern int hfmodem_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+#if LINUX_VERSION_CODE >= 0x20100
+extern unsigned int hfmodem_poll(struct file *file, poll_table *wait);
+#else
+extern int hfmodem_select(struct inode *inode, struct file *file, int sel_type, select_table *wait);
+#endif
+
+extern void hfmodem_clear_rq(struct hfmodem_state *dev);
+extern void hfmodem_input_samples(struct hfmodem_state *dev, hfmodem_time_t tstart,
+ hfmodem_time_t tinc, __s16 *samples);
+extern int hfmodem_output_samples(struct hfmodem_state *dev, hfmodem_time_t tstart,
+ hfmodem_time_t tinc, __s16 *samples);
+extern long hfmodem_next_tx_event(struct hfmodem_state *dev, hfmodem_time_t curr);
+extern void hfmodem_finish_pending_rx_requests(struct hfmodem_state *dev);
+extern void hfmodem_wakeup(struct hfmodem_state *dev);
+
+
+extern int hfmodem_sbcprobe(struct hfmodem_state *dev);
+extern int hfmodem_wssprobe(struct hfmodem_state *dev);
+
+extern void hfmodem_refclock_probe(void);
+extern void hfmodem_refclock_init(struct hfmodem_state *dev);
+extern hfmodem_time_t hfmodem_refclock_current(struct hfmodem_state *dev, hfmodem_time_t expected, int exp_valid);
+
+/* --------------------------------------------------------------------- */
+
+extern const char hfmodem_drvname[];
+extern const char hfmodem_drvinfo[];
+
+extern struct hfmodem_state hfmodem_state[NR_DEVICE];
+extern struct hfmodem_correlator_cache hfmodem_correlator_cache[HFMODEM_CORRELATOR_CACHE];
+
+/* --------------------------------------------------------------------- */
+#endif /* __KERNEL__ */
+/* --------------------------------------------------------------------- */
+#endif /* _HFMODEM_H */
diff --git a/pfinet/linux-src/include/linux/hfs_fs.h b/pfinet/linux-src/include/linux/hfs_fs.h
new file mode 100644
index 00000000..36cf43f5
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hfs_fs.h
@@ -0,0 +1,325 @@
+/*
+ * linux/include/linux/hfs_fs.h
+ *
+ * Copyright (C) 1995-1997 Paul H. Hargrove
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ * The source code distribution of the Columbia AppleTalk Package for
+ * UNIX, version 6.0, (CAP) was used as a specification of the
+ * location and format of files used by CAP's Aufs. No code from CAP
+ * appears in hfs_fs. hfs_fs is not a work ``derived'' from CAP in
+ * the sense of intellectual property law.
+ *
+ * The source code distributions of Netatalk, versions 1.3.3b2 and
+ * 1.4b2, were used as a specification of the location and format of
+ * files used by Netatalk's afpd. No code from Netatalk appears in
+ * hfs_fs. hfs_fs is not a work ``derived'' from Netatalk in the
+ * sense of intellectual property law.
+ */
+
+#ifndef _LINUX_HFS_FS_H
+#define _LINUX_HFS_FS_H
+
+#include <linux/hfs_sysdep.h>
+
+/* magic numbers for Apple Double header files */
+#define HFS_DBL_MAGIC 0x00051607
+#define HFS_SNGL_MAGIC 0x00051600
+#define HFS_HDR_VERSION_1 0x00010000
+#define HFS_HDR_VERSION_2 0x00020000
+
+/* magic numbers for various internal structures */
+#define HFS_INO_MAGIC 0x4821
+#define HFS_SB_MAGIC 0x4822
+
+/* The space used for the AppleDouble or AppleSingle headers */
+#define HFS_DBL_HDR_LEN 1024
+
+/* The space used for the Netatalk header */
+#define HFS_NAT_HDR_LEN 1024 /* 589 for an exact match */
+
+/* Macros to extract CNID and file "type" from the Linux inode number */
+#define HFS_CNID(X) ((X) & 0x3FFFFFFF)
+#define HFS_ITYPE(X) ((X) & 0xC0000000)
+
+/* Macros to enumerate types */
+#define HFS_ITYPE_TO_INT(X) ((X) >> 30)
+#define HFS_INT_TO_ITYPE(X) ((X) << 30)
+
+/* generic ITYPEs */
+#define HFS_ITYPE_0 0x00000000
+#define HFS_ITYPE_1 0x40000000
+#define HFS_ITYPE_2 0x80000000
+#define HFS_ITYPE_3 0xC0000000
+#define HFS_ITYPE_NORM HFS_ITYPE_0 /* "normal" directory or file */
+
+/* ITYPEs for CAP */
+#define HFS_CAP_NORM HFS_ITYPE_0 /* data fork or normal directory */
+#define HFS_CAP_DATA HFS_ITYPE_0 /* data fork of file */
+#define HFS_CAP_NDIR HFS_ITYPE_0 /* normal directory */
+#define HFS_CAP_FNDR HFS_ITYPE_1 /* finder info for file or dir */
+#define HFS_CAP_RSRC HFS_ITYPE_2 /* resource fork of file */
+#define HFS_CAP_RDIR HFS_ITYPE_2 /* .resource directory */
+#define HFS_CAP_FDIR HFS_ITYPE_3 /* .finderinfo directory */
+
+/* ITYPEs for Apple Double */
+#define HFS_DBL_NORM HFS_ITYPE_0 /* data fork or directory */
+#define HFS_DBL_DATA HFS_ITYPE_0 /* data fork of file */
+#define HFS_DBL_DIR HFS_ITYPE_0 /* directory */
+#define HFS_DBL_HDR HFS_ITYPE_1 /* AD header of file or dir */
+
+/* ITYPEs for netatalk */
+#define HFS_NAT_NORM HFS_ITYPE_0 /* data fork or directory */
+#define HFS_NAT_DATA HFS_ITYPE_0 /* data fork of file */
+#define HFS_NAT_NDIR HFS_ITYPE_0 /* normal directory */
+#define HFS_NAT_HDR HFS_ITYPE_1 /* AD header of file or dir */
+#define HFS_NAT_HDIR HFS_ITYPE_2 /* directory holding AD headers */
+
+/* ITYPEs for Apple Single */
+#define HFS_SGL_NORM HFS_ITYPE_0 /* AppleSingle file or directory */
+#define HFS_SGL_SNGL HFS_ITYPE_0 /* AppleSingle file */
+#define HFS_SGL_DIR HFS_ITYPE_0 /* directory */
+#define HFS_SGL_DINF HFS_ITYPE_1 /* %DirInfo for directory */
+
+/* IDs for elements of an AppleDouble or AppleSingle header */
+#define HFS_HDR_DATA 1 /* data fork */
+#define HFS_HDR_RSRC 2 /* resource fork */
+#define HFS_HDR_FNAME 3 /* full (31-character) name */
+#define HFS_HDR_COMNT 4 /* comment */
+#define HFS_HDR_BWICN 5 /* b/w icon */
+#define HFS_HDR_CICON 6 /* color icon info */
+#define HFS_HDR_OLDI 7 /* old file info */
+#define HFS_HDR_DATES 8 /* file dates info */
+#define HFS_HDR_FINFO 9 /* Finder info */
+#define HFS_HDR_MACI 10 /* Macintosh info */
+#define HFS_HDR_PRODOSI 11 /* ProDOS info */
+#define HFS_HDR_MSDOSI 12 /* MSDOS info */
+#define HFS_HDR_SNAME 13 /* short name */
+#define HFS_HDR_AFPI 14 /* AFP file info */
+#define HFS_HDR_DID 15 /* directory id */
+#define HFS_HDR_MAX 16
+
+/*
+ * There are three time systems. All three are based on seconds since
+ * a particular time/date.
+ * Unix: unsigned lil-endian since 00:00 GMT, Jan. 1, 1970
+ * mac: unsigned big-endian since 00:00 GMT, Jan. 1, 1904
+ * header: SIGNED big-endian since 00:00 GMT, Jan. 1, 2000
+ *
+ */
+#define hfs_h_to_mtime(ARG) htonl((hfs_s32)ntohl(ARG)+3029529600U)
+#define hfs_m_to_htime(ARG) ((hfs_s32)htonl(ntohl(ARG)-3029529600U))
+#define hfs_h_to_utime(ARG) ((hfs_s32)hfs_to_utc(ntohl(ARG)+946684800U))
+#define hfs_u_to_htime(ARG) ((hfs_s32)htonl(hfs_from_utc(ARG)-946684800U))
+#define hfs_u_to_mtime(ARG) htonl(hfs_from_utc(ARG)+2082844800U)
+#define hfs_m_to_utime(ARG) (hfs_to_utc(ntohl(ARG)-2082844800U))
+
+/*======== Data structures kept in memory ========*/
+
+/*
+ * A descriptor for a single entry within the header of an
+ * AppleDouble or AppleSingle header file.
+ * An array of these make up a table of contents for the file.
+ */
+struct hfs_hdr_descr {
+ hfs_u32 id; /* The Apple assigned ID for the entry type */
+ hfs_u32 offset; /* The offset to reach the entry */
+ hfs_u32 length; /* The length of the entry */
+};
+
+/*
+ * The info needed to reconstruct a given header layout
+ */
+struct hfs_hdr_layout {
+ hfs_u32 magic; /* AppleSingle or AppleDouble */
+ hfs_u32 version; /* 0x00010000 or 0x00020000 */
+ hfs_u16 entries; /* How many entries used */
+ struct hfs_hdr_descr
+ descr[HFS_HDR_MAX]; /* Descriptors */
+ struct hfs_hdr_descr
+ *order[HFS_HDR_MAX]; /* 'descr' ordered by offset */
+};
+
+/*
+ * Default header layout for Netatalk and AppleDouble
+ */
+struct hfs_dbl_hdr {
+ hfs_lword_t magic;
+ hfs_lword_t version;
+ hfs_byte_t filler[16];
+ hfs_word_t entries;
+ hfs_byte_t descrs[12*HFS_HDR_MAX];
+ hfs_byte_t real_name[255]; /* id=3 */
+ hfs_byte_t comment[200]; /* id=4 XXX: not yet implemented */
+ hfs_u32 create_time; /* \ */
+ hfs_u32 modify_time; /* | id=8 (or 7) */
+ hfs_u32 backup_time; /* | */
+ hfs_u32 access_time; /* / (attributes with id=7) */
+ hfs_u8 finderinfo[32]; /* id=9 */
+ hfs_u32 fileinfo; /* id=10 */
+ hfs_u32 cnid; /* id=15 */
+ hfs_u8 short_name[12]; /* id=13 */
+ hfs_u8 prodosi[8]; /* id=11 */
+};
+
+
+/* finder metadata for CAP */
+struct hfs_cap_info {
+ hfs_byte_t fi_fndr[32]; /* Finder's info */
+ hfs_word_t fi_attr; /* AFP attributes (f=file/d=dir) */
+#define HFS_AFP_INV 0x001 /* Invisible bit (f/d) */
+#define HFS_AFP_EXPFOLDER 0x002 /* exported folder (d) */
+#define HFS_AFP_MULTI 0x002 /* Multiuser bit (f) */
+#define HFS_AFP_SYS 0x004 /* System bit (f/d) */
+#define HFS_AFP_DOPEN 0x008 /* data fork already open (f) */
+#define HFS_AFP_MOUNTED 0x008 /* mounted folder (d) */
+#define HFS_AFP_ROPEN 0x010 /* resource fork already open (f) */
+#define HFS_AFP_INEXPFOLDER 0x010 /* folder in shared area (d) */
+#define HFS_AFP_WRI 0x020 /* Write inhibit bit (readonly) (f) */
+#define HFS_AFP_BACKUP 0x040 /* backup needed bit (f/d) */
+#define HFS_AFP_RNI 0x080 /* Rename inhibit bit (f/d) */
+#define HFS_AFP_DEI 0x100 /* Delete inhibit bit (f/d) */
+#define HFS_AFP_NOCOPY 0x400 /* Copy protect bit (f) */
+#define HFS_AFP_RDONLY ( HFS_AFP_WRI|HFS_AFP_RNI|HFS_AFP_DEI)
+ hfs_byte_t fi_magic1; /* Magic number: */
+#define HFS_CAP_MAGIC1 0xFF
+ hfs_byte_t fi_version; /* Version of this structure: */
+#define HFS_CAP_VERSION 0x10
+ hfs_byte_t fi_magic; /* Another magic number: */
+#define HFS_CAP_MAGIC 0xDA
+ hfs_byte_t fi_bitmap; /* Bitmap of which names are valid: */
+#define HFS_CAP_SHORTNAME 0x01
+#define HFS_CAP_LONGNAME 0x02
+ hfs_byte_t fi_shortfilename[12+1]; /* "short name" (unused) */
+ hfs_byte_t fi_macfilename[32+1]; /* Original (Macintosh) name */
+ hfs_byte_t fi_comln; /* Length of comment (always 0) */
+ hfs_byte_t fi_comnt[200]; /* Finder comment (unused) */
+ /* optional: used by aufs only if compiled with USE_MAC_DATES */
+ hfs_byte_t fi_datemagic; /* Magic number for dates extension: */
+#define HFS_CAP_DMAGIC 0xDA
+ hfs_byte_t fi_datevalid; /* Bitmap of which dates are valid: */
+#define HFS_CAP_MDATE 0x01
+#define HFS_CAP_CDATE 0x02
+ hfs_lword_t fi_ctime; /* Creation date (in AFP format) */
+ hfs_lword_t fi_mtime; /* Modify date (in AFP format) */
+ hfs_lword_t fi_utime; /* Un*x time of last mtime change */
+ hfs_byte_t pad;
+};
+
+#ifdef __KERNEL__
+
+typedef ssize_t hfs_rwret_t;
+typedef size_t hfs_rwarg_t;
+
+#include <asm/uaccess.h>
+
+/* Some forward declarations */
+struct hfs_fork;
+struct hfs_cat_key;
+struct hfs_cat_entry;
+extern struct hfs_cat_entry *hfs_cat_get(struct hfs_mdb *,
+ const struct hfs_cat_key *);
+
+/* dir.c */
+extern hfs_rwret_t hfs_dir_read(struct file *, char *, hfs_rwarg_t,
+ loff_t *);
+extern int hfs_create(struct inode *, struct dentry *, int);
+extern int hfs_mkdir(struct inode *, struct dentry *, int);
+extern int hfs_mknod(struct inode *, struct dentry *, int, int);
+extern int hfs_unlink(struct inode *, struct dentry *);
+extern int hfs_rmdir(struct inode *, struct dentry *);
+extern int hfs_rename(struct inode *, struct dentry *,
+ struct inode *, struct dentry *);
+
+/* dir_cap.c */
+extern const struct hfs_name hfs_cap_reserved1[];
+extern const struct hfs_name hfs_cap_reserved2[];
+extern struct inode_operations hfs_cap_ndir_inode_operations;
+extern struct inode_operations hfs_cap_fdir_inode_operations;
+extern struct inode_operations hfs_cap_rdir_inode_operations;
+extern void hfs_cap_drop_dentry(struct dentry *, const ino_t);
+
+/* dir_dbl.c */
+extern const struct hfs_name hfs_dbl_reserved1[];
+extern const struct hfs_name hfs_dbl_reserved2[];
+extern struct inode_operations hfs_dbl_dir_inode_operations;
+extern void hfs_dbl_drop_dentry(struct dentry *, const ino_t);
+
+/* dir_nat.c */
+extern const struct hfs_name hfs_nat_reserved1[];
+extern const struct hfs_name hfs_nat_reserved2[];
+extern struct inode_operations hfs_nat_ndir_inode_operations;
+extern struct inode_operations hfs_nat_hdir_inode_operations;
+extern void hfs_nat_drop_dentry(struct dentry *, const ino_t);
+
+/* dir_sngl.c */
+extern const struct hfs_name hfs_sngl_reserved1[];
+extern const struct hfs_name hfs_sngl_reserved2[];
+extern struct inode_operations hfs_sngl_dir_inode_operations;
+
+/* file.c */
+extern hfs_s32 hfs_do_read(struct inode *, struct hfs_fork *, hfs_u32,
+ char *, hfs_u32, int);
+extern hfs_s32 hfs_do_write(struct inode *, struct hfs_fork *, hfs_u32,
+ const char *, hfs_u32);
+extern void hfs_file_fix_mode(struct hfs_cat_entry *entry);
+extern struct inode_operations hfs_file_inode_operations;
+
+/* file_cap.c */
+extern struct inode_operations hfs_cap_info_inode_operations;
+
+/* file_hdr.c */
+extern struct inode_operations hfs_hdr_inode_operations;
+extern const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout;
+extern const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout;
+extern const struct hfs_hdr_layout hfs_nat_hdr_layout;
+extern const struct hfs_hdr_layout hfs_nat2_hdr_layout;
+extern const struct hfs_hdr_layout hfs_sngl_hdr_layout;
+
+/* inode.c */
+extern void hfs_put_inode(struct inode *);
+extern int hfs_notify_change(struct dentry *, struct iattr *);
+extern struct inode *hfs_iget(struct hfs_cat_entry *, ino_t, struct dentry *);
+
+extern void hfs_cap_ifill(struct inode *, ino_t, const int);
+extern void hfs_dbl_ifill(struct inode *, ino_t, const int);
+extern void hfs_nat_ifill(struct inode *, ino_t, const int);
+extern void hfs_sngl_ifill(struct inode *, ino_t, const int);
+
+/* super.c */
+extern struct super_block *hfs_read_super(struct super_block *,void *,int);
+extern int init_hfs_fs(void);
+
+/* trans.c */
+extern void hfs_colon2mac(struct hfs_name *, const char *, int);
+extern void hfs_prcnt2mac(struct hfs_name *, const char *, int);
+extern void hfs_triv2mac(struct hfs_name *, const char *, int);
+extern void hfs_latin2mac(struct hfs_name *, const char *, int);
+extern int hfs_mac2cap(char *, const struct hfs_name *);
+extern int hfs_mac2nat(char *, const struct hfs_name *);
+extern int hfs_mac2latin(char *, const struct hfs_name *);
+extern int hfs_mac2seven(char *, const struct hfs_name *);
+extern int hfs_mac2eight(char *, const struct hfs_name *);
+extern int hfs_mac2alpha(char *, const struct hfs_name *);
+extern int hfs_mac2triv(char *, const struct hfs_name *);
+extern void hfs_tolower(unsigned char *, int);
+
+#define HFS_I(X) (&((X)->u.hfs_i))
+#define HFS_SB(X) (&((X)->u.hfs_sb))
+
+extern __inline__ void hfs_nameout(struct inode *dir, struct hfs_name *out,
+ const char *in, int len) {
+ HFS_SB(dir->i_sb)->s_nameout(out, in, len);
+}
+
+extern __inline__ int hfs_namein(struct inode *dir, char *out,
+ const struct hfs_name *in) {
+ int len = HFS_SB(dir->i_sb)->s_namein(out, in);
+ if (HFS_SB(dir->i_sb)->s_lowercase) {
+ hfs_tolower(out, len);
+ }
+ return len;
+}
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/pfinet/linux-src/include/linux/hfs_fs_i.h b/pfinet/linux-src/include/linux/hfs_fs_i.h
new file mode 100644
index 00000000..03585a08
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hfs_fs_i.h
@@ -0,0 +1,43 @@
+/*
+ * linux/include/linux/hfs_fs_i.h
+ *
+ * Copyright (C) 1995, 1996 Paul H. Hargrove
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ * This file defines the type (struct hfs_inode_info) and the two
+ * subordinate types hfs_extent and hfs_file.
+ */
+
+#ifndef _LINUX_HFS_FS_I_H
+#define _LINUX_HFS_FS_I_H
+
+/*
+ * struct hfs_inode_info
+ *
+ * The HFS-specific part of a Linux (struct inode)
+ */
+struct hfs_inode_info {
+ int magic; /* A magic number */
+
+ struct hfs_cat_entry *entry;
+
+ /* For a regular or header file */
+ struct hfs_fork *fork;
+ int convert;
+
+ /* For a directory */
+ ino_t file_type;
+ char dir_size;
+
+ /* For header files */
+ const struct hfs_hdr_layout *default_layout;
+ struct hfs_hdr_layout *layout;
+
+ /* to deal with localtime ugliness */
+ int tz_secondswest;
+
+ /* for dentry cleanup */
+ void (*d_drop_op)(struct dentry *, const ino_t);
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/hfs_fs_sb.h b/pfinet/linux-src/include/linux/hfs_fs_sb.h
new file mode 100644
index 00000000..826f388c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hfs_fs_sb.h
@@ -0,0 +1,53 @@
+/*
+ * linux/include/linux/hfs_fs_sb.h
+ *
+ * Copyright (C) 1995-1997 Paul H. Hargrove
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ * This file defines the type (struct hfs_sb_info) which contains the
+ * HFS-specific information in the in-core superblock.
+ */
+
+#ifndef _LINUX_HFS_FS_SB_H
+#define _LINUX_HFS_FS_SB_H
+
+/* forward declaration: */
+struct hfs_name;
+
+typedef int (*hfs_namein_fn) (char *, const struct hfs_name *);
+typedef void (*hfs_nameout_fn) (struct hfs_name *, const char *, int);
+typedef void (*hfs_ifill_fn) (struct inode *, ino_t, const int);
+
+/*
+ * struct hfs_sb_info
+ *
+ * The HFS-specific part of a Linux (struct super_block)
+ */
+struct hfs_sb_info {
+ int magic; /* A magic number */
+ struct hfs_mdb *s_mdb; /* The HFS MDB */
+ int s_quiet; /* Silent failure when
+ changing owner or mode? */
+ int s_lowercase; /* Map names to lowercase? */
+ int s_afpd; /* AFPD compatible mode? */
+ int s_version; /* version info */
+ hfs_namein_fn s_namein; /* The function used to
+ map Mac filenames to
+ Linux filenames */
+ hfs_nameout_fn s_nameout; /* The function used to
+ map Linux filenames
+ to Mac filenames */
+ hfs_ifill_fn s_ifill; /* The function used
+ to fill in inode fields */
+ const struct hfs_name *s_reserved1; /* Reserved names */
+ const struct hfs_name *s_reserved2; /* Reserved names */
+ __u32 s_type; /* Type for new files */
+ __u32 s_creator; /* Creator for new files */
+ umode_t s_umask; /* The umask applied to the
+ permissions on all files */
+ uid_t s_uid; /* The uid of all files */
+ gid_t s_gid; /* The gid of all files */
+ char s_conv; /* Type of text conversion */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/hfs_sysdep.h b/pfinet/linux-src/include/linux/hfs_sysdep.h
new file mode 100644
index 00000000..00cc6400
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hfs_sysdep.h
@@ -0,0 +1,245 @@
+/*
+ * linux/include/linux/hfs_sysdep.h
+ *
+ * Copyright (C) 1996-1997 Paul H. Hargrove
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ * This file contains constants, types and inline
+ * functions for various system dependent things.
+ *
+ * "XXX" in a comment is a note to myself to consider changing something.
+ *
+ * In function preconditions the term "valid" applied to a pointer to
+ * a structure means that the pointer is non-NULL and the structure it
+ * points to has all fields initialized to consistent values.
+ */
+
+#ifndef _HFS_SYSDEP_H
+#define _HFS_SYSDEP_H
+
+#include <linux/malloc.h>
+#include <linux/types.h>
+#include <linux/locks.h>
+#include <linux/fs.h>
+
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+
+extern struct timezone sys_tz;
+
+#undef offsetof
+#define offsetof(TYPE, MEMB) ((size_t) &((TYPE *)0)->MEMB)
+
+/* Typedefs for integer types by size and signedness */
+typedef __u8 hfs_u8;
+typedef __u16 hfs_u16;
+typedef __u32 hfs_u32;
+typedef __s8 hfs_s8;
+typedef __s16 hfs_s16;
+typedef __s32 hfs_s32;
+
+/* Typedefs for unaligned integer types */
+typedef unsigned char hfs_byte_t;
+typedef unsigned char hfs_word_t[2];
+typedef unsigned char hfs_lword_t[4];
+
+/* these funny looking things are GCC variable argument macros */
+#define hfs_warn(format, args...) printk(KERN_WARNING format , ## args)
+#define hfs_error(format, args...) printk(KERN_ERR format , ## args)
+
+
+#if defined(DEBUG_ALL) || defined(DEBUG_MEM)
+extern long int hfs_alloc;
+#endif
+
+extern inline void *hfs_malloc(unsigned int size) {
+#if defined(DEBUG_ALL) || defined(DEBUG_MEM)
+ hfs_warn("%ld bytes allocation at %s:%u\n",
+ (hfs_alloc += size), __FILE__, __LINE__);
+#endif
+ return kmalloc(size, GFP_KERNEL);
+}
+
+extern inline void hfs_free(void *ptr, unsigned int size) {
+ kfree_s(ptr, size);
+#if defined(DEBUG_ALL) || defined(DEBUG_MEM)
+ hfs_warn("%ld bytes allocation at %s:%u\n",
+ (hfs_alloc -= ptr ? size : 0), __FILE__, __LINE__);
+#endif
+}
+
+
+/* handle conversion between times.
+ *
+ * NOTE: hfs+ doesn't need this. also, we don't use tz_dsttime as that's
+ * not a good thing to do. instead, we depend upon tz_minuteswest
+ * having the correct daylight savings correction.
+ */
+extern inline hfs_u32 hfs_from_utc(hfs_s32 time)
+{
+ return time - sys_tz.tz_minuteswest*60;
+}
+
+extern inline hfs_s32 hfs_to_utc(hfs_u32 time)
+{
+ return time + sys_tz.tz_minuteswest*60;
+}
+
+extern inline hfs_u32 hfs_time(void) {
+ return htonl(hfs_from_utc(CURRENT_TIME)+2082844800U);
+}
+
+
+/*
+ * hfs_wait_queue
+ */
+typedef struct wait_queue *hfs_wait_queue;
+
+extern inline void hfs_init_waitqueue(hfs_wait_queue *queue) {
+ init_waitqueue(queue);
+}
+
+extern inline void hfs_sleep_on(hfs_wait_queue *queue) {
+ sleep_on(queue);
+}
+
+extern inline void hfs_wake_up(hfs_wait_queue *queue) {
+ wake_up(queue);
+}
+
+extern inline void hfs_relinquish(void) {
+ schedule();
+}
+
+
+/*
+ * hfs_sysmdb
+ */
+typedef struct super_block *hfs_sysmdb;
+
+extern inline void hfs_mdb_dirty(hfs_sysmdb sys_mdb) {
+ sys_mdb->s_dirt = 1;
+}
+
+extern inline char *hfs_mdb_name(hfs_sysmdb sys_mdb) {
+ return kdevname(sys_mdb->s_dev);
+}
+
+
+/*
+ * hfs_sysentry
+ */
+typedef struct dentry *hfs_sysentry[4];
+
+/*
+ * hfs_buffer
+ */
+typedef struct buffer_head *hfs_buffer;
+
+#define HFS_BAD_BUFFER NULL
+
+/* In sysdep.c, since it needs HFS_SECTOR_SIZE */
+extern hfs_buffer hfs_buffer_get(hfs_sysmdb, int, int);
+
+extern inline int hfs_buffer_ok(hfs_buffer buffer) {
+ return (buffer != NULL);
+}
+
+extern inline void hfs_buffer_put(hfs_buffer buffer) {
+ brelse(buffer);
+}
+
+extern inline void hfs_buffer_dirty(hfs_buffer buffer) {
+ mark_buffer_dirty(buffer, 1);
+}
+
+extern inline void hfs_buffer_sync(hfs_buffer buffer) {
+ while (buffer_locked(buffer)) {
+ wait_on_buffer(buffer);
+ }
+ if (buffer_dirty(buffer)) {
+ ll_rw_block(WRITE, 1, &buffer);
+ wait_on_buffer(buffer);
+ }
+}
+
+extern inline void *hfs_buffer_data(const hfs_buffer buffer) {
+ return buffer->b_data;
+}
+
+
+/*
+ * bit operations
+ */
+
+#undef BITNR
+#if defined(__BIG_ENDIAN)
+# define BITNR(X) ((X)^31)
+# if !defined(__constant_htonl)
+# define __constant_htonl(x) (x)
+# endif
+# if !defined(__constant_htons)
+# define __constant_htons(x) (x)
+# endif
+#elif defined(__LITTLE_ENDIAN)
+# define BITNR(X) ((X)^7)
+# if !defined(__constant_htonl)
+# define __constant_htonl(x) \
+ ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
+ (((unsigned long int)(x) & 0x0000ff00U) << 8) | \
+ (((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
+ (((unsigned long int)(x) & 0xff000000U) >> 24)))
+# endif
+# if !defined(__constant_htons)
+# define __constant_htons(x) \
+ ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
+ (((unsigned short int)(x) & 0xff00) >> 8)))
+# endif
+#else
+# error "Don't know if bytes are big- or little-endian!"
+#endif
+
+extern inline int hfs_clear_bit(int bitnr, hfs_u32 *lword) {
+ return test_and_clear_bit(BITNR(bitnr), lword);
+}
+
+extern inline int hfs_set_bit(int bitnr, hfs_u32 *lword) {
+ return test_and_set_bit(BITNR(bitnr), lword);
+}
+
+extern inline int hfs_test_bit(int bitnr, const hfs_u32 *lword) {
+ /* the kernel should declare the second arg of test_bit as const */
+ return test_bit(BITNR(bitnr), (void *)lword);
+}
+
+#undef BITNR
+
+/*
+ * HFS structures have fields aligned to 16-bit boundaries.
+ * So, 16-bit get/put are easy while 32-bit get/put need
+ * some care on architectures like the DEC Alpha.
+ *
+ * In what follows:
+ * ns = 16-bit integer in network byte-order w/ 16-bit alignment
+ * hs = 16-bit integer in host byte-order w/ 16-bit alignment
+ * nl = 32-bit integer in network byte-order w/ unknown alignment
+ * hl = 32-bit integer in host byte-order w/ unknown alignment
+ * anl = 32-bit integer in network byte-order w/ 32-bit alignment
+ * ahl = 32-bit integer in host byte-order w/ 32-bit alignment
+ * Example: hfs_get_hl() gets an unaligned 32-bit integer converting
+ * it to host byte-order.
+ */
+#define hfs_get_hs(addr) ntohs(*((hfs_u16 *)(addr)))
+#define hfs_get_ns(addr) (*((hfs_u16 *)(addr)))
+#define hfs_get_hl(addr) ntohl(get_unaligned((hfs_u32 *)(addr)))
+#define hfs_get_nl(addr) get_unaligned((hfs_u32 *)(addr))
+#define hfs_get_ahl(addr) ntohl(*((hfs_u32 *)(addr)))
+#define hfs_get_anl(addr) (*((hfs_u32 *)(addr)))
+#define hfs_put_hs(val, addr) ((void)(*((hfs_u16 *)(addr)) = ntohs(val)))
+#define hfs_put_ns(val, addr) ((void)(*((hfs_u16 *)(addr)) = (val)))
+#define hfs_put_hl(val, addr) put_unaligned(htonl(val), (hfs_u32 *)(addr))
+#define hfs_put_nl(val, addr) put_unaligned((val), (hfs_u32 *)(addr))
+#define hfs_put_ahl(val, addr) ((void)(*((hfs_u32 *)(addr)) = ntohl(val)))
+#define hfs_put_anl(val, addr) ((void)(*((hfs_u32 *)(addr)) = (val)))
+
+#endif
diff --git a/pfinet/linux-src/include/linux/hippidevice.h b/pfinet/linux-src/include/linux/hippidevice.h
new file mode 100644
index 00000000..e345a9d2
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hippidevice.h
@@ -0,0 +1,58 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the HIPPI handlers.
+ *
+ * Version: @(#)hippidevice.h 1.0.0 05/26/97
+ *
+ * Author: Jes Sorensen, <Jes.Sorensen@cern.ch>
+ *
+ * hippidevice.h is based on previous fddidevice.h work by
+ * Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Lawrence V. Stefani, <stefani@lkg.dec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_HIPPIDEVICE_H
+#define _LINUX_HIPPIDEVICE_H
+
+#include <linux/if_hippi.h>
+
+#ifdef __KERNEL__
+extern int hippi_header(struct sk_buff *skb,
+ struct device *dev,
+ unsigned short type,
+ void *daddr,
+ void *saddr,
+ unsigned len);
+
+extern int hippi_rebuild_header(struct sk_buff *skb);
+
+extern unsigned short hippi_type_trans(struct sk_buff *skb,
+ struct device *dev);
+
+extern void hippi_header_cache_bind(struct hh_cache ** hhp,
+ struct device *dev,
+ unsigned short htype,
+ __u32 daddr);
+
+extern void hippi_header_cache_update(struct hh_cache *hh,
+ struct device *dev,
+ unsigned char * haddr);
+extern int hippi_header_parse(struct sk_buff *skb, unsigned char *haddr);
+
+extern void hippi_net_init(void);
+void hippi_setup(struct device *dev);
+
+extern struct device *init_hippi_dev(struct device *, int);
+extern void unregister_hipdev(struct device *dev);
+#endif
+
+#endif /* _LINUX_HIPPIDEVICE_H */
diff --git a/pfinet/linux-src/include/linux/hpfs_fs.h b/pfinet/linux-src/include/linux/hpfs_fs.h
new file mode 100644
index 00000000..2b7926ab
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hpfs_fs.h
@@ -0,0 +1,13 @@
+#ifndef _LINUX_HPFS_FS_H
+#define _LINUX_HPFS_FS_H
+
+/* HPFS magic number (word 0 of block 16) */
+
+#define HPFS_SUPER_MAGIC 0xf995e849
+
+/* The entry point for a VFS */
+
+extern struct super_block *hpfs_read_super (struct super_block *, void *, int);
+extern int init_hpfs_fs(void);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/hpfs_fs_i.h b/pfinet/linux-src/include/linux/hpfs_fs_i.h
new file mode 100644
index 00000000..d9aa8f34
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hpfs_fs_i.h
@@ -0,0 +1,24 @@
+#ifndef _HPFS_FS_I
+#define _HPFS_FS_I
+
+struct hpfs_inode_info {
+ ino_t i_parent_dir; /* (directories) gives fnode of parent dir */
+ unsigned i_dno; /* (directories) root dnode */
+ unsigned i_dpos; /* (directories) temp for readdir */
+ unsigned i_dsubdno; /* (directories) temp for readdir */
+ unsigned i_file_sec; /* (files) minimalist cache of alloc info */
+ unsigned i_disk_sec; /* (files) minimalist cache of alloc info */
+ unsigned i_n_secs; /* (files) minimalist cache of alloc info */
+ unsigned i_conv : 2; /* (files) crlf->newline hackery */
+};
+
+#define i_hpfs_dno u.hpfs_i.i_dno
+#define i_hpfs_parent_dir u.hpfs_i.i_parent_dir
+#define i_hpfs_n_secs u.hpfs_i.i_n_secs
+#define i_hpfs_file_sec u.hpfs_i.i_file_sec
+#define i_hpfs_disk_sec u.hpfs_i.i_disk_sec
+#define i_hpfs_dpos u.hpfs_i.i_dpos
+#define i_hpfs_dsubdno u.hpfs_i.i_dsubdno
+#define i_hpfs_conv u.hpfs_i.i_conv
+
+#endif
diff --git a/pfinet/linux-src/include/linux/hpfs_fs_sb.h b/pfinet/linux-src/include/linux/hpfs_fs_sb.h
new file mode 100644
index 00000000..a383e16b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/hpfs_fs_sb.h
@@ -0,0 +1,32 @@
+#ifndef _HPFS_FS_SB
+#define _HPFS_FS_SB
+
+struct hpfs_sb_info {
+ ino_t sb_root; /* inode number of root dir */
+ unsigned sb_fs_size; /* file system size, sectors */
+ unsigned sb_bitmaps; /* sector number of bitmap list */
+ unsigned sb_dirband_size; /* directory band size, dnodes */
+ unsigned sb_dmap; /* sector number of dnode bit map */
+ unsigned sb_n_free; /* free blocks for statfs, or -1 */
+ unsigned sb_n_free_dnodes; /* free dnodes for statfs, or -1 */
+ uid_t sb_uid; /* uid from mount options */
+ gid_t sb_gid; /* gid from mount options */
+ umode_t sb_mode; /* mode from mount options */
+ unsigned sb_lowercase : 1; /* downcase filenames hackery */
+ unsigned sb_conv : 2; /* crlf->newline hackery */
+};
+
+#define s_hpfs_root u.hpfs_sb.sb_root
+#define s_hpfs_fs_size u.hpfs_sb.sb_fs_size
+#define s_hpfs_bitmaps u.hpfs_sb.sb_bitmaps
+#define s_hpfs_dirband_size u.hpfs_sb.sb_dirband_size
+#define s_hpfs_dmap u.hpfs_sb.sb_dmap
+#define s_hpfs_uid u.hpfs_sb.sb_uid
+#define s_hpfs_gid u.hpfs_sb.sb_gid
+#define s_hpfs_mode u.hpfs_sb.sb_mode
+#define s_hpfs_n_free u.hpfs_sb.sb_n_free
+#define s_hpfs_n_free_dnodes u.hpfs_sb.sb_n_free_dnodes
+#define s_hpfs_lowercase u.hpfs_sb.sb_lowercase
+#define s_hpfs_conv u.hpfs_sb.sb_conv
+
+#endif
diff --git a/pfinet/linux-src/include/linux/i2c.h b/pfinet/linux-src/include/linux/i2c.h
new file mode 100644
index 00000000..273b2a71
--- /dev/null
+++ b/pfinet/linux-src/include/linux/i2c.h
@@ -0,0 +1,188 @@
+#ifndef I2C_H
+#define I2C_H
+
+/*
+ * linux i2c interface. Works a little bit like the scsi subsystem.
+ * There are:
+ *
+ * i2c the basic control module (like scsi_mod)
+ * bus driver a driver with a i2c bus (hostadapter driver)
+ * chip driver a driver for a chip connected
+ * to a i2c bus (cdrom/hd driver)
+ *
+ * A device will be attached to one bus and one chip driver. Every chip
+ * driver gets a unique ID.
+ *
+ * A chip driver can provide a ioctl-like callback for the
+ * communication with other parts of the kernel (not every i2c chip is
+ * useful without other devices, a TV card tuner for example).
+ *
+ * "i2c internal" parts of the structs: only the i2c module is allowed to
+ * write to them, for others they are read-only.
+ *
+ */
+
+#define I2C_BUS_MAX 4 /* max # of bus drivers */
+#define I2C_DRIVER_MAX 8 /* max # of chip drivers */
+#define I2C_DEVICE_MAX 8 /* max # if devices per bus/driver */
+
+struct i2c_bus;
+struct i2c_driver;
+struct i2c_device;
+
+#define I2C_DRIVERID_MSP3400 1
+#define I2C_DRIVERID_TUNER 2
+#define I2C_DRIVERID_VIDEOTEXT 3
+#define I2C_DRIVERID_VIDEODECODER 4
+#define I2C_DRIVERID_VIDEOENCODER 5
+
+#define I2C_BUSID_BT848 1 /* I2C bus on a BT848 */
+ /* 2 is used in 2.3.x */
+#define I2C_BUSID_BUZ 3 /* I2C bus on a BUZ */
+
+/*
+ * struct for a driver for a i2c chip (tuner, soundprocessor,
+ * videotext, ... ).
+ *
+ * a driver will register within the i2c module. The i2c module will
+ * callback the driver (i2c_attach) for every device it finds on a i2c
+ * bus at the specified address. If the driver decides to "accept"
+ * the, device, it must return a struct i2c_device, and NULL
+ * otherwise.
+ *
+ * i2c_detach = i2c_attach ** -1
+ *
+ * i2c_command will be used to pass commands to the driver in a
+ * ioctl-line manner.
+ *
+ */
+
+struct i2c_driver
+{
+ char name[32]; /* some useful label */
+ int id; /* device type ID */
+ unsigned char addr_l, addr_h; /* address range of the chip */
+
+ int (*attach)(struct i2c_device *device);
+ int (*detach)(struct i2c_device *device);
+ int (*command)(struct i2c_device *device,unsigned int cmd, void *arg);
+
+ /* i2c internal */
+ struct i2c_device *devices[I2C_DEVICE_MAX];
+ int devcount;
+};
+
+
+/*
+ * this holds the informations about a i2c bus available in the system.
+ *
+ * a chip with a i2c bus interface (like bt848) registers the bus within
+ * the i2c module. This struct provides functions to access the i2c bus.
+ *
+ * One must hold the spinlock to access the i2c bus (XXX: is the irqsave
+ * required? Maybe better use a semaphore?).
+ * [-AC-] having a spinlock_irqsave is only needed if we have drivers wishing
+ * to bang their i2c bus from an interrupt.
+ *
+ * attach/detach_inform is a callback to inform the bus driver about
+ * attached chip drivers.
+ *
+ */
+
+/* needed: unsigned long flags */
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= 0x020100
+# if 0
+# define LOCK_FLAGS unsigned long flags;
+# define LOCK_I2C_BUS(bus) spin_lock_irqsave(&(bus->bus_lock),flags);
+# define UNLOCK_I2C_BUS(bus) spin_unlock_irqrestore(&(bus->bus_lock),flags);
+# else
+# define LOCK_FLAGS
+# define LOCK_I2C_BUS(bus) spin_lock(&(bus->bus_lock));
+# define UNLOCK_I2C_BUS(bus) spin_unlock(&(bus->bus_lock));
+# endif
+#else
+# define LOCK_FLAGS unsigned long flags;
+# define LOCK_I2C_BUS(bus) { save_flags(flags); cli(); }
+# define UNLOCK_I2C_BUS(bus) { restore_flags(flags); }
+#endif
+
+struct i2c_bus
+{
+ char name[32]; /* some useful label */
+ int id;
+ void *data; /* free for use by the bus driver */
+
+#if LINUX_VERSION_CODE >= 0x020100
+ spinlock_t bus_lock;
+#endif
+
+ /* attach/detach inform callbacks */
+ void (*attach_inform)(struct i2c_bus *bus, int id);
+ void (*detach_inform)(struct i2c_bus *bus, int id);
+
+ /* Software I2C */
+ void (*i2c_setlines)(struct i2c_bus *bus, int ctrl, int data);
+ int (*i2c_getdataline)(struct i2c_bus *bus);
+
+ /* Hardware I2C */
+ int (*i2c_read)(struct i2c_bus *bus, unsigned char addr);
+ int (*i2c_write)(struct i2c_bus *bus, unsigned char addr,
+ unsigned char b1, unsigned char b2, int both);
+
+ /* internal data for i2c module */
+ struct i2c_device *devices[I2C_DEVICE_MAX];
+ int devcount;
+};
+
+
+/*
+ * This holds per-device data for a i2c device
+ */
+
+struct i2c_device
+{
+ char name[32]; /* some useful label */
+ void *data; /* free for use by the chip driver */
+ unsigned char addr; /* chip addr */
+
+ /* i2c internal */
+ struct i2c_bus *bus;
+ struct i2c_driver *driver;
+};
+
+
+/* ------------------------------------------------------------------- */
+/* i2c module functions */
+
+/* register/unregister a i2c bus */
+int i2c_register_bus(struct i2c_bus *bus);
+int i2c_unregister_bus(struct i2c_bus *bus);
+
+/* register/unregister a chip driver */
+int i2c_register_driver(struct i2c_driver *driver);
+int i2c_unregister_driver(struct i2c_driver *driver);
+
+/* send a command to a chip using the ioctl-like callback interface */
+int i2c_control_device(struct i2c_bus *bus, int id,
+ unsigned int cmd, void *arg);
+
+/* i2c bus access functions */
+void i2c_start(struct i2c_bus *bus);
+void i2c_stop(struct i2c_bus *bus);
+void i2c_one(struct i2c_bus *bus);
+void i2c_zero(struct i2c_bus *bus);
+int i2c_ack(struct i2c_bus *bus);
+
+int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack);
+unsigned char i2c_readbyte(struct i2c_bus *bus,int last);
+
+/* i2c (maybe) hardware functions */
+int i2c_read(struct i2c_bus *bus, unsigned char addr);
+int i2c_write(struct i2c_bus *bus, unsigned char addr,
+ unsigned char b1, unsigned char b2, int both);
+
+int i2c_init(void);
+#endif /* I2C_H */
diff --git a/pfinet/linux-src/include/linux/icmp.h b/pfinet/linux-src/include/linux/icmp.h
new file mode 100644
index 00000000..fb4ed8b9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/icmp.h
@@ -0,0 +1,102 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the ICMP protocol.
+ *
+ * Version: @(#)icmp.h 1.0.3 04/28/93
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_ICMP_H
+#define _LINUX_ICMP_H
+
+#define ICMP_ECHOREPLY 0 /* Echo Reply */
+#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
+#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
+#define ICMP_REDIRECT 5 /* Redirect (change route) */
+#define ICMP_ECHO 8 /* Echo Request */
+#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
+#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
+#define ICMP_TIMESTAMP 13 /* Timestamp Request */
+#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
+#define ICMP_INFO_REQUEST 15 /* Information Request */
+#define ICMP_INFO_REPLY 16 /* Information Reply */
+#define ICMP_ADDRESS 17 /* Address Mask Request */
+#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
+#define NR_ICMP_TYPES 18
+
+
+/* Codes for UNREACH. */
+#define ICMP_NET_UNREACH 0 /* Network Unreachable */
+#define ICMP_HOST_UNREACH 1 /* Host Unreachable */
+#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
+#define ICMP_PORT_UNREACH 3 /* Port Unreachable */
+#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
+#define ICMP_SR_FAILED 5 /* Source Route failed */
+#define ICMP_NET_UNKNOWN 6
+#define ICMP_HOST_UNKNOWN 7
+#define ICMP_HOST_ISOLATED 8
+#define ICMP_NET_ANO 9
+#define ICMP_HOST_ANO 10
+#define ICMP_NET_UNR_TOS 11
+#define ICMP_HOST_UNR_TOS 12
+#define ICMP_PKT_FILTERED 13 /* Packet filtered */
+#define ICMP_PREC_VIOLATION 14 /* Precedence violation */
+#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
+#define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */
+
+/* Codes for REDIRECT. */
+#define ICMP_REDIR_NET 0 /* Redirect Net */
+#define ICMP_REDIR_HOST 1 /* Redirect Host */
+#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
+#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
+
+/* Codes for TIME_EXCEEDED. */
+#define ICMP_EXC_TTL 0 /* TTL count exceeded */
+#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */
+
+
+struct icmphdr {
+ __u8 type;
+ __u8 code;
+ __u16 checksum;
+ union {
+ struct {
+ __u16 id;
+ __u16 sequence;
+ } echo;
+ __u32 gateway;
+ struct {
+ __u16 __unused;
+ __u16 mtu;
+ } frag;
+ } un;
+};
+
+#ifdef __KERNEL__
+
+struct icmp_err {
+ int errno;
+ unsigned fatal:1;
+};
+#endif
+
+/*
+ * constants for (set|get)sockopt
+ */
+
+#define ICMP_FILTER 1
+
+struct icmp_filter {
+ __u32 data;
+};
+
+
+#endif /* _LINUX_ICMP_H */
diff --git a/pfinet/linux-src/include/linux/icmpv6.h b/pfinet/linux-src/include/linux/icmpv6.h
new file mode 100644
index 00000000..fcd6fce2
--- /dev/null
+++ b/pfinet/linux-src/include/linux/icmpv6.h
@@ -0,0 +1,149 @@
+#ifndef _LINUX_ICMPV6_H
+#define _LINUX_ICMPV6_H
+
+#include <asm/byteorder.h>
+
+struct icmp6hdr {
+
+ __u8 icmp6_type;
+ __u8 icmp6_code;
+ __u16 icmp6_cksum;
+
+
+ union {
+ __u32 un_data32[1];
+ __u16 un_data16[2];
+ __u8 un_data8[4];
+
+ struct icmpv6_echo {
+ __u16 identifier;
+ __u16 sequence;
+ } u_echo;
+
+ struct icmpv6_nd_advt {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u32 reserved:5,
+ override:1,
+ solicited:1,
+ router:1,
+ reserved2:24;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u32 router:1,
+ solicited:1,
+ override:1,
+ reserved:29;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ } u_nd_advt;
+
+ struct icmpv6_nd_ra {
+ __u8 hop_limit;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 reserved:6,
+ other:1,
+ managed:1;
+
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 managed:1,
+ other:1,
+ reserved:6;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __u16 rt_lifetime;
+ } u_nd_ra;
+
+ } icmp6_dataun;
+
+#define icmp6_identifier icmp6_dataun.u_echo.identifier
+#define icmp6_sequence icmp6_dataun.u_echo.sequence
+#define icmp6_pointer icmp6_dataun.un_data32[0]
+#define icmp6_mtu icmp6_dataun.un_data32[0]
+#define icmp6_unused icmp6_dataun.un_data32[0]
+#define icmp6_maxdelay icmp6_dataun.un_data16[0]
+#define icmp6_router icmp6_dataun.u_nd_advt.router
+#define icmp6_solicited icmp6_dataun.u_nd_advt.solicited
+#define icmp6_override icmp6_dataun.u_nd_advt.override
+#define icmp6_ndiscreserved icmp6_dataun.u_nd_advt.reserved
+#define icmp6_hop_limit icmp6_dataun.u_nd_ra.hop_limit
+#define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed
+#define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other
+#define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime
+};
+
+
+#define ICMPV6_DEST_UNREACH 1
+#define ICMPV6_PKT_TOOBIG 2
+#define ICMPV6_TIME_EXCEED 3
+#define ICMPV6_PARAMPROB 4
+
+#define ICMPV6_INFOMSG_MASK 0x80
+
+#define ICMPV6_ECHO_REQUEST 128
+#define ICMPV6_ECHO_REPLY 129
+#define ICMPV6_MGM_QUERY 130
+#define ICMPV6_MGM_REPORT 131
+#define ICMPV6_MGM_REDUCTION 132
+
+/*
+ * Codes for Destination Unreachable
+ */
+#define ICMPV6_NOROUTE 0
+#define ICMPV6_ADM_PROHIBITED 1
+#define ICMPV6_NOT_NEIGHBOUR 2
+#define ICMPV6_ADDR_UNREACH 3
+#define ICMPV6_PORT_UNREACH 4
+
+/*
+ * Codes for Time Exceeded
+ */
+#define ICMPV6_EXC_HOPLIMIT 0
+#define ICMPV6_EXC_FRAGTIME 1
+
+/*
+ * Codes for Parameter Problem
+ */
+#define ICMPV6_HDR_FIELD 0
+#define ICMPV6_UNK_NEXTHDR 1
+#define ICMPV6_UNK_OPTION 2
+
+/*
+ * constants for (set|get)sockopt
+ */
+
+#define ICMPV6_FILTER 1
+
+/*
+ * ICMPV6 filter
+ */
+
+#define ICMPV6_FILTER_BLOCK 1
+#define ICMPV6_FILTER_PASS 2
+#define ICMPV6_FILTER_BLOCKOTHERS 3
+#define ICMPV6_FILTER_PASSONLY 4
+
+struct icmp6_filter {
+ __u32 data[8];
+};
+
+#ifdef __KERNEL__
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+
+
+extern void icmpv6_send(struct sk_buff *skb,
+ int type, int code,
+ __u32 info,
+ struct device *dev);
+
+extern int icmpv6_init(struct net_proto_family *ops);
+extern int icmpv6_err_convert(int type, int code,
+ int *err);
+extern void icmpv6_cleanup(void);
+extern void icmpv6_param_prob(struct sk_buff *skb,
+ int code, void *pos);
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if.h b/pfinet/linux-src/include/linux/if.h
new file mode 100644
index 00000000..cd5f3139
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if.h
@@ -0,0 +1,163 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the INET interface module.
+ *
+ * Version: @(#)if.h 1.0.2 04/18/93
+ *
+ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
+ * Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_H
+#define _LINUX_IF_H
+
+#include <linux/types.h> /* for "__kernel_caddr_t" et al */
+#include <linux/socket.h> /* for "struct sockaddr" et al */
+
+/* Standard interface flags. */
+#define IFF_UP 0x1 /* interface is up */
+#define IFF_BROADCAST 0x2 /* broadcast address valid */
+#define IFF_DEBUG 0x4 /* turn on debugging */
+#define IFF_LOOPBACK 0x8 /* is a loopback net */
+#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
+#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
+#define IFF_RUNNING 0x40 /* resources allocated */
+#define IFF_NOARP 0x80 /* no ARP protocol */
+#define IFF_PROMISC 0x100 /* receive all packets */
+#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
+
+#define IFF_MASTER 0x400 /* master of a load balancer */
+#define IFF_SLAVE 0x800 /* slave of a load balancer */
+
+#define IFF_MULTICAST 0x1000 /* Supports multicast */
+
+#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ALLMULTI)
+
+#define IFF_PORTSEL 0x2000 /* can set media type */
+#define IFF_AUTOMEDIA 0x4000 /* auto media select active */
+#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
+
+#ifdef __KERNEL__
+/*
+ * The ifaddr structure contains information about one address
+ * of an interface. They are maintained by the different address
+ * families, are allocated and attached when an address is set,
+ * and are linked together so all addresses for an interface can
+ * be located.
+ */
+
+struct ifaddr
+{
+ struct sockaddr ifa_addr; /* address of interface */
+ union {
+ struct sockaddr ifu_broadaddr;
+ struct sockaddr ifu_dstaddr;
+ } ifa_ifu;
+ struct iface *ifa_ifp; /* back-pointer to interface */
+ struct ifaddr *ifa_next; /* next address for interface */
+};
+
+#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */
+#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */
+
+#endif /* __KERNEL__ */
+
+/*
+ * Device mapping structure. I'd just gone off and designed a
+ * beautiful scheme using only loadable modules with arguments
+ * for driver options and along come the PCMCIA people 8)
+ *
+ * Ah well. The get() side of this is good for WDSETUP, and it'll
+ * be handy for debugging things. The set side is fine for now and
+ * being very small might be worth keeping for clean configuration.
+ */
+
+struct ifmap
+{
+ unsigned long mem_start;
+ unsigned long mem_end;
+ unsigned short base_addr;
+ unsigned char irq;
+ unsigned char dma;
+ unsigned char port;
+ /* 3 bytes spare */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's. All interface ioctl's must have parameter
+ * definitions which begin with ifr_name. The
+ * remainder may be interface specific.
+ */
+
+struct ifreq
+{
+#define IFHWADDRLEN 6
+#define IFNAMSIZ 16
+ union
+ {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ } ifr_ifrn;
+
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ short ifru_flags;
+ int ifru_ivalue;
+ int ifru_mtu;
+ struct ifmap ifru_map;
+ char ifru_slave[IFNAMSIZ]; /* Just fits the size */
+ char ifru_newname[IFNAMSIZ];
+ char * ifru_data;
+ } ifr_ifru;
+};
+
+#define ifr_name ifr_ifrn.ifrn_name /* interface name */
+#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
+#define ifr_addr ifr_ifru.ifru_addr /* address */
+#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
+#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_metric ifr_ifru.ifru_ivalue /* metric */
+#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+#define ifr_map ifr_ifru.ifru_map /* device map */
+#define ifr_slave ifr_ifru.ifru_slave /* slave device */
+#define ifr_data ifr_ifru.ifru_data /* for use by interface */
+#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
+#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
+#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */
+#define ifr_newname ifr_ifru.ifru_newname /* New name */
+
+/*
+ * Structure used in SIOCGIFCONF request.
+ * Used to retrieve interface configuration
+ * for machine (useful for programs which
+ * must know all networks accessible).
+ */
+
+struct ifconf
+{
+ int ifc_len; /* size of buffer */
+ union
+ {
+ char * ifcu_buf;
+ struct ifreq *ifcu_req;
+ } ifc_ifcu;
+};
+#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
+#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
+
+
+#endif /* _LINUX_IF_H */
diff --git a/pfinet/linux-src/include/linux/if_arcnet.h b/pfinet/linux-src/include/linux/if_arcnet.h
new file mode 100644
index 00000000..8b2ba0aa
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_arcnet.h
@@ -0,0 +1,63 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the ARCnet interface.
+ *
+ * Version: $Id: if_arcnet.h,v 1.2 1997/09/05 08:57:54 mj Exp $
+ *
+ * Author: David Woodhouse <dwmw2@cam.ac.uk>
+ * Avery Pennarun <apenwarr@bond.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_IF_ARCNET_H
+#define _LINUX_IF_ARCNET_H
+
+
+/*
+ * These are the defined ARCnet Protocol ID's.
+ */
+
+ /* RFC1201 Protocol ID's */
+#define ARC_P_IP 212 /* 0xD4 */
+#define ARC_P_ARP 213 /* 0xD5 */
+#define ARC_P_RARP 214 /* 0xD6 */
+#define ARC_P_IPX 250 /* 0xFA */
+#define ARC_P_NOVELL_EC 236 /* 0xEC */
+
+ /* Old RFC1051 Protocol ID's */
+#define ARC_P_IP_RFC1051 240 /* 0xF0 */
+#define ARC_P_ARP_RFC1051 241 /* 0xF1 */
+
+ /* MS LanMan/WfWg protocol */
+#define ARC_P_ETHER 0xE8
+
+ /* Unsupported/indirectly supported protocols */
+#define ARC_P_DATAPOINT_BOOT 0 /* very old Datapoint equipment */
+#define ARC_P_DATAPOINT_MOUNT 1
+#define ARC_P_POWERLAN_BEACON 8 /* Probably ATA-Netbios related */
+#define ARC_P_POWERLAN_BEACON2 243
+#define ARC_P_LANSOFT 251 /* 0xFB - what is this? */
+#define ARC_P_ATALK 0xDD
+
+
+/*
+ * This is an ARCnet frame header.
+ */
+
+struct archdr /* was struct HardHeader */
+{
+ u_char source, /* source ARCnet - filled in automagically */
+ destination, /* destination ARCnet - 0 for broadcast */
+ offset1, /* offset of ClientData (256-byte packets) */
+ offset2; /* offset of ClientData (512-byte packets) */
+
+};
+
+#endif /* _LINUX_IF_ARCNET_H */
diff --git a/pfinet/linux-src/include/linux/if_arp.h b/pfinet/linux-src/include/linux/if_arp.h
new file mode 100644
index 00000000..39007c8b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_arp.h
@@ -0,0 +1,133 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the ARP (RFC 826) protocol.
+ *
+ * Version: @(#)if_arp.h 1.0.1 04/16/93
+ *
+ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988
+ * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source.
+ * Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Florian La Roche,
+ * Jonathan Layes <layes@loran.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_ARP_H
+#define _LINUX_IF_ARP_H
+
+#include <linux/netdevice.h>
+
+/* ARP protocol HARDWARE identifiers. */
+#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
+#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
+#define ARPHRD_EETHER 2 /* Experimental Ethernet */
+#define ARPHRD_AX25 3 /* AX.25 Level 2 */
+#define ARPHRD_PRONET 4 /* PROnet token ring */
+#define ARPHRD_CHAOS 5 /* Chaosnet */
+#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
+#define ARPHRD_ARCNET 7 /* ARCnet */
+#define ARPHRD_APPLETLK 8 /* APPLEtalk */
+#define ARPHRD_DLCI 15 /* Frame Relay DLCI */
+#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */
+
+/* Dummy types for non ARP hardware */
+#define ARPHRD_SLIP 256
+#define ARPHRD_CSLIP 257
+#define ARPHRD_SLIP6 258
+#define ARPHRD_CSLIP6 259
+#define ARPHRD_RSRVD 260 /* Notional KISS type */
+#define ARPHRD_ADAPT 264
+#define ARPHRD_ROSE 270
+#define ARPHRD_X25 271 /* CCITT X.25 */
+#define ARPHRD_PPP 512
+#define ARPHRD_HDLC 513 /* (Cisco) HDLC */
+#define ARPHRD_LAPB 516 /* LAPB */
+
+#define ARPHRD_TUNNEL 768 /* IPIP tunnel */
+#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel */
+#define ARPHRD_FRAD 770 /* Frame Relay Access Device */
+#define ARPHRD_SKIP 771 /* SKIP vif */
+#define ARPHRD_LOOPBACK 772 /* Loopback device */
+#define ARPHRD_LOCALTLK 773 /* Localtalk device */
+#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface */
+#define ARPHRD_BIF 775 /* AP1000 BIF */
+#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4 */
+#define ARPHRD_IPDDP 777 /* IP over DDP tunneller */
+#define ARPHRD_IPGRE 778 /* GRE over IP */
+#define ARPHRD_PIMREG 779 /* PIMSM register interface */
+#define ARPHRD_HIPPI 780 /* High Performance Parallel Interface */
+#define ARPHRD_ASH 781 /* Nexus 64Mbps Ash */
+#define ARPHRD_ECONET 782 /* Acorn Econet */
+#define ARPHRD_IRDA 783 /* Linux/IR */
+/* ARP works differently on different FC media .. so */
+#define ARPHRD_FCPP 784 /* Point to point fibrechanel */
+#define ARPHRD_FCAL 785 /* Fibrechannel arbitrated loop */
+#define ARPHRD_FCPL 786 /* Fibrechannel public loop */
+#define ARPHRD_FCFABRIC 787 /* Fibrechannel fabric */
+ /* 787->799 reserved for fibrechannel media types */
+
+
+/* ARP protocol opcodes. */
+#define ARPOP_REQUEST 1 /* ARP request */
+#define ARPOP_REPLY 2 /* ARP reply */
+#define ARPOP_RREQUEST 3 /* RARP request */
+#define ARPOP_RREPLY 4 /* RARP reply */
+
+
+/* ARP ioctl request. */
+struct arpreq {
+ struct sockaddr arp_pa; /* protocol address */
+ struct sockaddr arp_ha; /* hardware address */
+ int arp_flags; /* flags */
+ struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
+ char arp_dev[16];
+};
+
+struct arpreq_old {
+ struct sockaddr arp_pa; /* protocol address */
+ struct sockaddr arp_ha; /* hardware address */
+ int arp_flags; /* flags */
+ struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
+};
+
+/* ARP Flag values. */
+#define ATF_COM 0x02 /* completed entry (ha valid) */
+#define ATF_PERM 0x04 /* permanent entry */
+#define ATF_PUBL 0x08 /* publish entry */
+#define ATF_USETRAILERS 0x10 /* has requested trailers */
+#define ATF_NETMASK 0x20 /* want to use a netmask (only
+ for proxy entries) */
+#define ATF_DONTPUB 0x40 /* don't answer this addresses */
+
+/*
+ * This structure defines an ethernet arp header.
+ */
+
+struct arphdr
+{
+ unsigned short ar_hrd; /* format of hardware address */
+ unsigned short ar_pro; /* format of protocol address */
+ unsigned char ar_hln; /* length of hardware address */
+ unsigned char ar_pln; /* length of protocol address */
+ unsigned short ar_op; /* ARP opcode (command) */
+
+#if 0
+ /*
+ * Ethernet looks like this : This bit is variable sized however...
+ */
+ unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
+ unsigned char ar_sip[4]; /* sender IP address */
+ unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
+ unsigned char ar_tip[4]; /* target IP address */
+#endif
+
+};
+
+#endif /* _LINUX_IF_ARP_H */
diff --git a/pfinet/linux-src/include/linux/if_cablemodem.h b/pfinet/linux-src/include/linux/if_cablemodem.h
new file mode 100644
index 00000000..9ca1007e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_cablemodem.h
@@ -0,0 +1,22 @@
+#ifndef _LINUX_CABLEMODEM_H_
+#define _LINUX_CABLEMODEM_H_
+/*
+ * Author: Franco Venturi <fventuri@mediaone.net>
+ * Copyright 1998 Franco Venturi
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+/* some useful defines for sb1000.c e cmconfig.c - fv */
+#define SIOCGCMSTATS SIOCDEVPRIVATE+0 /* get cable modem stats */
+#define SIOCGCMFIRMWARE SIOCDEVPRIVATE+1 /* get cm firmware version */
+#define SIOCGCMFREQUENCY SIOCDEVPRIVATE+2 /* get cable modem frequency */
+#define SIOCSCMFREQUENCY SIOCDEVPRIVATE+3 /* set cable modem frequency */
+#define SIOCGCMPIDS SIOCDEVPRIVATE+4 /* get cable modem PIDs */
+#define SIOCSCMPIDS SIOCDEVPRIVATE+5 /* set cable modem PIDs */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_ec.h b/pfinet/linux-src/include/linux/if_ec.h
new file mode 100644
index 00000000..4883f16a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_ec.h
@@ -0,0 +1,47 @@
+/* Definitions for Econet sockets. */
+
+#ifndef __LINUX_IF_EC
+#define __LINUX_IF_EC
+
+/* User visible stuff. Glibc provides its own but libc5 folk will use these */
+
+struct ec_addr
+{
+ unsigned char station; /* Station number. */
+ unsigned char net; /* Network number. */
+};
+
+struct sockaddr_ec
+{
+ unsigned short sec_family;
+ unsigned char port; /* Port number. */
+ unsigned char cb; /* Control/flag byte. */
+ unsigned char type; /* Type of message. */
+ struct ec_addr addr;
+ unsigned long cookie;
+};
+
+#define ECTYPE_PACKET_RECEIVED 0 /* Packet received */
+#define ECTYPE_TRANSMIT_STATUS 0x10 /* Transmit completed,
+ low nibble holds status */
+
+#define ECTYPE_TRANSMIT_OK 1
+#define ECTYPE_TRANSMIT_NOT_LISTENING 2
+#define ECTYPE_TRANSMIT_NET_ERROR 3
+#define ECTYPE_TRANSMIT_NO_CLOCK 4
+#define ECTYPE_TRANSMIT_LINE_JAMMED 5
+#define ECTYPE_TRANSMIT_NOT_PRESENT 6
+
+#ifdef __KERNEL__
+
+struct econet_opt
+{
+ unsigned char cb;
+ unsigned char port;
+ unsigned char station;
+ unsigned char net;
+};
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_eql.h b/pfinet/linux-src/include/linux/if_eql.h
new file mode 100644
index 00000000..320dbebf
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_eql.h
@@ -0,0 +1,81 @@
+/*
+ * Equalizer Load-balancer for serial network interfaces.
+ *
+ * (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
+ * NCM: Network and Communications Management, Inc.
+ *
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ *
+ * The author may be reached as simon@ncm.com, or C/O
+ * NCM
+ * Attn: Simon Janes
+ * 6803 Whittier Ave
+ * McLean VA 22101
+ * Phone: 1-703-847-0040 ext 103
+ */
+
+#ifndef _LINUX_IF_EQL_H
+#define _LINUX_IF_EQL_H
+
+#include <linux/timer.h>
+
+#define EQL_DEFAULT_SLAVE_PRIORITY 28800
+#define EQL_DEFAULT_MAX_SLAVES 4
+#define EQL_DEFAULT_MTU 576
+#define EQL_DEFAULT_RESCHED_IVAL 100
+
+#define EQL_ENSLAVE (SIOCDEVPRIVATE)
+#define EQL_EMANCIPATE (SIOCDEVPRIVATE + 1)
+
+#define EQL_GETSLAVECFG (SIOCDEVPRIVATE + 2)
+#define EQL_SETSLAVECFG (SIOCDEVPRIVATE + 3)
+
+#define EQL_GETMASTRCFG (SIOCDEVPRIVATE + 4)
+#define EQL_SETMASTRCFG (SIOCDEVPRIVATE + 5)
+
+typedef struct slave {
+ struct device *dev;
+ long priority;
+ long priority_bps;
+ long priority_Bps;
+ long bytes_queued;
+ struct slave *next;
+} slave_t;
+
+typedef struct slave_queue {
+ slave_t *head;
+ slave_t *best_slave;
+ int num_slaves;
+ struct device *master_dev;
+ char lock;
+} slave_queue_t;
+
+typedef struct equalizer {
+ slave_queue_t *queue;
+ int min_slaves;
+ int max_slaves;
+ struct enet_statistics *stats;
+ struct timer_list timer;
+ char timer_on;
+} equalizer_t;
+
+typedef struct master_config {
+ char master_name[16];
+ int max_slaves;
+ int min_slaves;
+} master_config_t;
+
+typedef struct slave_config {
+ char slave_name[16];
+ long priority;
+} slave_config_t;
+
+typedef struct slaving_request {
+ char slave_name[16];
+ long priority;
+} slaving_request_t;
+
+
+#endif /* _LINUX_EQL_H */
diff --git a/pfinet/linux-src/include/linux/if_ether.h b/pfinet/linux-src/include/linux/if_ether.h
new file mode 100644
index 00000000..99bb97fa
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_ether.h
@@ -0,0 +1,98 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the Ethernet IEEE 802.3 interface.
+ *
+ * Version: @(#)if_ether.h 1.0.1a 02/08/94
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Donald Becker, <becker@super.org>
+ * Alan Cox, <alan@redhat.com>
+ * Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_IF_ETHER_H
+#define _LINUX_IF_ETHER_H
+
+/*
+ * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble
+ * and FCS/CRC (frame check sequence).
+ */
+
+#define ETH_ALEN 6 /* Octets in one ethernet addr */
+#define ETH_HLEN 14 /* Total octets in header. */
+#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
+#define ETH_DATA_LEN 1500 /* Max. octets in payload */
+#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
+
+/*
+ * These are the defined Ethernet Protocol ID's.
+ */
+
+#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
+#define ETH_P_ECHO 0x0200 /* Ethernet Echo packet */
+#define ETH_P_PUP 0x0400 /* Xerox PUP packet */
+#define ETH_P_IP 0x0800 /* Internet Protocol packet */
+#define ETH_P_X25 0x0805 /* CCITT X.25 */
+#define ETH_P_ARP 0x0806 /* Address Resolution packet */
+#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_DEC 0x6000 /* DEC Assigned proto */
+#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */
+#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */
+#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */
+#define ETH_P_LAT 0x6004 /* DEC LAT */
+#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */
+#define ETH_P_CUST 0x6006 /* DEC Customer use */
+#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */
+#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */
+#define ETH_P_ATALK 0x809B /* Appletalk DDP */
+#define ETH_P_AARP 0x80F3 /* Appletalk AARP */
+#define ETH_P_IPX 0x8137 /* IPX over DIX */
+#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
+
+/*
+ * Non DIX types. Won't clash for 1500 types.
+ */
+
+#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */
+#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */
+#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
+#define ETH_P_802_2 0x0004 /* 802.2 frames */
+#define ETH_P_SNAP 0x0005 /* Internal only */
+#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */
+#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/
+#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */
+#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */
+#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/
+#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */
+#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */
+#define ETH_P_CONTROL 0x0016 /* Card specific control frames */
+#define ETH_P_IRDA 0x0017 /* Linux/IR */
+
+/*
+ * This is an Ethernet frame header.
+ */
+
+struct ethhdr
+{
+ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
+ unsigned char h_source[ETH_ALEN]; /* source ether addr */
+ unsigned short h_proto; /* packet type ID field */
+};
+
+/*
+ * We Have changed the ethernet statistics collection data. This
+ * is just for partial compatibility for now.
+ */
+
+
+#define enet_statistics net_device_stats
+
+#endif /* _LINUX_IF_ETHER_H */
diff --git a/pfinet/linux-src/include/linux/if_fc.h b/pfinet/linux-src/include/linux/if_fc.h
new file mode 100644
index 00000000..33330b45
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_fc.h
@@ -0,0 +1,50 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for Fibre Channel.
+ *
+ * Version: @(#)if_fc.h 0.0 11/20/98
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Donald Becker, <becker@super.org>
+ * Peter De Schrijver, <stud11@cc4.kuleuven.ac.be>
+ * Vineet Abraham, <vma@iol.unh.edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_FC_H
+#define _LINUX_IF_FC_H
+
+
+#define FC_ALEN 6 /* Octets in one ethernet addr */
+#define FC_HLEN (sizeof(struct fch_hdr)+sizeof(struct fcllc))
+#define FC_ID_LEN 3 /* Octets in a Fibre Channel Address */
+
+/* LLC and SNAP constants */
+#define EXTENDED_SAP 0xAA
+#define UI_CMD 0x03
+
+/* This is NOT the Fibre Channel frame header. The FC frame header is
+ * constructed in the driver as the Tachyon needs certain fields in
+ * certains positions. So, it can't be generalized here.*/
+
+struct fch_hdr {
+ __u8 daddr[FC_ALEN]; /* destination address */
+ __u8 saddr[FC_ALEN]; /* source address */
+};
+
+/* This is a Fibre Channel LLC structure */
+struct fcllc {
+ __u8 dsap; /* destination SAP */
+ __u8 ssap; /* source SAP */
+ __u8 llc; /* LLC control field */
+ __u8 protid[3]; /* protocol id */
+ __u16 ethertype; /* ether type field */
+};
+
+#endif /* _LINUX_IF_FC_H */
diff --git a/pfinet/linux-src/include/linux/if_fddi.h b/pfinet/linux-src/include/linux/if_fddi.h
new file mode 100644
index 00000000..22179636
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_fddi.h
@@ -0,0 +1,223 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the ANSI FDDI interface.
+ *
+ * Version: @(#)if_fddi.h 1.0.1 09/16/96
+ *
+ * Author: Lawrence V. Stefani, <stefani@lkg.dec.com>
+ *
+ * if_fddi.h is based on previous if_ether.h and if_tr.h work by
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Donald Becker, <becker@super.org>
+ * Alan Cox, <alan@redhat.com>
+ * Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
+ * Peter De Schrijver, <stud11@cc4.kuleuven.ac.be>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_FDDI_H
+#define _LINUX_IF_FDDI_H
+
+/*
+ * Define max and min legal sizes. The frame sizes do not include
+ * 4 byte FCS/CRC (frame check sequence).
+ */
+#define FDDI_K_ALEN 6 /* Octets in one FDDI address */
+#define FDDI_K_8022_HLEN 16 /* Total octets in 802.2 header */
+#define FDDI_K_SNAP_HLEN 21 /* Total octets in 802.2 SNAP header */
+#define FDDI_K_8022_ZLEN 16 /* Min octets in 802.2 frame sans FCS */
+#define FDDI_K_SNAP_ZLEN 21 /* Min octets in 802.2 SNAP frame sans FCS */
+#define FDDI_K_8022_DLEN 4475 /* Max octets in 802.2 payload */
+#define FDDI_K_SNAP_DLEN 4470 /* Max octets in 802.2 SNAP payload */
+#define FDDI_K_LLC_ZLEN 13 /* Min octets in LLC frame sans FCS */
+#define FDDI_K_LLC_LEN 4491 /* Max octets in LLC frame sans FCS */
+
+/* Define FDDI Frame Control (FC) Byte values */
+#define FDDI_FC_K_VOID 0x00
+#define FDDI_FC_K_NON_RESTRICTED_TOKEN 0x80
+#define FDDI_FC_K_RESTRICTED_TOKEN 0xC0
+#define FDDI_FC_K_SMT_MIN 0x41
+#define FDDI_FC_K_SMT_MAX 0x4F
+#define FDDI_FC_K_MAC_MIN 0xC1
+#define FDDI_FC_K_MAC_MAX 0xCF
+#define FDDI_FC_K_ASYNC_LLC_MIN 0x50
+#define FDDI_FC_K_ASYNC_LLC_DEF 0x54
+#define FDDI_FC_K_ASYNC_LLC_MAX 0x5F
+#define FDDI_FC_K_SYNC_LLC_MIN 0xD0
+#define FDDI_FC_K_SYNC_LLC_MAX 0xD7
+#define FDDI_FC_K_IMPLEMENTOR_MIN 0x60
+#define FDDI_FC_K_IMPLEMENTOR_MAX 0x6F
+#define FDDI_FC_K_RESERVED_MIN 0x70
+#define FDDI_FC_K_RESERVED_MAX 0x7F
+
+/* Define LLC and SNAP constants */
+#define FDDI_EXTENDED_SAP 0xAA
+#define FDDI_UI_CMD 0x03
+
+/* Define 802.2 Type 1 header */
+struct fddi_8022_1_hdr
+ {
+ __u8 dsap; /* destination service access point */
+ __u8 ssap; /* source service access point */
+ __u8 ctrl; /* control byte #1 */
+ } __attribute__ ((packed));
+
+/* Define 802.2 Type 2 header */
+struct fddi_8022_2_hdr
+ {
+ __u8 dsap; /* destination service access point */
+ __u8 ssap; /* source service access point */
+ __u8 ctrl_1; /* control byte #1 */
+ __u8 ctrl_2; /* control byte #2 */
+ } __attribute__ ((packed));
+
+/* Define 802.2 SNAP header */
+#define FDDI_K_OUI_LEN 3
+struct fddi_snap_hdr
+ {
+ __u8 dsap; /* always 0xAA */
+ __u8 ssap; /* always 0xAA */
+ __u8 ctrl; /* always 0x03 */
+ __u8 oui[FDDI_K_OUI_LEN]; /* organizational universal id */
+ __u16 ethertype; /* packet type ID field */
+ } __attribute__ ((packed));
+
+/* Define FDDI LLC frame header */
+struct fddihdr
+ {
+ __u8 fc; /* frame control */
+ __u8 daddr[FDDI_K_ALEN]; /* destination address */
+ __u8 saddr[FDDI_K_ALEN]; /* source address */
+ union
+ {
+ struct fddi_8022_1_hdr llc_8022_1;
+ struct fddi_8022_2_hdr llc_8022_2;
+ struct fddi_snap_hdr llc_snap;
+ } hdr;
+ } __attribute__ ((packed));
+
+/* Define FDDI statistics structure */
+struct fddi_statistics
+ {
+ __u32 rx_packets; /* total packets received */
+ __u32 tx_packets; /* total packets transmitted */
+ __u32 rx_bytes; /* total bytes received */
+ __u32 tx_bytes; /* total bytes transmitted */
+ __u32 rx_errors; /* bad packets received */
+ __u32 tx_errors; /* packet transmit problems */
+ __u32 rx_dropped; /* no space in linux buffers */
+ __u32 tx_dropped; /* no space available in linux */
+ __u32 multicast; /* multicast packets received */
+ __u32 transmit_collision; /* always 0 for FDDI */
+
+ /* detailed rx_errors */
+ __u32 rx_length_errors;
+ __u32 rx_over_errors; /* receiver ring buff overflow */
+ __u32 rx_crc_errors; /* recved pkt with crc error */
+ __u32 rx_frame_errors; /* recv'd frame alignment error */
+ __u32 rx_fifo_errors; /* recv'r fifo overrun */
+ __u32 rx_missed_errors; /* receiver missed packet */
+
+ /* detailed tx_errors */
+ __u32 tx_aborted_errors;
+ __u32 tx_carrier_errors;
+ __u32 tx_fifo_errors;
+ __u32 tx_heartbeat_errors;
+ __u32 tx_window_errors;
+
+ /* for cslip etc */
+ __u32 rx_compressed;
+ __u32 tx_compressed;
+
+ /* Detailed FDDI statistics. Adopted from RFC 1512 */
+
+ __u8 smt_station_id[8];
+ __u32 smt_op_version_id;
+ __u32 smt_hi_version_id;
+ __u32 smt_lo_version_id;
+ __u8 smt_user_data[32];
+ __u32 smt_mib_version_id;
+ __u32 smt_mac_cts;
+ __u32 smt_non_master_cts;
+ __u32 smt_master_cts;
+ __u32 smt_available_paths;
+ __u32 smt_config_capabilities;
+ __u32 smt_config_policy;
+ __u32 smt_connection_policy;
+ __u32 smt_t_notify;
+ __u32 smt_stat_rpt_policy;
+ __u32 smt_trace_max_expiration;
+ __u32 smt_bypass_present;
+ __u32 smt_ecm_state;
+ __u32 smt_cf_state;
+ __u32 smt_remote_disconnect_flag;
+ __u32 smt_station_status;
+ __u32 smt_peer_wrap_flag;
+ __u32 smt_time_stamp;
+ __u32 smt_transition_time_stamp;
+ __u32 mac_frame_status_functions;
+ __u32 mac_t_max_capability;
+ __u32 mac_tvx_capability;
+ __u32 mac_available_paths;
+ __u32 mac_current_path;
+ __u8 mac_upstream_nbr[FDDI_K_ALEN];
+ __u8 mac_downstream_nbr[FDDI_K_ALEN];
+ __u8 mac_old_upstream_nbr[FDDI_K_ALEN];
+ __u8 mac_old_downstream_nbr[FDDI_K_ALEN];
+ __u32 mac_dup_address_test;
+ __u32 mac_requested_paths;
+ __u32 mac_downstream_port_type;
+ __u8 mac_smt_address[FDDI_K_ALEN];
+ __u32 mac_t_req;
+ __u32 mac_t_neg;
+ __u32 mac_t_max;
+ __u32 mac_tvx_value;
+ __u32 mac_frame_cts;
+ __u32 mac_copied_cts;
+ __u32 mac_transmit_cts;
+ __u32 mac_error_cts;
+ __u32 mac_lost_cts;
+ __u32 mac_frame_error_threshold;
+ __u32 mac_frame_error_ratio;
+ __u32 mac_rmt_state;
+ __u32 mac_da_flag;
+ __u32 mac_una_da_flag;
+ __u32 mac_frame_error_flag;
+ __u32 mac_ma_unitdata_available;
+ __u32 mac_hardware_present;
+ __u32 mac_ma_unitdata_enable;
+ __u32 path_tvx_lower_bound;
+ __u32 path_t_max_lower_bound;
+ __u32 path_max_t_req;
+ __u32 path_configuration[8];
+ __u32 port_my_type[2];
+ __u32 port_neighbor_type[2];
+ __u32 port_connection_policies[2];
+ __u32 port_mac_indicated[2];
+ __u32 port_current_path[2];
+ __u8 port_requested_paths[3*2];
+ __u32 port_mac_placement[2];
+ __u32 port_available_paths[2];
+ __u32 port_pmd_class[2];
+ __u32 port_connection_capabilities[2];
+ __u32 port_bs_flag[2];
+ __u32 port_lct_fail_cts[2];
+ __u32 port_ler_estimate[2];
+ __u32 port_lem_reject_cts[2];
+ __u32 port_lem_cts[2];
+ __u32 port_ler_cutoff[2];
+ __u32 port_ler_alarm[2];
+ __u32 port_connect_state[2];
+ __u32 port_pcm_state[2];
+ __u32 port_pc_withhold[2];
+ __u32 port_ler_flag[2];
+ __u32 port_hardware_present[2];
+ };
+
+#endif /* _LINUX_IF_FDDI_H */
diff --git a/pfinet/linux-src/include/linux/if_frad.h b/pfinet/linux-src/include/linux/if_frad.h
new file mode 100644
index 00000000..4f1a1e2f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_frad.h
@@ -0,0 +1,201 @@
+/*
+ * DLCI/FRAD Definitions for Frame Relay Access Devices. DLCI devices are
+ * created for each DLCI associated with a FRAD. The FRAD driver
+ * is not truly a network device, but the lower level device
+ * handler. This allows other FRAD manufacturers to use the DLCI
+ * code, including its RFC1490 encapsulation alongside the current
+ * implementation for the Sangoma cards.
+ *
+ * Version: @(#)if_ifrad.h 0.15 31 Mar 96
+ *
+ * Author: Mike McLagan <mike.mclagan@linux.org>
+ *
+ * Changes:
+ * 0.15 Mike McLagan changed structure defs (packed)
+ * re-arranged flags
+ * added DLCI_RET vars
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _FRAD_H_
+#define _FRAD_H_
+
+#include <linux/config.h>
+#include <linux/if.h>
+
+#if defined(CONFIG_DLCI) || defined(CONFIG_DLCI_MODULE)
+
+/* Structures and constants associated with the DLCI device driver */
+
+struct dlci_add
+{
+ char devname[IFNAMSIZ];
+ short dlci;
+};
+
+#define DLCI_GET_CONF (SIOCDEVPRIVATE + 2)
+#define DLCI_SET_CONF (SIOCDEVPRIVATE + 3)
+
+/*
+ * These are related to the Sangoma SDLA and should remain in order.
+ * Code within the SDLA module is based on the specifics of this
+ * structure. Change at your own peril.
+ */
+struct dlci_conf {
+ short flags;
+ short CIR_fwd;
+ short Bc_fwd;
+ short Be_fwd;
+ short CIR_bwd;
+ short Bc_bwd;
+ short Be_bwd;
+
+/* these are part of the status read */
+ short Tc_fwd;
+ short Tc_bwd;
+ short Tf_max;
+ short Tb_max;
+
+/* add any new fields here above is a mirror of sdla_dlci_conf */
+};
+
+#define DLCI_GET_SLAVE (SIOCDEVPRIVATE + 4)
+
+/* configuration flags for DLCI */
+#define DLCI_IGNORE_CIR_OUT 0x0001
+#define DLCI_ACCOUNT_CIR_IN 0x0002
+#define DLCI_BUFFER_IF 0x0008
+
+#define DLCI_VALID_FLAGS 0x000B
+
+/* FRAD driver uses these to indicate what it did with packet */
+#define DLCI_RET_OK 0x00
+#define DLCI_RET_ERR 0x01
+#define DLCI_RET_DROP 0x02
+
+/* defines for the actual Frame Relay hardware */
+#define FRAD_GET_CONF (SIOCDEVPRIVATE)
+#define FRAD_SET_CONF (SIOCDEVPRIVATE + 1)
+
+#define FRAD_LAST_IOCTL FRAD_SET_CONF
+
+/*
+ * Based on the setup for the Sangoma SDLA. If changes are
+ * necessary to this structure, a routine will need to be
+ * added to that module to copy fields.
+ */
+struct frad_conf
+{
+ short station;
+ short flags;
+ short kbaud;
+ short clocking;
+ short mtu;
+ short T391;
+ short T392;
+ short N391;
+ short N392;
+ short N393;
+ short CIR_fwd;
+ short Bc_fwd;
+ short Be_fwd;
+ short CIR_bwd;
+ short Bc_bwd;
+ short Be_bwd;
+
+/* Add new fields here, above is a mirror of the sdla_conf */
+
+};
+
+#define FRAD_STATION_CPE 0x0000
+#define FRAD_STATION_NODE 0x0001
+
+#define FRAD_TX_IGNORE_CIR 0x0001
+#define FRAD_RX_ACCOUNT_CIR 0x0002
+#define FRAD_DROP_ABORTED 0x0004
+#define FRAD_BUFFERIF 0x0008
+#define FRAD_STATS 0x0010
+#define FRAD_MCI 0x0100
+#define FRAD_AUTODLCI 0x8000
+#define FRAD_VALID_FLAGS 0x811F
+
+#define FRAD_CLOCK_INT 0x0001
+#define FRAD_CLOCK_EXT 0x0000
+
+#ifdef __KERNEL__
+
+/* these are the fields of an RFC 1490 header */
+struct frhdr
+{
+ unsigned char control __attribute__((packed));
+
+ /* for IP packets, this can be the NLPID */
+ unsigned char pad __attribute__((packed));
+
+ unsigned char NLPID __attribute__((packed));
+ unsigned char OUI[3] __attribute__((packed));
+ unsigned short PID __attribute__((packed));
+
+#define IP_NLPID pad
+};
+
+/* see RFC 1490 for the definition of the following */
+#define FRAD_I_UI 0x03
+
+#define FRAD_P_PADDING 0x00
+#define FRAD_P_Q933 0x08
+#define FRAD_P_SNAP 0x80
+#define FRAD_P_CLNP 0x81
+#define FRAD_P_IP 0xCC
+
+struct dlci_local
+{
+ struct enet_statistics stats;
+ struct device *slave;
+ struct dlci_conf config;
+ int configured;
+
+ /* callback function */
+ void (*receive)(struct sk_buff *skb, struct device *);
+};
+
+struct frad_local
+{
+ struct enet_statistics stats;
+
+ /* devices which this FRAD is slaved to */
+ struct device *master[CONFIG_DLCI_MAX];
+ short dlci[CONFIG_DLCI_MAX];
+
+ struct frad_conf config;
+ int configured; /* has this device been configured */
+ int initialized; /* mem_start, port, irq set ? */
+
+ /* callback functions */
+ int (*activate)(struct device *, struct device *);
+ int (*deactivate)(struct device *, struct device *);
+ int (*assoc)(struct device *, struct device *);
+ int (*deassoc)(struct device *, struct device *);
+ int (*dlci_conf)(struct device *, struct device *, int get);
+
+ /* fields that are used by the Sangoma SDLA cards */
+ struct timer_list timer;
+ int type; /* adapter type */
+ int state; /* state of the S502/8 control latch */
+ int buffer; /* current buffer for S508 firmware */
+};
+
+int register_frad(const char *name);
+int unregister_frad(const char *name);
+
+int (*dlci_ioctl_hook)(unsigned int, void *);
+
+#endif __KERNEL__
+
+#endif /* CONFIG_DLCI || CONFIG_DLCI_MODULE */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_hippi.h b/pfinet/linux-src/include/linux/if_hippi.h
new file mode 100644
index 00000000..52c4a80b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_hippi.h
@@ -0,0 +1,157 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the HIPPI interface.
+ *
+ * Version: @(#)if_hippi.h 1.0.0 05/26/97
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Donald Becker, <becker@super.org>
+ * Alan Cox, <alan@redhat.com>
+ * Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
+ * Jes Sorensen, <Jes.Sorensen@cern.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_IF_HIPPI_H
+#define _LINUX_IF_HIPPI_H
+
+#include <asm/byteorder.h>
+
+/*
+ * HIPPI magic constants.
+ */
+
+#define HIPPI_ALEN 6 /* Bytes in one HIPPI hw-addr */
+#define HIPPI_HLEN sizeof(struct hippi_hdr)
+#define HIPPI_ZLEN 0 /* Min. bytes in frame without FCS */
+#define HIPPI_DATA_LEN 65280 /* Max. bytes in payload */
+#define HIPPI_FRAME_LEN (HIPPI_DATA_LEN + HIPPI_HLEN)
+ /* Max. bytes in frame without FCS */
+
+/*
+ * Define LLC and SNAP constants.
+ */
+#define HIPPI_EXTENDED_SAP 0xAA
+#define HIPPI_UI_CMD 0x03
+
+
+/*
+ * Do we need to list some sort of ID's here?
+ */
+
+/*
+ * HIPPI statistics collection data.
+ */
+
+struct hipnet_statistics
+{
+ int rx_packets; /* total packets received */
+ int tx_packets; /* total packets transmitted */
+ int rx_errors; /* bad packets received */
+ int tx_errors; /* packet transmit problems */
+ int rx_dropped; /* no space in linux buffers */
+ int tx_dropped; /* no space available in linux */
+
+ /* detailed rx_errors: */
+ int rx_length_errors;
+ int rx_over_errors; /* receiver ring buff overflow */
+ int rx_crc_errors; /* recved pkt with crc error */
+ int rx_frame_errors; /* recv'd frame alignment error */
+ int rx_fifo_errors; /* recv'r fifo overrun */
+ int rx_missed_errors; /* receiver missed packet */
+
+ /* detailed tx_errors */
+ int tx_aborted_errors;
+ int tx_carrier_errors;
+ int tx_fifo_errors;
+ int tx_heartbeat_errors;
+ int tx_window_errors;
+};
+
+
+struct hippi_fp_hdr
+{
+#if 0
+ __u8 ulp; /* must contain 4 */
+#if defined (__BIG_ENDIAN_BITFIELD)
+ __u8 d1_data_present:1; /* must be 1 */
+ __u8 start_d2_burst_boundary:1; /* must be zero */
+ __u8 reserved:6; /* must be zero */
+#if 0
+ __u16 reserved1:5;
+ __u16 d1_area_size:8; /* must be 3 */
+ __u16 d2_offset:3; /* must be zero */
+#endif
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 reserved:6; /* must be zero */
+ __u8 start_d2_burst_boundary:1; /* must be zero */
+ __u8 d1_data_present:1; /* must be 1 */
+#if 0
+ __u16 d2_offset:3; /* must be zero */
+ __u16 d1_area_size:8; /* must be 3 */
+ __u16 reserved1:5; /* must be zero */
+#endif
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+#else
+ __u32 fixed;
+#endif
+ __u32 d2_size;
+} __attribute__ ((packed));
+
+struct hippi_le_hdr
+{
+#if defined (__BIG_ENDIAN_BITFIELD)
+ unsigned long fc:3;
+ unsigned long double_wide:1;
+ unsigned long message_type:4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ unsigned long message_type:4;
+ unsigned long double_wide:1;
+ unsigned long fc:3;
+#endif
+ __u8 dest_switch_addr[3];
+#if defined (__BIG_ENDIAN_BITFIELD)
+ __u8 dest_addr_type:4,
+ src_addr_type:4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 src_addr_type:4,
+ dest_addr_type:4;
+#endif
+ __u8 src_switch_addr[3];
+ __u16 reserved;
+ __u8 daddr[HIPPI_ALEN];
+ __u16 locally_administered;
+ __u8 saddr[HIPPI_ALEN];
+} __attribute__ ((packed));
+
+#define HIPPI_OUI_LEN 3
+/*
+ * Looks like the dsap and ssap fields have been swapped by mistake in
+ * RFC 2067 "IP over HIPPI".
+ */
+struct hippi_snap_hdr
+{
+ __u8 dsap; /* always 0xAA */
+ __u8 ssap; /* always 0xAA */
+ __u8 ctrl; /* always 0x03 */
+ __u8 oui[HIPPI_OUI_LEN]; /* organizational universal id (zero)*/
+ __u16 ethertype; /* packet type ID field */
+} __attribute__ ((packed));
+
+struct hippi_hdr
+{
+ struct hippi_fp_hdr fp;
+ struct hippi_le_hdr le;
+ struct hippi_snap_hdr snap;
+} __attribute__ ((packed));
+
+#endif /* _LINUX_IF_HIPPI_H */
diff --git a/pfinet/linux-src/include/linux/if_ltalk.h b/pfinet/linux-src/include/linux/if_ltalk.h
new file mode 100644
index 00000000..d7b17d32
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_ltalk.h
@@ -0,0 +1,12 @@
+#ifndef __LINUX_LTALK_H
+#define __LINUX_LTALK_H
+
+#define LTALK_HLEN 1
+#define LTALK_MTU 600
+#define LTALK_ALEN 1
+
+#ifdef __KERNEL__
+extern void ltalk_setup(struct device *);
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_packet.h b/pfinet/linux-src/include/linux/if_packet.h
new file mode 100644
index 00000000..ad5655cf
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_packet.h
@@ -0,0 +1,50 @@
+#ifndef __LINUX_IF_PACKET_H
+#define __LINUX_IF_PACKET_H
+
+struct sockaddr_pkt
+{
+ unsigned short spkt_family;
+ unsigned char spkt_device[14];
+ unsigned short spkt_protocol;
+};
+
+struct sockaddr_ll
+{
+ unsigned short sll_family;
+ unsigned short sll_protocol;
+ int sll_ifindex;
+ unsigned short sll_hatype;
+ unsigned char sll_pkttype;
+ unsigned char sll_halen;
+ unsigned char sll_addr[8];
+};
+
+/* Packet types */
+
+#define PACKET_HOST 0 /* To us */
+#define PACKET_BROADCAST 1 /* To all */
+#define PACKET_MULTICAST 2 /* To group */
+#define PACKET_OTHERHOST 3 /* To someone else */
+#define PACKET_OUTGOING 4 /* Outgoing of any type */
+/* These ones are invisible by user level */
+#define PACKET_LOOPBACK 5 /* MC/BRD frame looped back */
+#define PACKET_FASTROUTE 6 /* Fastrouted frame */
+
+/* Packet socket options */
+
+#define PACKET_ADD_MEMBERSHIP 1
+#define PACKET_DROP_MEMBERSHIP 2
+
+struct packet_mreq
+{
+ int mr_ifindex;
+ unsigned short mr_type;
+ unsigned short mr_alen;
+ unsigned char mr_address[8];
+};
+
+#define PACKET_MR_MULTICAST 0
+#define PACKET_MR_PROMISC 1
+#define PACKET_MR_ALLMULTI 2
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_plip.h b/pfinet/linux-src/include/linux/if_plip.h
new file mode 100644
index 00000000..153a6499
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_plip.h
@@ -0,0 +1,28 @@
+/*
+ * NET3 PLIP tuning facilities for the new Niibe PLIP.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef _LINUX_IF_PLIP_H
+#define _LINUX_IF_PLIP_H
+
+#include <linux/sockios.h>
+
+#define SIOCDEVPLIP SIOCDEVPRIVATE
+
+struct plipconf
+{
+ unsigned short pcmd;
+ unsigned long nibble;
+ unsigned long trigger;
+};
+
+#define PLIP_GET_TIMEOUT 0x1
+#define PLIP_SET_TIMEOUT 0x2
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_ppp.h b/pfinet/linux-src/include/linux/if_ppp.h
new file mode 100644
index 00000000..1d103bdc
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_ppp.h
@@ -0,0 +1,143 @@
+/* $Id: if_ppp.h,v 1.19 1999/03/31 06:07:57 paulus Exp $ */
+
+/*
+ * if_ppp.h - Point-to-Point Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+/*
+ * ==FILEVERSION 990331==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, please set the above date.
+ * if_ppp.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new if_ppp.h
+ * file. Don't change the format of that line otherwise, so the
+ * installation script can recognize it.
+ */
+
+#ifndef _IF_PPP_H_
+#define _IF_PPP_H_
+
+/*
+ * Packet sizes
+ */
+
+#define PPP_MTU 1500 /* Default MTU (size of Info field) */
+#define PPP_MAXMRU 65000 /* Largest MRU we allow */
+#define PPP_VERSION "2.3.7"
+#define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */
+#define PROTO_IPX 0x002b /* protocol numbers */
+#define PROTO_DNA_RT 0x0027 /* DNA Routing */
+
+
+/*
+ * Bit definitions for flags.
+ */
+
+#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */
+#define SC_COMP_AC 0x00000002 /* header compression (output) */
+#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */
+#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */
+#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */
+#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */
+#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */
+#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */
+#define SC_ENABLE_IP 0x00000100 /* IP packets may be exchanged */
+#define SC_COMP_RUN 0x00001000 /* compressor has been inited */
+#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */
+#define SC_DEBUG 0x00010000 /* enable debug messages */
+#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */
+#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */
+#define SC_LOG_RAWIN 0x00080000 /* log all chars received */
+#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */
+#define SC_SYNC 0x00200000 /* synchronous serial mode */
+#define SC_MASK 0x0f2000ff /* bits that user can change */
+
+/* state bits */
+#define SC_XMIT_BUSY 0x10000000 /* (used by isdn_ppp?) */
+#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */
+#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */
+#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */
+#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */
+#define SC_DC_FERROR 0x00800000 /* fatal decomp error detected */
+#define SC_DC_ERROR 0x00400000 /* non-fatal decomp error detected */
+
+/*
+ * Ioctl definitions.
+ */
+
+struct npioctl {
+ int protocol; /* PPP protocol, e.g. PPP_IP */
+ enum NPmode mode;
+};
+
+/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */
+struct ppp_option_data {
+ __u8 *ptr;
+ __u32 length;
+ int transmit;
+};
+
+struct ifpppstatsreq {
+ struct ifreq b;
+ struct ppp_stats stats; /* statistic information */
+};
+
+struct ifpppcstatsreq {
+ struct ifreq b;
+ struct ppp_comp_stats stats;
+};
+
+#define ifr__name b.ifr_ifrn.ifrn_name
+#define stats_ptr b.ifr_ifru.ifru_data
+
+/*
+ * Ioctl definitions.
+ */
+
+#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */
+#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */
+#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */
+#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */
+#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */
+#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */
+#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */
+#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */
+#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */
+#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */
+#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */
+#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */
+#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */
+#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data)
+#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */
+#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */
+#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */
+#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */
+#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */
+
+#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0)
+#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */
+#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2)
+
+#if !defined(ifr_mtu)
+#define ifr_mtu ifr_ifru.ifru_metric
+#endif
+
+#endif /* _IF_PPP_H_ */
diff --git a/pfinet/linux-src/include/linux/if_pppvar.h b/pfinet/linux-src/include/linux/if_pppvar.h
new file mode 100644
index 00000000..d6cd0c25
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_pppvar.h
@@ -0,0 +1,135 @@
+/* From: if_pppvar.h,v 1.2 1995/06/12 11:36:51 paulus Exp */
+/*
+ * if_pppvar.h - private structures and declarations for PPP.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * ==FILEVERSION 990325==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, please set the above date.
+ * if_pppvar.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new if_pppvar.h
+ * file. Don't change the format of that line otherwise, so the
+ * installation script can recognize it.
+ */
+
+/*
+ * Supported network protocols. These values are used for
+ * indexing sc_npmode.
+ */
+
+#define NP_IP 0 /* Internet Protocol */
+#define NP_IPX 1 /* IPX protocol */
+#define NP_AT 2 /* Appletalk protocol */
+#define NP_IPV6 3 /* Internet Protocol */
+#define NUM_NP 4 /* Number of NPs. */
+
+#define OBUFSIZE 256 /* # chars of output buffering */
+
+/*
+ * Structure describing each ppp unit.
+ */
+
+struct ppp {
+ int magic; /* magic value for structure */
+ struct ppp *next; /* unit with next index */
+ unsigned long inuse; /* are we allocated? */
+ int line; /* network interface unit # */
+ __u32 flags; /* miscellaneous control flags */
+ int mtu; /* maximum xmit frame size */
+ int mru; /* maximum receive frame size */
+ struct slcompress *slcomp; /* for TCP header compression */
+ struct sk_buff_head xmt_q; /* frames to send from pppd */
+ struct sk_buff_head rcv_q; /* frames for pppd to read */
+ unsigned long xmit_busy; /* bit 0 set when xmitter busy */
+
+ /* Information specific to using ppp on async serial lines. */
+ struct tty_struct *tty; /* ptr to TTY structure */
+ struct tty_struct *backup_tty; /* TTY to use if tty gets closed */
+ __u8 escape; /* 0x20 if prev char was PPP_ESC */
+ __u8 toss; /* toss this frame */
+ volatile __u8 tty_pushing; /* internal state flag */
+ volatile __u8 woke_up; /* internal state flag */
+ __u32 xmit_async_map[8]; /* 1 bit means that given control
+ character is quoted on output*/
+ __u32 recv_async_map; /* 1 bit means that given control
+ character is ignored on input*/
+ __u32 bytes_sent; /* Bytes sent on frame */
+ __u32 bytes_rcvd; /* Bytes recvd on frame */
+
+ /* Async transmission information */
+ struct sk_buff *tpkt; /* frame currently being sent */
+ int tpkt_pos; /* how much of it we've done */
+ __u16 tfcs; /* FCS so far for it */
+ unsigned char *optr; /* where we're up to in sending */
+ unsigned char *olim; /* points past last valid char */
+
+ /* Async reception information */
+ struct sk_buff *rpkt; /* frame currently being rcvd */
+ __u16 rfcs; /* FCS so far of rpkt */
+
+ /* Queues for select() functionality */
+ struct wait_queue *read_wait; /* queue for reading processes */
+
+ /* info for detecting idle channels */
+ unsigned long last_xmit; /* time of last transmission */
+ unsigned long last_recv; /* time last packet received */
+
+ /* Statistic information */
+ struct pppstat stats; /* statistic information */
+
+ /* PPP compression protocol information */
+ struct compressor *sc_xcomp; /* transmit compressor */
+ void *sc_xc_state; /* transmit compressor state */
+ struct compressor *sc_rcomp; /* receive decompressor */
+ void *sc_rc_state; /* receive decompressor state */
+
+ enum NPmode sc_npmode[NUM_NP]; /* what to do with each NP */
+ int sc_xfer; /* PID of reserved PPP table */
+ char name[8]; /* space for unit name */
+ struct device dev; /* net device structure */
+ struct enet_statistics estats; /* more detailed stats */
+
+ /* tty output buffer */
+ unsigned char obuf[OBUFSIZE]; /* buffer for characters to send */
+};
diff --git a/pfinet/linux-src/include/linux/if_shaper.h b/pfinet/linux-src/include/linux/if_shaper.h
new file mode 100644
index 00000000..e2e97c30
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_shaper.h
@@ -0,0 +1,64 @@
+#ifndef __LINUX_SHAPER_H
+#define __LINUX_SHAPER_H
+
+#ifdef __KERNEL__
+
+#define SHAPER_QLEN 10
+/*
+ * This is a bit speed dependent (read it shouldn't be a constant!)
+ *
+ * 5 is about right for 28.8 upwards. Below that double for every
+ * halving of speed or so. - ie about 20 for 9600 baud.
+ */
+#define SHAPER_LATENCY (5*HZ)
+#define SHAPER_MAXSLIP 2
+#define SHAPER_BURST (HZ/50) /* Good for >128K then */
+
+struct shaper
+{
+ struct sk_buff_head sendq;
+ __u32 bytespertick;
+ __u32 bitspersec;
+ __u32 shapelatency;
+ __u32 shapeclock;
+ __u32 recovery; /* Time we can next clock a packet out on
+ an empty queue */
+ unsigned long locked;
+ struct net_device_stats stats;
+ struct device *dev;
+ int (*hard_start_xmit) (struct sk_buff *skb,
+ struct device *dev);
+ int (*hard_header) (struct sk_buff *skb,
+ struct device *dev,
+ unsigned short type,
+ void *daddr,
+ void *saddr,
+ unsigned len);
+ int (*rebuild_header)(struct sk_buff *skb);
+ int (*hard_header_cache)(struct neighbour *neigh, struct hh_cache *hh);
+ void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char * haddr);
+ struct net_device_stats* (*get_stats)(struct device *dev);
+ struct wait_queue *wait_queue;
+ struct timer_list timer;
+};
+
+#endif
+
+#define SHAPER_SET_DEV 0x0001
+#define SHAPER_SET_SPEED 0x0002
+#define SHAPER_GET_DEV 0x0003
+#define SHAPER_GET_SPEED 0x0004
+
+struct shaperconf
+{
+ __u16 ss_cmd;
+ union
+ {
+ char ssu_name[14];
+ __u32 ssu_speed;
+ } ss_u;
+#define ss_speed ss_u.ssu_speed
+#define ss_name ss_u.ssu_name
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_slip.h b/pfinet/linux-src/include/linux/if_slip.h
new file mode 100644
index 00000000..1eb4e3a8
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_slip.h
@@ -0,0 +1,30 @@
+/*
+ * Swansea University Computer Society NET3
+ *
+ * This file declares the constants of special use with the SLIP/CSLIP/
+ * KISS TNC driver.
+ */
+
+#ifndef __LINUX_SLIP_H
+#define __LINUX_SLIP_H
+
+#define SL_MODE_SLIP 0
+#define SL_MODE_CSLIP 1
+#define SL_MODE_KISS 4
+
+#define SL_OPT_SIXBIT 2
+#define SL_OPT_ADAPTIVE 8
+
+/*
+ * VSV = ioctl for keepalive & outfill in SLIP driver
+ */
+
+#define SIOCSKEEPALIVE (SIOCDEVPRIVATE) /* Set keepalive timeout in sec */
+#define SIOCGKEEPALIVE (SIOCDEVPRIVATE+1) /* Get keepalive timeout */
+#define SIOCSOUTFILL (SIOCDEVPRIVATE+2) /* Set outfill timeout */
+#define SIOCGOUTFILL (SIOCDEVPRIVATE+3) /* Get outfill timeout */
+#define SIOCSLEASE (SIOCDEVPRIVATE+4) /* Set "leased" line type */
+#define SIOCGLEASE (SIOCDEVPRIVATE+5) /* Get line type */
+
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_strip.h b/pfinet/linux-src/include/linux/if_strip.h
new file mode 100644
index 00000000..fb5c5c98
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_strip.h
@@ -0,0 +1,25 @@
+/*
+ * if_strip.h --
+ *
+ * Definitions for the STRIP interface
+ *
+ * Copyright 1996 The Board of Trustees of The Leland Stanford
+ * Junior University. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies. Stanford University
+ * makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#ifndef __LINUX_STRIP_H
+#define __LINUX_STRIP_H
+
+typedef struct {
+ __u8 c[6];
+} MetricomAddress;
+
+#endif
diff --git a/pfinet/linux-src/include/linux/if_tr.h b/pfinet/linux-src/include/linux/if_tr.h
new file mode 100644
index 00000000..f7c97eeb
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_tr.h
@@ -0,0 +1,100 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the Token-Ring IEEE 802.5 interface.
+ *
+ * Version: @(#)if_tr.h 0.0 07/11/94
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Donald Becker, <becker@super.org>
+ * Peter De Schrijver, <stud11@cc4.kuleuven.ac.be>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_TR_H
+#define _LINUX_IF_TR_H
+
+
+/* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble
+ and FCS/CRC (frame check sequence). */
+#define TR_ALEN 6 /* Octets in one ethernet addr */
+#define TR_HLEN (sizeof(struct trh_hdr)+sizeof(struct trllc))
+#define AC 0x10
+#define LLC_FRAME 0x40
+#if 0
+#define ETH_HLEN 14 /* Total octets in header. */
+#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
+#define ETH_DATA_LEN 1500 /* Max. octets in payload */
+#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
+#endif
+
+
+/* LLC and SNAP constants */
+#define EXTENDED_SAP 0xAA
+#define UI_CMD 0x03
+
+/* This is an Token-Ring frame header. */
+struct trh_hdr {
+ __u8 ac; /* access control field */
+ __u8 fc; /* frame control field */
+ __u8 daddr[TR_ALEN]; /* destination address */
+ __u8 saddr[TR_ALEN]; /* source address */
+ __u16 rcf; /* route control field */
+ __u16 rseg[8]; /* routing registers */
+};
+
+/* This is an Token-Ring LLC structure */
+struct trllc {
+ __u8 dsap; /* destination SAP */
+ __u8 ssap; /* source SAP */
+ __u8 llc; /* LLC control field */
+ __u8 protid[3]; /* protocol id */
+ __u16 ethertype; /* ether type field */
+};
+
+/* Token-Ring statistics collection data. */
+struct tr_statistics {
+ unsigned long rx_packets; /* total packets received */
+ unsigned long tx_packets; /* total packets transmitted */
+ unsigned long rx_bytes; /* total bytes received */
+ unsigned long tx_bytes; /* total bytes transmitted */
+ unsigned long rx_errors; /* bad packets received */
+ unsigned long tx_errors; /* packet transmit problems */
+ unsigned long rx_dropped; /* no space in linux buffers */
+ unsigned long tx_dropped; /* no space available in linux */
+ unsigned long multicast; /* multicast packets received */
+ unsigned long transmit_collision;
+
+ /* detailed Token-Ring errors. See IBM Token-Ring Network
+ Architecture for more info */
+
+ unsigned long line_errors;
+ unsigned long internal_errors;
+ unsigned long burst_errors;
+ unsigned long A_C_errors;
+ unsigned long abort_delimiters;
+ unsigned long lost_frames;
+ unsigned long recv_congest_count;
+ unsigned long frame_copied_errors;
+ unsigned long frequency_errors;
+ unsigned long token_errors;
+ unsigned long dummy1;
+};
+
+/* source routing stuff */
+
+#define TR_RII 0x80
+#define TR_RCF_DIR_BIT 0x80
+#define TR_RCF_LEN_MASK 0x1f00
+#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */
+#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */
+#define TR_RCF_FRAME2K 0x20
+#define TR_RCF_BROADCAST_MASK 0xC000
+#define TR_MAXRIFLEN 18
+
+#endif /* _LINUX_IF_TR_H */
diff --git a/pfinet/linux-src/include/linux/if_tunnel.h b/pfinet/linux-src/include/linux/if_tunnel.h
new file mode 100644
index 00000000..bef9f8fd
--- /dev/null
+++ b/pfinet/linux-src/include/linux/if_tunnel.h
@@ -0,0 +1,29 @@
+#ifndef _IF_TUNNEL_H_
+#define _IF_TUNNEL_H_
+
+#define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0)
+#define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1)
+#define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2)
+#define SIOCCHGTUNNEL (SIOCDEVPRIVATE + 3)
+
+#define GRE_CSUM __constant_htons(0x8000)
+#define GRE_ROUTING __constant_htons(0x4000)
+#define GRE_KEY __constant_htons(0x2000)
+#define GRE_SEQ __constant_htons(0x1000)
+#define GRE_STRICT __constant_htons(0x0800)
+#define GRE_REC __constant_htons(0x0700)
+#define GRE_FLAGS __constant_htons(0x00F8)
+#define GRE_VERSION __constant_htons(0x0007)
+
+struct ip_tunnel_parm
+{
+ char name[IFNAMSIZ];
+ int link;
+ __u16 i_flags;
+ __u16 o_flags;
+ __u32 i_key;
+ __u32 o_key;
+ struct iphdr iph;
+};
+
+#endif /* _IF_TUNNEL_H_ */
diff --git a/pfinet/linux-src/include/linux/igmp.h b/pfinet/linux-src/include/linux/igmp.h
new file mode 100644
index 00000000..c13afde2
--- /dev/null
+++ b/pfinet/linux-src/include/linux/igmp.h
@@ -0,0 +1,129 @@
+/*
+ * Linux NET3: Internet Group Management Protocol [IGMP]
+ *
+ * Authors:
+ * Alan Cox <Alan.Cox@linux.org>
+ *
+ * Extended to talk the BSD extended IGMP protocol of mrouted 3.6
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_IGMP_H
+#define _LINUX_IGMP_H
+
+/*
+ * IGMP protocol structures
+ */
+
+/*
+ * Header in on cable format
+ */
+
+struct igmphdr
+{
+ __u8 type;
+ __u8 code; /* For newer IGMP */
+ __u16 csum;
+ __u32 group;
+};
+
+#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */
+#define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */
+#define IGMP_DVMRP 0x13 /* DVMRP routing */
+#define IGMP_PIM 0x14 /* PIM routing */
+#define IGMP_TRACE 0x15
+#define IGMP_HOST_NEW_MEMBERSHIP_REPORT 0x16 /* New version of 0x11 */
+#define IGMP_HOST_LEAVE_MESSAGE 0x17
+
+#define IGMP_MTRACE_RESP 0x1e
+#define IGMP_MTRACE 0x1f
+
+
+/*
+ * Use the BSD names for these for compatibility
+ */
+
+#define IGMP_DELAYING_MEMBER 0x01
+#define IGMP_IDLE_MEMBER 0x02
+#define IGMP_LAZY_MEMBER 0x03
+#define IGMP_SLEEPING_MEMBER 0x04
+#define IGMP_AWAKENING_MEMBER 0x05
+
+#define IGMP_MINLEN 8
+
+#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */
+ /* query (in seconds) */
+
+#define IGMP_TIMER_SCALE 10 /* denotes that the igmphdr->timer field */
+ /* specifies time in 10th of seconds */
+
+#define IGMP_AGE_THRESHOLD 400 /* If this host don't hear any IGMP V1 */
+ /* message in this period of time, */
+ /* revert to IGMP v2 router. */
+
+#define IGMP_ALL_HOSTS htonl(0xE0000001L)
+#define IGMP_ALL_ROUTER htonl(0xE0000002L)
+#define IGMP_LOCAL_GROUP htonl(0xE0000000L)
+#define IGMP_LOCAL_GROUP_MASK htonl(0xFFFFFF00L)
+
+/*
+ * struct for keeping the multicast list in
+ */
+
+#ifdef __KERNEL__
+
+/* ip_mc_socklist is real list now. Speed is not argument;
+ this list never used in fast path code
+ */
+
+struct ip_mc_socklist
+{
+ struct ip_mc_socklist *next;
+ int count;
+ struct ip_mreqn multi;
+};
+
+struct ip_mc_list
+{
+ struct in_device *interface;
+ unsigned long multiaddr;
+ struct ip_mc_list *next;
+ struct timer_list timer;
+ int users;
+ char tm_running;
+ char reporter;
+ char unsolicit_count;
+ char loaded;
+};
+
+extern __inline__ int ip_check_mc(struct device *dev, u32 mc_addr)
+{
+ struct in_device *in_dev = dev->ip_ptr;
+ struct ip_mc_list *im;
+
+ if (in_dev) {
+ for (im=in_dev->mc_list; im; im=im->next)
+ if (im->multiaddr == mc_addr)
+ return 1;
+ }
+ return 0;
+}
+
+extern int igmp_rcv(struct sk_buff *, unsigned short);
+extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
+extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
+extern void ip_mc_drop_socket(struct sock *sk);
+extern void ip_mr_init(void);
+extern void ip_mc_init_dev(struct in_device *);
+extern void ip_mc_destroy_dev(struct in_device *);
+extern void ip_mc_up(struct in_device *);
+extern void ip_mc_down(struct in_device *);
+extern int ip_mc_dec_group(struct in_device *in_dev, u32 addr);
+extern void ip_mc_inc_group(struct in_device *in_dev, u32 addr);
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/in.h b/pfinet/linux-src/include/linux/in.h
new file mode 100644
index 00000000..37db22a9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/in.h
@@ -0,0 +1,189 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions of the Internet Protocol.
+ *
+ * Version: @(#)in.h 1.0.1 04/21/93
+ *
+ * Authors: Original taken from the GNU Project <netinet/in.h> file.
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IN_H
+#define _LINUX_IN_H
+
+#include <linux/types.h>
+
+/* Standard well-defined IP protocols. */
+enum {
+ IPPROTO_IP = 0, /* Dummy protocol for TCP */
+ IPPROTO_ICMP = 1, /* Internet Control Message Protocol */
+ IPPROTO_IGMP = 2, /* Internet Group Management Protocol */
+ IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */
+ IPPROTO_TCP = 6, /* Transmission Control Protocol */
+ IPPROTO_EGP = 8, /* Exterior Gateway Protocol */
+ IPPROTO_PUP = 12, /* PUP protocol */
+ IPPROTO_UDP = 17, /* User Datagram Protocol */
+ IPPROTO_IDP = 22, /* XNS IDP protocol */
+ IPPROTO_RSVP = 46, /* RSVP protocol */
+ IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
+
+ IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */
+
+ IPPROTO_PIM = 103, /* Protocol Independent Multicast */
+
+ IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */
+ IPPROTO_AH = 51, /* Authentication Header protocol */
+ IPPROTO_COMP = 108, /* Compression Header protocol */
+
+ IPPROTO_RAW = 255, /* Raw IP packets */
+ IPPROTO_MAX
+};
+
+
+/* Internet address. */
+struct in_addr {
+ __u32 s_addr;
+};
+
+#define IP_TOS 1
+#define IP_TTL 2
+#define IP_HDRINCL 3
+#define IP_OPTIONS 4
+#define IP_ROUTER_ALERT 5
+#define IP_RECVOPTS 6
+#define IP_RETOPTS 7
+#define IP_PKTINFO 8
+#define IP_PKTOPTIONS 9
+#define IP_MTU_DISCOVER 10
+#define IP_RECVERR 11
+#define IP_RECVTTL 12
+#define IP_RECVTOS 13
+#define IP_MTU 14
+
+/* BSD compatibility */
+#define IP_RECVRETOPTS IP_RETOPTS
+
+/* IP_MTU_DISCOVER values */
+#define IP_PMTUDISC_DONT 0 /* Never send DF frames */
+#define IP_PMTUDISC_WANT 1 /* Use per route hints */
+#define IP_PMTUDISC_DO 2 /* Always DF */
+
+#define IP_MULTICAST_IF 32
+#define IP_MULTICAST_TTL 33
+#define IP_MULTICAST_LOOP 34
+#define IP_ADD_MEMBERSHIP 35
+#define IP_DROP_MEMBERSHIP 36
+
+/* These need to appear somewhere around here */
+#define IP_DEFAULT_MULTICAST_TTL 1
+#define IP_DEFAULT_MULTICAST_LOOP 1
+
+/* Request struct for multicast socket ops */
+
+struct ip_mreq
+{
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+};
+
+struct ip_mreqn
+{
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_address; /* local IP address of interface */
+ int imr_ifindex; /* Interface index */
+};
+
+struct in_pktinfo
+{
+ int ipi_ifindex;
+ struct in_addr ipi_spec_dst;
+ struct in_addr ipi_addr;
+};
+
+/* Structure describing an Internet (IP) socket address. */
+#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
+struct sockaddr_in {
+ sa_family_t sin_family; /* Address family */
+ unsigned short int sin_port; /* Port number */
+ struct in_addr sin_addr; /* Internet address */
+
+ /* Pad to size of `struct sockaddr'. */
+ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
+ sizeof(unsigned short int) - sizeof(struct in_addr)];
+};
+#define sin_zero __pad /* for BSD UNIX comp. -FvK */
+
+
+/*
+ * Definitions of the bits in an Internet address integer.
+ * On subnets, host and network parts are found according
+ * to the subnet mask, not these masks.
+ */
+#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0)
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSA_NSHIFT 24
+#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
+#define IN_CLASSA_MAX 128
+
+#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000)
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSB_NSHIFT 16
+#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
+#define IN_CLASSB_MAX 65536
+
+#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000)
+#define IN_CLASSC_NET 0xffffff00
+#define IN_CLASSC_NSHIFT 8
+#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
+
+#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
+#define IN_MULTICAST(a) IN_CLASSD(a)
+#define IN_MULTICAST_NET 0xF0000000
+
+#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
+#define IN_BADCLASS(a) IN_EXPERIMENTAL((a))
+
+/* Address to accept any incoming messages. */
+#define INADDR_ANY ((unsigned long int) 0x00000000)
+
+/* Address to send to all hosts. */
+#define INADDR_BROADCAST ((unsigned long int) 0xffffffff)
+
+/* Address indicating an error return. */
+#define INADDR_NONE ((unsigned long int) 0xffffffff)
+
+/* Network number for local host loopback. */
+#define IN_LOOPBACKNET 127
+
+/* Address to loopback in software to local host. */
+#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */
+#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
+
+/* Defines for Multicast INADDR */
+#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */
+#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */
+#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */
+#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */
+
+
+/* <asm/byteorder.h> contains the htonl type stuff.. */
+#include <asm/byteorder.h>
+
+#ifdef __KERNEL__
+/* Some random defines to make it easier in the kernel.. */
+#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
+#define MULTICAST(x) (((x) & htonl(0xf0000000)) == htonl(0xe0000000))
+#define BADCLASS(x) (((x) & htonl(0xf0000000)) == htonl(0xf0000000))
+#define ZERONET(x) (((x) & htonl(0xff000000)) == htonl(0x00000000))
+#define LOCAL_MCAST(x) (((x) & htonl(0xFFFFFF00)) == htonl(0xE0000000))
+
+#endif
+
+#endif /* _LINUX_IN_H */
diff --git a/pfinet/linux-src/include/linux/in6.h b/pfinet/linux-src/include/linux/in6.h
new file mode 100644
index 00000000..ca5e768b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/in6.h
@@ -0,0 +1,193 @@
+/*
+ * Types and definitions for AF_INET6
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ * Sources:
+ * IPv6 Program Interfaces for BSD Systems
+ * <draft-ietf-ipngwg-bsd-api-05.txt>
+ *
+ * Advanced Sockets API for IPv6
+ * <draft-stevens-advanced-api-00.txt>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_IN6_H
+#define _LINUX_IN6_H
+
+#include <linux/types.h>
+
+/*
+ * IPv6 address structure
+ */
+
+struct in6_addr
+{
+ union
+ {
+ __u8 u6_addr8[16];
+ __u16 u6_addr16[8];
+ __u32 u6_addr32[4];
+#if (~0UL) > 0xffffffff
+#ifndef __RELAX_IN6_ADDR_ALIGNMENT
+ /* Alas, protocols do not respect 64bit alignmnet.
+ rsvp/pim/... are broken. However, it is good
+ idea to force correct alignment always, when
+ it is possible.
+ */
+ __u64 u6_addr64[2];
+#endif
+#endif
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+#define s6_addr64 in6_u.u6_addr64
+};
+
+struct sockaddr_in6 {
+ unsigned short int sin6_family; /* AF_INET6 */
+ __u16 sin6_port; /* Transport layer port # */
+ __u32 sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+};
+
+
+struct ipv6_mreq {
+ /* IPv6 multicast address of group */
+ struct in6_addr ipv6mr_multiaddr;
+
+ /* local IPv6 address of interface */
+ int ipv6mr_ifindex;
+};
+
+struct in6_flowlabel_req
+{
+ struct in6_addr flr_dst;
+ __u32 flr_label;
+ __u8 flr_action;
+ __u8 flr_share;
+ __u16 flr_flags;
+ __u16 flr_expires;
+ __u16 flr_linger;
+ __u32 __flr_pad;
+ /* Options in format of IPV6_PKTOPTIONS */
+};
+
+#define IPV6_FL_A_GET 0
+#define IPV6_FL_A_PUT 1
+#define IPV6_FL_A_RENEW 2
+
+#define IPV6_FL_F_CREATE 1
+#define IPV6_FL_F_EXCL 2
+
+#define IPV6_FL_S_NONE 0
+#define IPV6_FL_S_EXCL 1
+#define IPV6_FL_S_PROCESS 2
+#define IPV6_FL_S_USER 3
+#define IPV6_FL_S_ANY 255
+
+
+/*
+ * Bitmask constant declarations to help applications select out the
+ * flow label and priority fields.
+ *
+ * Note that this are in host byte order while the flowinfo field of
+ * sockaddr_in6 is in network byte order.
+ */
+
+#define IPV6_FLOWINFO_FLOWLABEL 0x000fffff
+#define IPV6_FLOWINFO_PRIORITY 0x0ff00000
+
+/* These defintions are obsolete */
+#define IPV6_PRIORITY_UNCHARACTERIZED 0x0000
+#define IPV6_PRIORITY_FILLER 0x0100
+#define IPV6_PRIORITY_UNATTENDED 0x0200
+#define IPV6_PRIORITY_RESERVED1 0x0300
+#define IPV6_PRIORITY_BULK 0x0400
+#define IPV6_PRIORITY_RESERVED2 0x0500
+#define IPV6_PRIORITY_INTERACTIVE 0x0600
+#define IPV6_PRIORITY_CONTROL 0x0700
+#define IPV6_PRIORITY_8 0x0800
+#define IPV6_PRIORITY_9 0x0900
+#define IPV6_PRIORITY_10 0x0a00
+#define IPV6_PRIORITY_11 0x0b00
+#define IPV6_PRIORITY_12 0x0c00
+#define IPV6_PRIORITY_13 0x0d00
+#define IPV6_PRIORITY_14 0x0e00
+#define IPV6_PRIORITY_15 0x0f00
+
+/*
+ * IPV6 extension headers
+ */
+#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */
+#define IPPROTO_ROUTING 43 /* IPv6 routing header */
+#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */
+#define IPPROTO_ICMPV6 58 /* ICMPv6 */
+#define IPPROTO_NONE 59 /* IPv6 no next header */
+#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */
+
+/*
+ * IPv6 TLV options.
+ */
+#define IPV6_TLV_PAD0 0
+#define IPV6_TLV_PADN 1
+#define IPV6_TLV_ROUTERALERT 20
+#define IPV6_TLV_JUMBO 194
+
+/*
+ * IPV6 socket options
+ */
+
+#define IPV6_ADDRFORM 1
+#define IPV6_PKTINFO 2
+#define IPV6_HOPOPTS 3
+#define IPV6_DSTOPTS 4
+#define IPV6_RTHDR 5
+#define IPV6_PKTOPTIONS 6
+#define IPV6_CHECKSUM 7
+#define IPV6_HOPLIMIT 8
+#define IPV6_NEXTHOP 9
+#define IPV6_AUTHHDR 10
+#define IPV6_FLOWINFO 11
+
+#if 0
+/* Aliases for obsolete names */
+#define IPV6_RXHOPOPTS IPV6_HOPOPTS
+#define IPV6_RXDSTOPTS IPV6_DSTOPTS
+#define IPV6_RXSRCRT IPV6_RTHDR
+#endif
+
+/*
+ * Alternative names
+ */
+#define SCM_SRCRT IPV6_RXSRCRT
+
+#define IPV6_UNICAST_HOPS 16
+#define IPV6_MULTICAST_IF 17
+#define IPV6_MULTICAST_HOPS 18
+#define IPV6_MULTICAST_LOOP 19
+#define IPV6_ADD_MEMBERSHIP 20
+#define IPV6_DROP_MEMBERSHIP 21
+#define IPV6_ROUTER_ALERT 22
+#define IPV6_MTU_DISCOVER 23
+#define IPV6_MTU 24
+#define IPV6_RECVERR 25
+
+/* IPV6_MTU_DISCOVER values */
+#define IPV6_PMTUDISC_DONT 0
+#define IPV6_PMTUDISC_WANT 1
+#define IPV6_PMTUDISC_DO 2
+
+/* Flowlabel */
+#define IPV6_FLOWLABEL_MGR 32
+#define IPV6_FLOWINFO_SEND 33
+
+
+#endif
diff --git a/pfinet/linux-src/include/linux/in_route.h b/pfinet/linux-src/include/linux/in_route.h
new file mode 100644
index 00000000..61f25c30
--- /dev/null
+++ b/pfinet/linux-src/include/linux/in_route.h
@@ -0,0 +1,32 @@
+#ifndef _LINUX_IN_ROUTE_H
+#define _LINUX_IN_ROUTE_H
+
+/* IPv4 routing cache flags */
+
+#define RTCF_DEAD RTNH_F_DEAD
+#define RTCF_ONLINK RTNH_F_ONLINK
+
+/* Obsolete flag. About to be deleted */
+#define RTCF_NOPMTUDISC RTM_F_NOPMTUDISC
+
+#define RTCF_NOTIFY 0x00010000
+#define RTCF_DIRECTDST 0x00020000
+#define RTCF_REDIRECTED 0x00040000
+#define RTCF_TPROXY 0x00080000
+
+#define RTCF_FAST 0x00200000
+#define RTCF_MASQ 0x00400000
+#define RTCF_SNAT 0x00800000
+#define RTCF_DOREDIRECT 0x01000000
+#define RTCF_DIRECTSRC 0x04000000
+#define RTCF_DNAT 0x08000000
+#define RTCF_BROADCAST 0x10000000
+#define RTCF_MULTICAST 0x20000000
+#define RTCF_REJECT 0x40000000
+#define RTCF_LOCAL 0x80000000
+
+#define RTCF_NAT (RTCF_DNAT|RTCF_SNAT)
+
+#define RT_TOS(tos) ((tos)&IPTOS_TOS_MASK)
+
+#endif /* _LINUX_IN_ROUTE_H */
diff --git a/pfinet/linux-src/include/linux/in_systm.h b/pfinet/linux-src/include/linux/in_systm.h
new file mode 100644
index 00000000..eac9a588
--- /dev/null
+++ b/pfinet/linux-src/include/linux/in_systm.h
@@ -0,0 +1,32 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Miscellaneous internetwork definitions for kernel.
+ *
+ * Version: @(#)in_systm.h 1.0.0 12/17/93
+ *
+ * Authors: Original taken from Berkeley BSD UNIX 4.3-RENO.
+ * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IN_SYSTM_H
+#define _LINUX_IN_SYSTM_H
+
+/*
+ * Network types.
+ * The n_ types are network-order variants of their natural
+ * equivalents. The Linux kernel NET-2 code does not use
+ * them (yet), but it might in the future. This is mostly
+ * there for compatibility with BSD user-level programs.
+ */
+typedef u_short n_short; /* short as received from the net */
+typedef u_long n_long; /* long as received from the net */
+typedef u_long n_time; /* ms since 00:00 GMT, byte rev */
+
+#endif /* _LINUX_IN_SYSTM_H */
diff --git a/pfinet/linux-src/include/linux/inet.h b/pfinet/linux-src/include/linux/inet.h
new file mode 100644
index 00000000..acb93765
--- /dev/null
+++ b/pfinet/linux-src/include/linux/inet.h
@@ -0,0 +1,52 @@
+/*
+ * Swansea University Computer Society NET3
+ *
+ * This work is derived from NET2Debugged, which is in turn derived
+ * from NET2D which was written by:
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This work was derived from Ross Biro's inspirational work
+ * for the LINUX operating system. His version numbers were:
+ *
+ * $Id: Space.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $
+ * $Id: arp.c,v 0.8.4.6 1993/01/28 22:30:00 bir7 Exp $
+ * $Id: arp.h,v 0.8.4.6 1993/01/28 22:30:00 bir7 Exp $
+ * $Id: dev.c,v 0.8.4.13 1993/01/23 18:00:11 bir7 Exp $
+ * $Id: dev.h,v 0.8.4.7 1993/01/23 18:00:11 bir7 Exp $
+ * $Id: eth.c,v 0.8.4.4 1993/01/22 23:21:38 bir7 Exp $
+ * $Id: eth.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $
+ * $Id: icmp.c,v 0.8.4.9 1993/01/23 18:00:11 bir7 Exp $
+ * $Id: icmp.h,v 0.8.4.2 1992/11/15 14:55:30 bir7 Exp $
+ * $Id: ip.c,v 0.8.4.8 1992/12/12 19:25:04 bir7 Exp $
+ * $Id: ip.h,v 0.8.4.2 1993/01/23 18:00:11 bir7 Exp $
+ * $Id: loopback.c,v 0.8.4.8 1993/01/23 18:00:11 bir7 Exp $
+ * $Id: packet.c,v 0.8.4.7 1993/01/26 22:04:00 bir7 Exp $
+ * $Id: protocols.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $
+ * $Id: raw.c,v 0.8.4.12 1993/01/26 22:04:00 bir7 Exp $
+ * $Id: sock.c,v 0.8.4.6 1993/01/28 22:30:00 bir7 Exp $
+ * $Id: sock.h,v 0.8.4.7 1993/01/26 22:04:00 bir7 Exp $
+ * $Id: tcp.c,v 0.8.4.16 1993/01/26 22:04:00 bir7 Exp $
+ * $Id: tcp.h,v 0.8.4.7 1993/01/22 22:58:08 bir7 Exp $
+ * $Id: timer.c,v 0.8.4.8 1993/01/23 18:00:11 bir7 Exp $
+ * $Id: timer.h,v 0.8.4.2 1993/01/23 18:00:11 bir7 Exp $
+ * $Id: udp.c,v 0.8.4.12 1993/01/26 22:04:00 bir7 Exp $
+ * $Id: udp.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $
+ * $Id: we.c,v 0.8.4.10 1993/01/23 18:00:11 bir7 Exp $
+ * $Id: wereg.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_INET_H
+#define _LINUX_INET_H
+
+#ifdef __KERNEL__
+
+extern void inet_proto_init(struct net_proto *pro);
+extern char *in_ntoa(__u32 in);
+extern __u32 in_aton(const char *str);
+
+#endif
+#endif /* _LINUX_INET_H */
diff --git a/pfinet/linux-src/include/linux/inetdevice.h b/pfinet/linux-src/include/linux/inetdevice.h
new file mode 100644
index 00000000..25c44959
--- /dev/null
+++ b/pfinet/linux-src/include/linux/inetdevice.h
@@ -0,0 +1,126 @@
+#ifndef _LINUX_INETDEVICE_H
+#define _LINUX_INETDEVICE_H
+
+#ifdef __KERNEL__
+
+struct ipv4_devconf
+{
+ int accept_redirects;
+ int send_redirects;
+ int secure_redirects;
+ int shared_media;
+ int accept_source_route;
+ int rp_filter;
+ int proxy_arp;
+ int bootp_relay;
+ int log_martians;
+ int forwarding;
+ int mc_forwarding;
+ void *sysctl;
+};
+
+extern struct ipv4_devconf ipv4_devconf;
+
+struct in_device
+{
+ struct device *dev;
+ struct in_ifaddr *ifa_list; /* IP ifaddr chain */
+ struct ip_mc_list *mc_list; /* IP multicast filter chain */
+ unsigned long mr_v1_seen;
+ unsigned flags;
+ struct neigh_parms *arp_parms;
+ struct ipv4_devconf cnf;
+};
+
+#define IN_DEV_FORWARD(in_dev) ((in_dev)->cnf.forwarding)
+#define IN_DEV_MFORWARD(in_dev) (ipv4_devconf.mc_forwarding && (in_dev)->cnf.mc_forwarding)
+#define IN_DEV_RPFILTER(in_dev) (ipv4_devconf.rp_filter && (in_dev)->cnf.rp_filter)
+#define IN_DEV_SOURCE_ROUTE(in_dev) (ipv4_devconf.accept_source_route && (in_dev)->cnf.accept_source_route)
+#define IN_DEV_BOOTP_RELAY(in_dev) (ipv4_devconf.bootp_relay && (in_dev)->cnf.bootp_relay)
+
+#define IN_DEV_LOG_MARTIANS(in_dev) (ipv4_devconf.log_martians || (in_dev)->cnf.log_martians)
+#define IN_DEV_PROXY_ARP(in_dev) (ipv4_devconf.proxy_arp || (in_dev)->cnf.proxy_arp)
+#define IN_DEV_SHARED_MEDIA(in_dev) (ipv4_devconf.shared_media || (in_dev)->cnf.shared_media)
+#define IN_DEV_TX_REDIRECTS(in_dev) (ipv4_devconf.send_redirects || (in_dev)->cnf.send_redirects)
+#define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
+
+#define IN_DEV_RX_REDIRECTS(in_dev) \
+ ((IN_DEV_FORWARD(in_dev) && \
+ (ipv4_devconf.accept_redirects && (in_dev)->cnf.accept_redirects)) \
+ || (!IN_DEV_FORWARD(in_dev) && \
+ (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
+
+struct in_ifaddr
+{
+ struct in_ifaddr *ifa_next;
+ struct in_device *ifa_dev;
+ u32 ifa_local;
+ u32 ifa_address;
+ u32 ifa_mask;
+ u32 ifa_broadcast;
+ u32 ifa_anycast;
+ unsigned char ifa_scope;
+ unsigned char ifa_flags;
+ unsigned char ifa_prefixlen;
+ char ifa_label[IFNAMSIZ];
+};
+
+extern int register_inetaddr_notifier(struct notifier_block *nb);
+extern int unregister_inetaddr_notifier(struct notifier_block *nb);
+
+extern struct device *ip_dev_find(u32 addr);
+extern struct in_ifaddr *inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b);
+extern int devinet_ioctl(unsigned int cmd, void *);
+extern void devinet_init(void);
+extern struct in_device *inetdev_init(struct device *dev);
+extern struct in_device *inetdev_by_index(int);
+extern u32 inet_select_addr(struct device *dev, u32 dst, int scope);
+extern struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask);
+extern void inet_forward_change(void);
+
+extern __inline__ int inet_ifa_match(u32 addr, struct in_ifaddr *ifa)
+{
+ return !((addr^ifa->ifa_address)&ifa->ifa_mask);
+}
+
+/*
+ * Check if a mask is acceptable.
+ */
+
+extern __inline__ int bad_mask(u32 mask, u32 addr)
+{
+ if (addr & (mask = ~mask))
+ return 1;
+ mask = ntohl(mask);
+ if (mask & (mask+1))
+ return 1;
+ return 0;
+}
+
+#define for_primary_ifa(in_dev) { struct in_ifaddr *ifa; \
+ for (ifa = (in_dev)->ifa_list; ifa && !(ifa->ifa_flags&IFA_F_SECONDARY); ifa = ifa->ifa_next)
+
+#define for_ifa(in_dev) { struct in_ifaddr *ifa; \
+ for (ifa = (in_dev)->ifa_list; ifa; ifa = ifa->ifa_next)
+
+
+#define endfor_ifa(in_dev) }
+
+#endif /* __KERNEL__ */
+
+extern __inline__ __u32 inet_make_mask(int logmask)
+{
+ if (logmask)
+ return htonl(~((1<<(32-logmask))-1));
+ return 0;
+}
+
+extern __inline__ int inet_mask_len(__u32 mask)
+{
+ if (!(mask = ntohl(mask)))
+ return 0;
+ return 32 - ffz(~mask);
+}
+
+
+#endif /* _LINUX_INETDEVICE_H */
diff --git a/pfinet/linux-src/include/linux/init.h b/pfinet/linux-src/include/linux/init.h
new file mode 100644
index 00000000..4465f38b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/init.h
@@ -0,0 +1,68 @@
+#ifndef _LINUX_INIT_H
+#define _LINUX_INIT_H
+
+/* These macros are used to mark some functions or
+ * initialized data (doesn't apply to uninitialized data)
+ * as `initialization' functions. The kernel can take this
+ * as hint that the function is used only during the initialization
+ * phase and free up used memory resources after
+ *
+ * Usage:
+ * For functions:
+ *
+ * You should add __init immediately before the function name, like:
+ *
+ * static void __init initme(int x, int y)
+ * {
+ * extern int z; z = x * y;
+ * }
+ *
+ * Depricated: you can surround the whole function declaration
+ * just before function body into __initfunc() macro, like:
+ *
+ * __initfunc (static void initme(int x, int y))
+ * {
+ * extern int z; z = x * y;
+ * }
+ *
+ * If the function has a prototype somewhere, you can also add
+ * __init between closing brace of the prototype and semicolon:
+ *
+ * extern int initialize_foobar_device(int, int, int) __init;
+ *
+ * For initialized data:
+ * You should insert __initdata between the variable name and equal
+ * sign followed by value, e.g.:
+ *
+ * static int init_variable __initdata = 0;
+ * static char linux_logo[] __initdata = { 0x32, 0x36, ... };
+ *
+ * For initialized data not at file scope, i.e. within a function,
+ * you should use __initlocaldata instead, due to a bug in GCC 2.7.
+ */
+
+/*
+ * Disable the __initfunc macros if a file that is a part of a
+ * module attempts to use them. We do not want to interfere
+ * with module linking.
+ */
+
+#ifndef MODULE
+#include <asm/init.h>
+#else
+#define __init
+#define __initdata
+#define __initfunc(__arginit) __arginit
+/* For assembly routines */
+#define __INIT
+#define __FINIT
+#define __INITDATA
+#endif
+
+#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 8
+#define __initlocaldata __initdata
+#else
+#define __initlocaldata
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/interrupt.h b/pfinet/linux-src/include/linux/interrupt.h
new file mode 100644
index 00000000..3e3edd8b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/interrupt.h
@@ -0,0 +1,84 @@
+/* interrupt.h */
+#ifndef _LINUX_INTERRUPT_H
+#define _LINUX_INTERRUPT_H
+
+#include <linux/kernel.h>
+#include <asm/bitops.h>
+#include <asm/atomic.h>
+
+struct irqaction {
+ void (*handler)(int, void *, struct pt_regs *);
+ unsigned long flags;
+ unsigned long mask;
+ const char *name;
+ void *dev_id;
+ struct irqaction *next;
+};
+
+extern volatile unsigned char bh_running;
+
+extern atomic_t bh_mask_count[32];
+extern unsigned long bh_active;
+extern unsigned long bh_mask;
+extern void (*bh_base[32])(void);
+
+asmlinkage void do_bottom_half(void);
+
+/* Who gets which entry in bh_base. Things which will occur most often
+ should come first - in which case NET should be up the top with SERIAL/TQUEUE! */
+
+enum {
+ TIMER_BH = 0,
+ CONSOLE_BH,
+ TQUEUE_BH,
+ DIGI_BH,
+ SERIAL_BH,
+ RISCOM8_BH,
+ SPECIALIX_BH,
+ AURORA_BH,
+ ESP_BH,
+ NET_BH,
+ SCSI_BH,
+ IMMEDIATE_BH,
+ KEYBOARD_BH,
+ CYCLADES_BH,
+ CM206_BH,
+ JS_BH,
+ MACSERIAL_BH,
+ ISICOM_BH
+};
+
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+
+/*
+ * Autoprobing for irqs:
+ *
+ * probe_irq_on() and probe_irq_off() provide robust primitives
+ * for accurate IRQ probing during kernel initialization. They are
+ * reasonably simple to use, are not "fooled" by spurious interrupts,
+ * and, unlike other attempts at IRQ probing, they do not get hung on
+ * stuck interrupts (such as unused PS2 mouse interfaces on ASUS boards).
+ *
+ * For reasonably foolproof probing, use them as follows:
+ *
+ * 1. clear and/or mask the device's internal interrupt.
+ * 2. sti();
+ * 3. irqs = probe_irq_on(); // "take over" all unassigned idle IRQs
+ * 4. enable the device and cause it to trigger an interrupt.
+ * 5. wait for the device to interrupt, using non-intrusive polling or a delay.
+ * 6. irq = probe_irq_off(irqs); // get IRQ number, 0=none, negative=multiple
+ * 7. service the device to clear its pending interrupt.
+ * 8. loop again if paranoia is required.
+ *
+ * probe_irq_on() returns a mask of allocated irq's.
+ *
+ * probe_irq_off() takes the mask as a parameter,
+ * and returns the irq number which occurred,
+ * or zero if none occurred, or a negative irq number
+ * if more than one irq occurred.
+ */
+extern unsigned long probe_irq_on(void); /* returns 0 on failure */
+extern int probe_irq_off(unsigned long); /* returns 0 or negative on failure */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/ioctl.h b/pfinet/linux-src/include/linux/ioctl.h
new file mode 100644
index 00000000..aa91eb39
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ioctl.h
@@ -0,0 +1,7 @@
+#ifndef _LINUX_IOCTL_H
+#define _LINUX_IOCTL_H
+
+#include <asm/ioctl.h>
+
+#endif /* _LINUX_IOCTL_H */
+
diff --git a/pfinet/linux-src/include/linux/ioport.h b/pfinet/linux-src/include/linux/ioport.h
new file mode 100644
index 00000000..b5eef44d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ioport.h
@@ -0,0 +1,35 @@
+/*
+ * portio.h Definitions of routines for detecting, reserving and
+ * allocating system resources.
+ *
+ * Version: 0.01 8/30/93
+ *
+ * Author: Donald Becker (becker@super.org)
+ */
+
+#ifndef _LINUX_PORTIO_H
+#define _LINUX_PORTIO_H
+
+#define HAVE_PORTRESERVE
+/*
+ * Call check_region() before probing for your hardware.
+ * Once you have found you hardware, register it with request_region().
+ * If you unload the driver, use release_region to free ports.
+ */
+extern void reserve_setup(char *str, int *ints);
+extern int check_region(unsigned long from, unsigned long extent);
+extern void request_region(unsigned long from, unsigned long extent,const char *name);
+extern void release_region(unsigned long from, unsigned long extent);
+extern int get_ioport_list(char *);
+
+#ifdef __sparc__
+extern unsigned long occupy_region(unsigned long base, unsigned long end,
+ unsigned long num, unsigned int align,
+ const char *name);
+#endif
+
+#define HAVE_AUTOIRQ
+extern void autoirq_setup(int waittime);
+extern int autoirq_report(int waittime);
+
+#endif /* _LINUX_PORTIO_H */
diff --git a/pfinet/linux-src/include/linux/ip.h b/pfinet/linux-src/include/linux/ip.h
new file mode 100644
index 00000000..6675cee9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ip.h
@@ -0,0 +1,137 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the IP protocol.
+ *
+ * Version: @(#)ip.h 1.0.2 04/28/93
+ *
+ * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IP_H
+#define _LINUX_IP_H
+#include <asm/byteorder.h>
+
+/* SOL_IP socket options */
+
+#define IPTOS_TOS_MASK 0x1E
+#define IPTOS_TOS(tos) ((tos)&IPTOS_TOS_MASK)
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_RELIABILITY 0x04
+#define IPTOS_MINCOST 0x02
+
+#define IPTOS_PREC_MASK 0xE0
+#define IPTOS_PREC(tos) ((tos)&IPTOS_PREC_MASK)
+#define IPTOS_PREC_NETCONTROL 0xe0
+#define IPTOS_PREC_INTERNETCONTROL 0xc0
+#define IPTOS_PREC_CRITIC_ECP 0xa0
+#define IPTOS_PREC_FLASHOVERRIDE 0x80
+#define IPTOS_PREC_FLASH 0x60
+#define IPTOS_PREC_IMMEDIATE 0x40
+#define IPTOS_PREC_PRIORITY 0x20
+#define IPTOS_PREC_ROUTINE 0x00
+
+
+/* IP options */
+#define IPOPT_COPY 0x80
+#define IPOPT_CLASS_MASK 0x60
+#define IPOPT_NUMBER_MASK 0x1f
+
+#define IPOPT_COPIED(o) ((o)&IPOPT_COPY)
+#define IPOPT_CLASS(o) ((o)&IPOPT_CLASS_MASK)
+#define IPOPT_NUMBER(o) ((o)&IPOPT_NUMBER_MASK)
+
+#define IPOPT_CONTROL 0x00
+#define IPOPT_RESERVED1 0x20
+#define IPOPT_MEASUREMENT 0x40
+#define IPOPT_RESERVED2 0x60
+
+#define IPOPT_END (0 |IPOPT_CONTROL)
+#define IPOPT_NOOP (1 |IPOPT_CONTROL)
+#define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
+#define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
+#define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
+#define IPOPT_RR (7 |IPOPT_CONTROL)
+#define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
+#define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
+#define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
+
+#define IPVERSION 4
+#define MAXTTL 255
+#define IPDEFTTL 64
+
+/* struct timestamp, struct route and MAX_ROUTES are removed.
+
+ REASONS: it is clear that nobody used them because:
+ - MAX_ROUTES value was wrong.
+ - "struct route" was wrong.
+ - "struct timestamp" had fatally misaligned bitfields and was completely unusable.
+ */
+
+#define IPOPT_OPTVAL 0
+#define IPOPT_OLEN 1
+#define IPOPT_OFFSET 2
+#define IPOPT_MINOFF 4
+#define MAX_IPOPTLEN 40
+#define IPOPT_NOP IPOPT_NOOP
+#define IPOPT_EOL IPOPT_END
+#define IPOPT_TS IPOPT_TIMESTAMP
+
+#define IPOPT_TS_TSONLY 0 /* timestamps only */
+#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
+#define IPOPT_TS_PRESPEC 3 /* specified modules only */
+
+struct ip_options {
+ __u32 faddr; /* Saved first hop address */
+ unsigned char optlen;
+ unsigned char srr;
+ unsigned char rr;
+ unsigned char ts;
+ unsigned char is_setbyuser:1, /* Set by setsockopt? */
+ is_data:1, /* Options in __data, rather than skb */
+ is_strictroute:1, /* Strict source route */
+ srr_is_hit:1, /* Packet destination addr was our one */
+ is_changed:1, /* IP checksum more not valid */
+ rr_needaddr:1, /* Need to record addr of outgoing dev */
+ ts_needtime:1, /* Need to record timestamp */
+ ts_needaddr:1; /* Need to record addr of outgoing dev */
+ unsigned char router_alert;
+ unsigned char __pad1;
+ unsigned char __pad2;
+ unsigned char __data[0];
+};
+
+#ifdef __KERNEL__
+#define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
+#endif
+
+struct iphdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 ihl:4,
+ version:4;
+#elif defined (__BIG_ENDIAN_BITFIELD)
+ __u8 version:4,
+ ihl:4;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __u8 tos;
+ __u16 tot_len;
+ __u16 id;
+ __u16 frag_off;
+ __u8 ttl;
+ __u8 protocol;
+ __u16 check;
+ __u32 saddr;
+ __u32 daddr;
+ /*The options start here. */
+};
+
+#endif /* _LINUX_IP_H */
diff --git a/pfinet/linux-src/include/linux/ip_fw.h b/pfinet/linux-src/include/linux/ip_fw.h
new file mode 100644
index 00000000..f36ec7e6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ip_fw.h
@@ -0,0 +1,193 @@
+/*
+ * This code is heavily based on the code in ip_fw.h; see that file for
+ * copyrights and attributions. This code is basically GPL.
+ *
+ * 15-Feb-1997: Major changes to allow graphs for firewall rules.
+ * Paul Russell <Paul.Russell@rustcorp.com.au> and
+ * Michael Neuling <Michael.Neuling@rustcorp.com.au>
+ * 2-Nov-1997: Changed types to __u16, etc.
+ * Removed IP_FW_F_TCPACK & IP_FW_F_BIDIR.
+ * Added inverse flags field.
+ * Removed multiple port specs.
+ */
+
+/*
+ * Format of an IP firewall descriptor
+ *
+ * src, dst, src_mask, dst_mask are always stored in network byte order.
+ * flags are stored in host byte order (of course).
+ * Port numbers are stored in HOST byte order.
+ */
+
+#ifndef _IP_FWCHAINS_H
+#define _IP_FWCHAINS_H
+
+#ifdef __KERNEL__
+#include <linux/icmp.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#endif /* __KERNEL__ */
+#define IP_FW_MAX_LABEL_LENGTH 8
+typedef char ip_chainlabel[IP_FW_MAX_LABEL_LENGTH+1];
+
+struct ip_fw
+{
+ struct in_addr fw_src, fw_dst; /* Source and destination IP addr */
+ struct in_addr fw_smsk, fw_dmsk; /* Mask for src and dest IP addr */
+ __u32 fw_mark; /* ID to stamp on packet */
+ __u16 fw_proto; /* Protocol, 0 = ANY */
+ __u16 fw_flg; /* Flags word */
+ __u16 fw_invflg; /* Inverse flags */
+ __u16 fw_spts[2]; /* Source port range. */
+ __u16 fw_dpts[2]; /* Destination port range. */
+ __u16 fw_redirpt; /* Port to redirect to. */
+ __u16 fw_outputsize; /* Max amount to output to
+ NETLINK */
+ char fw_vianame[IFNAMSIZ]; /* name of interface "via" */
+ __u8 fw_tosand, fw_tosxor; /* Revised packet priority */
+};
+
+struct ip_fwuser
+{
+ struct ip_fw ipfw;
+ ip_chainlabel label;
+};
+
+/* Values for "fw_flg" field . */
+#define IP_FW_F_PRN 0x0001 /* Print packet if it matches */
+#define IP_FW_F_TCPSYN 0x0002 /* For tcp packets-check SYN only */
+#define IP_FW_F_FRAG 0x0004 /* Set if rule is a fragment rule */
+#define IP_FW_F_MARKABS 0x0008 /* Set the mark to fw_mark, not add. */
+#define IP_FW_F_WILDIF 0x0010 /* Need only match start of interface name. */
+#define IP_FW_F_NETLINK 0x0020 /* Redirect to netlink: 2.1.x only */
+#define IP_FW_F_MASK 0x003F /* All possible flag bits mask */
+
+/* Values for "fw_invflg" field. */
+#define IP_FW_INV_SRCIP 0x0001 /* Invert the sense of fw_src. */
+#define IP_FW_INV_DSTIP 0x0002 /* Invert the sense of fw_dst. */
+#define IP_FW_INV_PROTO 0x0004 /* Invert the sense of fw_proto. */
+#define IP_FW_INV_SRCPT 0x0008 /* Invert the sense of source ports. */
+#define IP_FW_INV_DSTPT 0x0010 /* Invert the sense of destination ports. */
+#define IP_FW_INV_VIA 0x0020 /* Invert the sense of fw_vianame. */
+#define IP_FW_INV_SYN 0x0040 /* Invert the sense of IP_FW_F_TCPSYN. */
+#define IP_FW_INV_FRAG 0x0080 /* Invert the sense of IP_FW_F_FRAG. */
+
+/*
+ * New IP firewall options for [gs]etsockopt at the RAW IP level.
+ * Unlike BSD Linux inherits IP options so you don't have to use
+ * a raw socket for this. Instead we check rights in the calls. */
+
+#define IP_FW_BASE_CTL 64 /* base for firewall socket options */
+
+#define IP_FW_APPEND (IP_FW_BASE_CTL) /* Takes ip_fwchange */
+#define IP_FW_REPLACE (IP_FW_BASE_CTL+1) /* Takes ip_fwnew */
+#define IP_FW_DELETE_NUM (IP_FW_BASE_CTL+2) /* Takes ip_fwdelnum */
+#define IP_FW_DELETE (IP_FW_BASE_CTL+3) /* Takes ip_fwchange */
+#define IP_FW_INSERT (IP_FW_BASE_CTL+4) /* Takes ip_fwnew */
+#define IP_FW_FLUSH (IP_FW_BASE_CTL+5) /* Takes ip_chainlabel */
+#define IP_FW_ZERO (IP_FW_BASE_CTL+6) /* Takes ip_chainlabel */
+#define IP_FW_CHECK (IP_FW_BASE_CTL+7) /* Takes ip_fwtest */
+#define IP_FW_MASQ_TIMEOUTS (IP_FW_BASE_CTL+8) /* Takes 3 ints */
+#define IP_FW_CREATECHAIN (IP_FW_BASE_CTL+9) /* Takes ip_chainlabel */
+#define IP_FW_DELETECHAIN (IP_FW_BASE_CTL+10) /* Takes ip_chainlabel */
+#define IP_FW_POLICY (IP_FW_BASE_CTL+11) /* Takes ip_fwpolicy */
+/* Masquerade control, only 1 optname */
+
+#define IP_FW_MASQ_CTL (IP_FW_BASE_CTL+12) /* General ip_masq ctl */
+
+/* Builtin chain labels */
+#define IP_FW_LABEL_FORWARD "forward"
+#define IP_FW_LABEL_INPUT "input"
+#define IP_FW_LABEL_OUTPUT "output"
+
+/* Special targets */
+#define IP_FW_LABEL_MASQUERADE "MASQ"
+#define IP_FW_LABEL_REDIRECT "REDIRECT"
+#define IP_FW_LABEL_ACCEPT "ACCEPT"
+#define IP_FW_LABEL_BLOCK "DENY"
+#define IP_FW_LABEL_REJECT "REJECT"
+#define IP_FW_LABEL_RETURN "RETURN"
+#define IP_FW_LABEL_QUEUE "QUEUE"
+
+/* Files in /proc/net */
+#define IP_FW_PROC_CHAINS "ip_fwchains"
+#define IP_FW_PROC_CHAIN_NAMES "ip_fwnames"
+
+
+struct ip_fwpkt
+{
+ struct iphdr fwp_iph; /* IP header */
+ union {
+ struct tcphdr fwp_tcph; /* TCP header or */
+ struct udphdr fwp_udph; /* UDP header */
+ struct icmphdr fwp_icmph; /* ICMP header */
+ } fwp_protoh;
+ struct in_addr fwp_via; /* interface address */
+ char fwp_vianame[IFNAMSIZ]; /* interface name */
+};
+
+/* The argument to IP_FW_DELETE and IP_FW_APPEND */
+struct ip_fwchange
+{
+ struct ip_fwuser fwc_rule;
+ ip_chainlabel fwc_label;
+};
+
+/* The argument to IP_FW_CHECK. */
+struct ip_fwtest
+{
+ struct ip_fwpkt fwt_packet; /* Packet to be tested */
+ ip_chainlabel fwt_label; /* Block to start test in */
+};
+
+/* The argument to IP_FW_DELETE_NUM */
+struct ip_fwdelnum
+{
+ __u32 fwd_rulenum;
+ ip_chainlabel fwd_label;
+};
+
+/* The argument to IP_FW_REPLACE and IP_FW_INSERT */
+struct ip_fwnew
+{
+ __u32 fwn_rulenum;
+ struct ip_fwuser fwn_rule;
+ ip_chainlabel fwn_label;
+};
+
+/* The argument to IP_FW_POLICY */
+struct ip_fwpolicy
+{
+ ip_chainlabel fwp_policy;
+ ip_chainlabel fwp_label;
+};
+/*
+ * timeouts for ip masquerading
+ */
+
+extern int ip_fw_masq_timeouts(void *, int);
+
+
+/*
+ * Main firewall chains definitions and global var's definitions.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#include <linux/init.h>
+extern void ip_fw_init(void) __init;
+#else /* 2.0.x */
+extern void ip_fw_init(void);
+#endif /* 2.1.x */
+extern int ip_fw_ctl(int, void *, int);
+#ifdef CONFIG_IP_MASQUERADE
+extern int ip_masq_uctl(int, char *, int);
+#endif
+#endif /* KERNEL */
+
+#endif /* _IP_FWCHAINS_H */
diff --git a/pfinet/linux-src/include/linux/ip_masq.h b/pfinet/linux-src/include/linux/ip_masq.h
new file mode 100644
index 00000000..ba893138
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ip_masq.h
@@ -0,0 +1,140 @@
+/*
+ * IP_MASQ user space control interface
+ * $Id: ip_masq.h,v 1.2 1998/12/08 05:41:48 davem Exp $
+ */
+
+#ifndef _LINUX_IP_MASQ_H
+#define _LINUX_IP_MASQ_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/stddef.h>
+#else
+#include <sys/types.h>
+#include <stddef.h>
+#endif
+
+struct ip_masq_user {
+ int protocol;
+ u_int16_t sport, dport, mport;
+ u_int32_t saddr, daddr, maddr;
+ u_int32_t rt_daddr; /* dst address to use for rt query */
+ u_int32_t rt_saddr;
+ u_int32_t ip_tos; /* TOS */
+ unsigned timeout; /* in ticks (HZ per sec) */
+ unsigned flags;
+ int fd; /* NOT IMPL: attach tunnel to this fd */
+ int state; /* NOT IMPL: return conn state */
+};
+
+#define IP_MASQ_USER_F_LISTEN 0x01 /* put entry to LISTEN state */
+#define IP_MASQ_USER_F_DEAD 0x02 /* mark as DEAD */
+#define IP_MASQ_USER_F_FORCE 0x04 /* force operation */
+
+struct ip_masq_timeout {
+ int protocol;
+ union {
+ struct {
+ unsigned established;
+ unsigned syn_sent;
+ unsigned syn_recv;
+ unsigned fin_wait;
+ unsigned time_wait;
+ unsigned close;
+ unsigned close_wait;
+ unsigned last_ack;
+ unsigned listen;
+ } tcp;
+ unsigned udp;
+ unsigned icmp;
+ } u;
+};
+
+/*
+ * AUTOFW stuff
+ */
+#define IP_FWD_RANGE 1
+#define IP_FWD_PORT 2
+#define IP_FWD_DIRECT 3
+
+#define IP_AUTOFW_ACTIVE 1
+#define IP_AUTOFW_USETIME 2
+#define IP_AUTOFW_SECURE 4
+
+
+/* WARNING: bitwise equal to ip_autofw in net/ip_autofw.h */
+struct ip_autofw_user {
+ void * next;
+ u_int16_t type;
+ u_int16_t low;
+ u_int16_t hidden;
+ u_int16_t high;
+ u_int16_t visible;
+ u_int16_t protocol;
+ u_int32_t lastcontact;
+ u_int32_t where;
+ u_int16_t ctlproto;
+ u_int16_t ctlport;
+ u_int16_t flags;
+ /* struct timer_list timer; */
+};
+
+/*
+ * PORTFW stuff
+ */
+struct ip_portfw_user {
+ u_int16_t protocol; /* Which protocol are we talking? */
+ u_int32_t laddr, raddr; /* Remote address */
+ u_int16_t lport, rport; /* Local and remote port */
+ int pref; /* Preference value */
+};
+
+/*
+ * MFW stuff
+ */
+struct ip_mfw_user {
+ u_int32_t fwmark; /* Firewalling mark */
+ u_int32_t raddr; /* remote port */
+ u_int16_t rport; /* remote port */
+ u_int16_t dummy; /* Make up to multiple of 4 */
+ int pref; /* Preference value */
+ unsigned flags; /* misc flags */
+};
+
+#define IP_MASQ_MFW_SCHED 0x01
+
+#define IP_FW_MASQCTL_MAX 256
+#define IP_MASQ_TNAME_MAX 32
+
+struct ip_masq_ctl {
+ int m_target;
+ int m_cmd;
+ char m_tname[IP_MASQ_TNAME_MAX];
+ union {
+ struct ip_portfw_user portfw_user;
+ struct ip_autofw_user autofw_user;
+ struct ip_mfw_user mfw_user;
+ struct ip_masq_user user;
+ unsigned char m_raw[IP_FW_MASQCTL_MAX];
+ } u;
+};
+
+#define IP_MASQ_CTL_BSIZE (offsetof (struct ip_masq_ctl,u))
+
+#define IP_MASQ_TARGET_CORE 1
+#define IP_MASQ_TARGET_MOD 2 /* masq_mod is selected by "name" */
+#define IP_MASQ_TARGET_USER 3
+#define IP_MASQ_TARGET_LAST 4
+
+#define IP_MASQ_CMD_NONE 0 /* just peek */
+#define IP_MASQ_CMD_INSERT 1
+#define IP_MASQ_CMD_ADD 2
+#define IP_MASQ_CMD_SET 3
+#define IP_MASQ_CMD_DEL 4
+#define IP_MASQ_CMD_GET 5
+#define IP_MASQ_CMD_FLUSH 6
+#define IP_MASQ_CMD_LIST 7 /* actually fake: done via /proc */
+#define IP_MASQ_CMD_ENABLE 8
+#define IP_MASQ_CMD_DISABLE 9
+
+#endif /* _LINUX_IP_MASQ_H */
diff --git a/pfinet/linux-src/include/linux/ipc.h b/pfinet/linux-src/include/linux/ipc.h
new file mode 100644
index 00000000..851ff4ce
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ipc.h
@@ -0,0 +1,49 @@
+#ifndef _LINUX_IPC_H
+#define _LINUX_IPC_H
+
+#include <linux/types.h>
+
+#define IPC_PRIVATE ((__kernel_key_t) 0)
+
+struct ipc_perm
+{
+ __kernel_key_t key;
+ __kernel_uid_t uid;
+ __kernel_gid_t gid;
+ __kernel_uid_t cuid;
+ __kernel_gid_t cgid;
+ __kernel_mode_t mode;
+ unsigned short seq;
+};
+
+/* resource get request flags */
+#define IPC_CREAT 00001000 /* create if key is nonexistent */
+#define IPC_EXCL 00002000 /* fail if key exists */
+#define IPC_NOWAIT 00004000 /* return error on wait */
+
+/* these fields are used by the DIPC package so the kernel as standard
+ should avoid using them if possible */
+
+#define IPC_DIPC 00010000 /* make it distributed */
+#define IPC_OWN 00020000 /* this machine is the DIPC owner */
+
+/*
+ * Control commands used with semctl, msgctl and shmctl
+ * see also specific commands in sem.h, msg.h and shm.h
+ */
+#define IPC_RMID 0 /* remove resource */
+#define IPC_SET 1 /* set ipc_perm options */
+#define IPC_STAT 2 /* get ipc_perm options */
+#define IPC_INFO 3 /* see ipcs */
+
+#ifdef __KERNEL__
+
+/* special shmsegs[id], msgque[id] or semary[id] values */
+#define IPC_UNUSED ((void *) -1)
+#define IPC_NOID ((void *) -2) /* being allocated/destroyed */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_IPC_H */
+
+
diff --git a/pfinet/linux-src/include/linux/ipsec.h b/pfinet/linux-src/include/linux/ipsec.h
new file mode 100644
index 00000000..b9d7bcc6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ipsec.h
@@ -0,0 +1,69 @@
+/*
+ * Definitions for the SECurity layer
+ *
+ * Author:
+ * Robert Muchsel <muchsel@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_IPSEC_H
+#define _LINUX_IPSEC_H
+
+#include <linux/config.h>
+#include <linux/socket.h>
+#include <net/sock.h>
+#include <linux/skbuff.h>
+
+/* Values for the set/getsockopt calls */
+
+/* These defines are compatible with NRL IPv6, however their semantics
+ is different */
+
+#define IPSEC_LEVEL_NONE -1 /* send plaintext, accept any */
+#define IPSEC_LEVEL_DEFAULT 0 /* encrypt/authenticate if possible */
+ /* the default MUST be 0, because a */
+ /* socket is initialized with 0's */
+#define IPSEC_LEVEL_USE 1 /* use outbound, don't require inbound */
+#define IPSEC_LEVEL_REQUIRE 2 /* require both directions */
+#define IPSEC_LEVEL_UNIQUE 2 /* for compatibility only */
+
+#ifdef __KERNEL__
+
+/* skb bit flags set on packet input processing */
+
+#define RCV_SEC 0x0f /* options on receive */
+#define RCV_AUTH 0x01 /* was authenticated */
+#define RCV_CRYPT 0x02 /* was encrypted */
+#define RCV_TUNNEL 0x04 /* was tunneled */
+#define SND_SEC 0xf0 /* options on send, these are */
+#define SND_AUTH 0x10 /* currently unused */
+#define SND_CRYPT 0x20
+#define SND_TUNNEL 0x40
+
+/*
+ * FIXME: ignores network encryption for now..
+ */
+
+#ifdef CONFIG_NET_SECURITY
+extern __inline__ int ipsec_sk_policy(struct sock *sk, struct sk_buff *skb)
+{
+ return ((sk->authentication < IPSEC_LEVEL_REQUIRE) ||
+ (skb->security & RCV_AUTH)) &&
+ ((sk->encryption < IPSEC_LEVEL_REQUIRE) ||
+ (skb->security & RCV_CRYPT));
+}
+
+#else
+
+extern __inline__ int ipsec_sk_policy(struct sock *sk, struct sk_buff *skb)
+{
+ return 1;
+}
+#endif /* CONFIG */
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_IPSEC_H */
diff --git a/pfinet/linux-src/include/linux/ipv6.h b/pfinet/linux-src/include/linux/ipv6.h
new file mode 100644
index 00000000..84564bae
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ipv6.h
@@ -0,0 +1,123 @@
+#ifndef _IPV6_H
+#define _IPV6_H
+
+#include <linux/in6.h>
+#include <asm/byteorder.h>
+
+/* The latest drafts declared increase in minimal mtu up to 1280. */
+
+#define IPV6_MIN_MTU 1280
+
+/*
+ * Advanced API
+ * source interface/address selection, source routing, etc...
+ * *under construction*
+ */
+
+
+struct in6_pktinfo {
+ struct in6_addr ipi6_addr;
+ int ipi6_ifindex;
+};
+
+
+struct in6_ifreq {
+ struct in6_addr ifr6_addr;
+ __u32 ifr6_prefixlen;
+ int ifr6_ifindex;
+};
+
+#define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */
+#define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */
+
+/*
+ * routing header
+ */
+struct ipv6_rt_hdr {
+ __u8 nexthdr;
+ __u8 hdrlen;
+ __u8 type;
+ __u8 segments_left;
+
+ /*
+ * type specific data
+ * variable length field
+ */
+};
+
+
+struct ipv6_opt_hdr {
+ __u8 nexthdr;
+ __u8 hdrlen;
+ /*
+ * TLV encoded option data follows.
+ */
+};
+
+#define ipv6_destopt_hdr ipv6_opt_hdr
+#define ipv6_hopopt_hdr ipv6_opt_hdr
+
+#ifdef __KERNEL__
+#define ipv6_optlen(p) (((p)->hdrlen+1) << 3)
+#endif
+
+/*
+ * routing header type 0 (used in cmsghdr struct)
+ */
+
+struct rt0_hdr {
+ struct ipv6_rt_hdr rt_hdr;
+ __u32 bitmap; /* strict/loose bit map */
+ struct in6_addr addr[0];
+
+#define rt0_type rt_hdr.type;
+};
+
+/*
+ * IPv6 fixed header
+ *
+ * BEWARE, it is incorrect. The first 4 bits of flow_lbl
+ * are glued to priority now, forming "class".
+ */
+
+struct ipv6hdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 priority:4,
+ version:4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 version:4,
+ priority:4;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __u8 flow_lbl[3];
+
+ __u16 payload_len;
+ __u8 nexthdr;
+ __u8 hop_limit;
+
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+};
+
+#ifdef __KERNEL__
+
+/*
+ This structure contains results of exthdrs parsing
+ as offsets from skb->nh.
+ */
+
+struct inet6_skb_parm
+{
+ int iif;
+ __u16 ra;
+ __u16 hop;
+ __u16 auth;
+ __u16 dst0;
+ __u16 srcrt;
+ __u16 dst1;
+};
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/ipv6_route.h b/pfinet/linux-src/include/linux/ipv6_route.h
new file mode 100644
index 00000000..a4861d05
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ipv6_route.h
@@ -0,0 +1,56 @@
+/*
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_IPV6_ROUTE_H
+#define _LINUX_IPV6_ROUTE_H
+
+enum
+{
+ RTA_IPV6_UNSPEC,
+ RTA_IPV6_HOPLIMIT,
+};
+
+#define RTA_IPV6_MAX RTA_IPV6_HOPLIMIT
+
+
+#define RTF_DEFAULT 0x00010000 /* default - learned via ND */
+#define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */
+#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */
+
+#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */
+#define RTF_EXPIRES 0x00400000
+
+#define RTF_CACHE 0x01000000 /* cache entry */
+#define RTF_FLOW 0x02000000 /* flow significant route */
+#define RTF_POLICY 0x04000000 /* policy route */
+
+#define RTF_LOCAL 0x80000000
+
+struct in6_rtmsg {
+ struct in6_addr rtmsg_dst;
+ struct in6_addr rtmsg_src;
+ struct in6_addr rtmsg_gateway;
+ __u32 rtmsg_type;
+ __u16 rtmsg_dst_len;
+ __u16 rtmsg_src_len;
+ __u32 rtmsg_metric;
+ unsigned long rtmsg_info;
+ __u32 rtmsg_flags;
+ int rtmsg_ifindex;
+};
+
+#define RTMSG_NEWDEVICE 0x11
+#define RTMSG_DELDEVICE 0x12
+#define RTMSG_NEWROUTE 0x21
+#define RTMSG_DELROUTE 0x22
+
+#endif
diff --git a/pfinet/linux-src/include/linux/ipx.h b/pfinet/linux-src/include/linux/ipx.h
new file mode 100644
index 00000000..8b9d6bb1
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ipx.h
@@ -0,0 +1,89 @@
+#ifndef _IPX_H_
+#define _IPX_H_
+#include <linux/sockios.h>
+#include <linux/socket.h>
+#define IPX_NODE_LEN 6
+#define IPX_MTU 576
+
+struct sockaddr_ipx
+{
+ sa_family_t sipx_family;
+ __u16 sipx_port;
+ __u32 sipx_network;
+ unsigned char sipx_node[IPX_NODE_LEN];
+ __u8 sipx_type;
+ unsigned char sipx_zero; /* 16 byte fill */
+};
+
+/*
+ * So we can fit the extra info for SIOCSIFADDR into the address nicely
+ */
+
+#define sipx_special sipx_port
+#define sipx_action sipx_zero
+#define IPX_DLTITF 0
+#define IPX_CRTITF 1
+
+typedef struct ipx_route_definition
+{
+ __u32 ipx_network;
+ __u32 ipx_router_network;
+ unsigned char ipx_router_node[IPX_NODE_LEN];
+} ipx_route_definition;
+
+typedef struct ipx_interface_definition
+{
+ __u32 ipx_network;
+ unsigned char ipx_device[16];
+ unsigned char ipx_dlink_type;
+#define IPX_FRAME_NONE 0
+#define IPX_FRAME_SNAP 1
+#define IPX_FRAME_8022 2
+#define IPX_FRAME_ETHERII 3
+#define IPX_FRAME_8023 4
+#define IPX_FRAME_TR_8022 5 /* obsolete */
+ unsigned char ipx_special;
+#define IPX_SPECIAL_NONE 0
+#define IPX_PRIMARY 1
+#define IPX_INTERNAL 2
+ unsigned char ipx_node[IPX_NODE_LEN];
+} ipx_interface_definition;
+
+typedef struct ipx_config_data
+{
+ unsigned char ipxcfg_auto_select_primary;
+ unsigned char ipxcfg_auto_create_interfaces;
+} ipx_config_data;
+
+/*
+ * OLD Route Definition for backward compatibility.
+ */
+
+struct ipx_route_def
+{
+ __u32 ipx_network;
+ __u32 ipx_router_network;
+#define IPX_ROUTE_NO_ROUTER 0
+ unsigned char ipx_router_node[IPX_NODE_LEN];
+ unsigned char ipx_device[16];
+ unsigned short ipx_flags;
+#define IPX_RT_SNAP 8
+#define IPX_RT_8022 4
+#define IPX_RT_BLUEBOOK 2
+#define IPX_RT_ROUTED 1
+};
+
+#define SIOCAIPXITFCRT (SIOCPROTOPRIVATE)
+#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1)
+#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2)
+#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE+3)
+
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+extern int ipxrtr_route_skb(struct sk_buff *);
+extern int ipx_if_offset(unsigned long ipx_net_number);
+extern void ipx_remove_socket(struct sock *sk);
+#endif /* def __KERNEL__ */
+
+#endif /* def _IPX_H_ */
diff --git a/pfinet/linux-src/include/linux/irda.h b/pfinet/linux-src/include/linux/irda.h
new file mode 100644
index 00000000..275d82fc
--- /dev/null
+++ b/pfinet/linux-src/include/linux/irda.h
@@ -0,0 +1,120 @@
+/*********************************************************************
+ *
+ * Filename: irda.h
+ * Version:
+ * Description:
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Mar 8 14:06:12 1999
+ * Modified at: Mon Mar 22 14:14:54 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef KERNEL_IRDA_H
+#define KERNEL_IRDA_H
+
+/* Hint bit positions for first hint byte */
+#define HINT_PNP 0x01
+#define HINT_PDA 0x02
+#define HINT_COMPUTER 0x04
+#define HINT_PRINTER 0x08
+#define HINT_MODEM 0x10
+#define HINT_FAX 0x20
+#define HINT_LAN 0x40
+#define HINT_EXTENSION 0x80
+
+/* Hint bit positions for second hint byte (first extension byte) */
+#define HINT_TELEPHONY 0x01
+#define HINT_FILE_SERVER 0x02
+#define HINT_COMM 0x04
+#define HINT_MESSAGE 0x08
+#define HINT_HTTP 0x10
+#define HINT_OBEX 0x20
+
+/* IrLMP character code values */
+#define CS_ASCII 0x00
+#define CS_ISO_8859_1 0x01
+#define CS_ISO_8859_2 0x02
+#define CS_ISO_8859_3 0x03
+#define CS_ISO_8859_4 0x04
+#define CS_ISO_8859_5 0x05
+#define CS_ISO_8859_6 0x06
+#define CS_ISO_8859_7 0x07
+#define CS_ISO_8859_8 0x08
+#define CS_ISO_8859_9 0x09
+#define CS_UNICODE 0xff
+
+#define SOL_IRLMP 266 /* Same as SOL_IRDA for now */
+#define SOL_IRTTP 266 /* Same as SOL_IRDA for now */
+
+#define IRLMP_ENUMDEVICES 1
+#define IRLMP_IAS_SET 2
+#define IRLMP_IAS_QUERY 3
+#define IRLMP_DISCOVERY_MASK_SET 4
+
+#define IRTTP_QOS_SET 5
+#define IRTTP_QOS_GET 6
+#define IRTTP_MAX_SDU_SIZE 7
+
+#define IAS_MAX_STRING 256
+#define IAS_MAX_OCTET_STRING 1024
+#define IAS_MAX_CLASSNAME 64
+#define IAS_MAX_ATTRIBNAME 256
+
+#define LSAP_ANY 0xff
+
+struct sockaddr_irda {
+ sa_family_t sir_family; /* AF_IRDA */
+ unsigned char sir_lsap_sel; /* LSAP/TSAP selector */
+ unsigned int sir_addr; /* Device address */
+ char sir_name[25]; /* Usually <service>:IrDA:TinyTP */
+};
+
+struct irda_device_info {
+ unsigned int saddr; /* Address of remote device */
+ unsigned int daddr; /* Link where it was discovered */
+ char info[22]; /* Description */
+ unsigned char charset; /* Charset used for description */
+ unsigned char hints[2]; /* Hint bits */
+};
+
+struct irda_device_list {
+ unsigned int len;
+ struct irda_device_info dev[0];
+};
+
+struct irda_ias_set {
+ char irda_class_name[IAS_MAX_CLASSNAME];
+ char irda_attrib_name[IAS_MAX_ATTRIBNAME];
+ unsigned int irda_attrib_type;
+ union {
+ unsigned int irda_attrib_int;
+ struct {
+ unsigned short len;
+ u_char OctetSeq[IAS_MAX_OCTET_STRING];
+ } irda_attrib_octet_seq;
+ struct {
+ unsigned char len;
+ unsigned char charset;
+ unsigned char string[IAS_MAX_STRING];
+ } irda_attrib_string;
+ } attribute;
+};
+
+#endif /* KERNEL_IRDA_H */
+
+
+
+
diff --git a/pfinet/linux-src/include/linux/isdn.h b/pfinet/linux-src/include/linux/isdn.h
new file mode 100644
index 00000000..853f236f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/isdn.h
@@ -0,0 +1,901 @@
+/* $Id: isdn.h,v 1.70 1999/07/31 12:59:58 armin Exp $
+ *
+ * Main header for the Linux ISDN subsystem (linklevel).
+ *
+ * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
+ * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: isdn.h,v $
+ * Revision 1.70 1999/07/31 12:59:58 armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.69 1999/07/13 20:47:53 werner
+ * added channel bit ISDN_USAGE_DISABLED for limiting b-channel access.
+ *
+ * Revision 1.68 1999/07/11 17:07:37 armin
+ * Added tty modem register S23.
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ *
+ * Revision 1.67 1999/07/07 10:17:24 detabc
+ * remove unused messages
+ *
+ * Revision 1.66 1999/07/01 08:35:37 keil
+ * compatibility to 2.3
+ *
+ * Revision 1.65 1999/06/10 11:51:27 paul
+ * fixed comment for NET_DV
+ *
+ * Revision 1.64 1999/04/18 14:57:14 fritz
+ * Removed TIMRU stuff
+ *
+ * Revision 1.63 1999/04/18 14:07:18 fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.62 1999/04/12 13:16:54 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.61 1999/03/02 11:43:21 armin
+ * Added variable to store connect-message of Modem.
+ * Added Timer-define for RegS7 (Wait for Carrier).
+ *
+ * Revision 1.60 1998/10/25 14:50:29 fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.59 1998/10/23 10:18:55 paul
+ * Implementation of "dialmode" (successor of "status")
+ * You also need current isdnctrl for this!
+ *
+ * Revision 1.58 1998/10/23 10:10:06 fritz
+ * Test-Checkin
+ *
+ * Revision 1.57 1998/08/31 21:10:01 he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ * peer phone number)
+ *
+ * Revision 1.56 1998/07/26 18:46:52 armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.55 1998/06/26 15:13:17 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.54 1998/06/18 23:32:01 fritz
+ * Replaced cli()/restore_flags() in isdn_tty_write() by locking.
+ * Removed direct-senddown feature in isdn_tty_write because it will
+ * never succeed with locking and is useless anyway.
+ *
+ * Revision 1.53 1998/06/17 19:51:51 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.46 1998/04/14 16:28:59 he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.45 1998/03/24 16:33:12 hipp
+ * More CCP changes. BSD compression now "works" on a local loopback link.
+ * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
+ *
+ * Revision 1.44 1998/03/22 18:50:56 hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.43 1998/03/09 17:46:44 he
+ * merged in 2.1.89 changes
+ *
+ *
+ * Revision 1.40 1998/03/08 01:08:29 fritz
+ * Increased NET_DV because of TIMRU
+ *
+ * Revision 1.39 1998/03/07 22:42:49 fritz
+ * Starting generic module support (Nothing usable yet).
+ *
+ * Revision 1.38 1998/03/07 18:21:29 cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.37 1998/02/22 19:45:24 fritz
+ * Some changes regarding V.110
+ *
+ * Revision 1.36 1998/02/20 17:35:55 fritz
+ * Added V.110 stuff.
+ *
+ * Revision 1.35 1998/01/31 22:14:14 keil
+ * changes for 2.1.82
+ *
+ * Revision 1.34 1997/10/09 21:28:11 fritz
+ * New HL<->LL interface:
+ * New BSENT callback with nr. of bytes included.
+ * Sending without ACK.
+ * New L1 error status (not yet in use).
+ * Cleaned up obsolete structures.
+ * Implemented Cisco-SLARP.
+ * Changed local net-interface data to be dynamically allocated.
+ * Removed old 2.0 compatibility stuff.
+ *
+ * Revision 1.33 1997/08/21 14:44:22 fritz
+ * Moved triggercps to end of struct for backwards-compatibility.
+ *
+ * Revision 1.32 1997/08/21 09:49:46 fritz
+ * Increased NET_DV
+ *
+ * Revision 1.31 1997/06/22 11:57:07 fritz
+ * Added ability to adjust slave triggerlevel.
+ *
+ * Revision 1.30 1997/06/17 13:07:23 hipp
+ * compression changes , MP changes
+ *
+ * Revision 1.29 1997/05/27 15:18:02 fritz
+ * Added changes for recent 2.1.x kernels:
+ * changed return type of isdn_close
+ * queue_task_* -> queue_task
+ * clear/set_bit -> test_and_... where apropriate.
+ * changed type of hard_header_cache parameter.
+ *
+ * Revision 1.28 1997/03/07 01:33:01 fritz
+ * Added proper ifdef's for CONFIG_ISDN_AUDIO
+ *
+ * Revision 1.27 1997/03/05 21:11:49 fritz
+ * Minor fixes.
+ *
+ * Revision 1.26 1997/02/28 02:37:53 fritz
+ * Added some comments.
+ *
+ * Revision 1.25 1997/02/23 16:54:23 hipp
+ * some initial changes for future PPP compresion
+ *
+ * Revision 1.24 1997/02/18 09:42:45 fritz
+ * Bugfix: Increased ISDN_MODEM_ANZREG.
+ * Increased TTY_DV.
+ *
+ * Revision 1.23 1997/02/10 22:07:13 fritz
+ * Added 2 modem registers for numbering plan and screening info.
+ *
+ * Revision 1.22 1997/02/03 23:42:08 fritz
+ * Added ISDN_TIMER_RINGING
+ * Misc. changes for Kernel 2.1.X compatibility
+ *
+ * Revision 1.21 1997/01/17 01:19:10 fritz
+ * Applied chargeint patch.
+ *
+ * Revision 1.20 1997/01/17 00:41:19 fritz
+ * Increased TTY_DV.
+ *
+ * Revision 1.19 1997/01/14 01:41:07 fritz
+ * Added ATI2 related variables.
+ * Added variables for audio support in skbuffs.
+ *
+ * Revision 1.18 1996/11/06 17:37:50 keil
+ * more changes for 2.1.X
+ *
+ * Revision 1.17 1996/09/07 12:53:57 hipp
+ * moved a few isdn_ppp.c specific defines to drives/isdn/isdn_ppp.h
+ *
+ * Revision 1.16 1996/08/12 16:20:56 hipp
+ * renamed ppp_minor to ppp_slot
+ *
+ * Revision 1.15 1996/06/15 14:56:57 fritz
+ * Added version signatures for data structures used
+ * by userlevel programs.
+ *
+ * Revision 1.14 1996/06/06 21:24:23 fritz
+ * Started adding support for suspend/resume.
+ *
+ * Revision 1.13 1996/06/05 02:18:20 fritz
+ * Added DTMF decoding stuff.
+ *
+ * Revision 1.12 1996/06/03 19:55:08 fritz
+ * Fixed typos.
+ *
+ * Revision 1.11 1996/05/31 01:37:47 fritz
+ * Minor changes, due to changes in isdn_tty.c
+ *
+ * Revision 1.10 1996/05/18 01:37:18 fritz
+ * Added spelling corrections and some minor changes
+ * to stay in sync with kernel.
+ *
+ * Revision 1.9 1996/05/17 03:58:20 fritz
+ * Added flags for DLE handling.
+ *
+ * Revision 1.8 1996/05/11 21:49:55 fritz
+ * Removed queue management variables.
+ * Changed queue management to use sk_buffs.
+ *
+ * Revision 1.7 1996/05/07 09:10:06 fritz
+ * Reorganized tty-related structs.
+ *
+ * Revision 1.6 1996/05/06 11:38:27 hipp
+ * minor change in ippp struct
+ *
+ * Revision 1.5 1996/04/30 11:03:16 fritz
+ * Added Michael's ippp-bind patch.
+ *
+ * Revision 1.4 1996/04/29 23:00:02 fritz
+ * Added variables for voice-support.
+ *
+ * Revision 1.3 1996/04/20 16:54:58 fritz
+ * Increased maximum number of channels.
+ * Added some flags for isdn_net to handle callback more reliable.
+ * Fixed delay-definitions to be more accurate.
+ * Misc. typos
+ *
+ * Revision 1.2 1996/02/11 02:10:02 fritz
+ * Changed IOCTL-names
+ * Added rx_netdev, st_netdev, first_skb, org_hcb, and org_hcu to
+ * Netdevice-local struct.
+ *
+ * Revision 1.1 1996/01/10 20:55:07 fritz
+ * Initial revision
+ *
+ */
+
+#ifndef isdn_h
+#define isdn_h
+
+#include <linux/isdn_compat.h>
+#include <linux/config.h>
+#include <linux/ioctl.h>
+
+#define ISDN_TTY_MAJOR 43
+#define ISDN_TTYAUX_MAJOR 44
+#define ISDN_MAJOR 45
+
+/* The minor-devicenumbers for Channel 0 and 1 are used as arguments for
+ * physical Channel-Mapping, so they MUST NOT be changed without changing
+ * the correspondent code in isdn.c
+ */
+
+#ifdef CONFIG_COBALT_MICRO_SERVER
+/* Save memory */
+#define ISDN_MAX_DRIVERS 2
+#define ISDN_MAX_CHANNELS 8
+#else
+#define ISDN_MAX_DRIVERS 32
+#define ISDN_MAX_CHANNELS 64
+#endif
+#define ISDN_MINOR_B 0
+#define ISDN_MINOR_BMAX (ISDN_MAX_CHANNELS-1)
+#define ISDN_MINOR_CTRL 64
+#define ISDN_MINOR_CTRLMAX (64 + (ISDN_MAX_CHANNELS-1))
+#define ISDN_MINOR_PPP 128
+#define ISDN_MINOR_PPPMAX (128 + (ISDN_MAX_CHANNELS-1))
+#define ISDN_MINOR_STATUS 255
+
+/* New ioctl-codes */
+#define IIOCNETAIF _IO('I',1)
+#define IIOCNETDIF _IO('I',2)
+#define IIOCNETSCF _IO('I',3)
+#define IIOCNETGCF _IO('I',4)
+#define IIOCNETANM _IO('I',5)
+#define IIOCNETDNM _IO('I',6)
+#define IIOCNETGNM _IO('I',7)
+#define IIOCGETSET _IO('I',8) /* no longer supported */
+#define IIOCSETSET _IO('I',9) /* no longer supported */
+#define IIOCSETVER _IO('I',10)
+#define IIOCNETHUP _IO('I',11)
+#define IIOCSETGST _IO('I',12)
+#define IIOCSETBRJ _IO('I',13)
+#define IIOCSIGPRF _IO('I',14)
+#define IIOCGETPRF _IO('I',15)
+#define IIOCSETPRF _IO('I',16)
+#define IIOCGETMAP _IO('I',17)
+#define IIOCSETMAP _IO('I',18)
+#define IIOCNETASL _IO('I',19)
+#define IIOCNETDIL _IO('I',20)
+#define IIOCGETCPS _IO('I',21)
+#define IIOCGETDVR _IO('I',22)
+
+#define IIOCNETALN _IO('I',32)
+#define IIOCNETDLN _IO('I',33)
+
+#define IIOCNETGPN _IO('I',34)
+
+#define IIOCDBGVAR _IO('I',127)
+
+#define IIOCDRVCTL _IO('I',128)
+
+/* Packet encapsulations for net-interfaces */
+#define ISDN_NET_ENCAP_ETHER 0
+#define ISDN_NET_ENCAP_RAWIP 1
+#define ISDN_NET_ENCAP_IPTYP 2
+#define ISDN_NET_ENCAP_CISCOHDLC 3 /* Without SLARP and keepalive */
+#define ISDN_NET_ENCAP_SYNCPPP 4
+#define ISDN_NET_ENCAP_UIHDLC 5
+#define ISDN_NET_ENCAP_CISCOHDLCK 6 /* With SLARP and keepalive */
+#define ISDN_NET_ENCAP_X25IFACE 7 /* Documentation/networking/x25-iface.txt*/
+#define ISDN_NET_ENCAP_MAX_ENCAP ISDN_NET_ENCAP_X25IFACE
+/* Facility which currently uses an ISDN-channel */
+#define ISDN_USAGE_NONE 0
+#define ISDN_USAGE_RAW 1
+#define ISDN_USAGE_MODEM 2
+#define ISDN_USAGE_NET 3
+#define ISDN_USAGE_VOICE 4
+#define ISDN_USAGE_FAX 5
+#define ISDN_USAGE_MASK 7 /* Mask to get plain usage */
+#define ISDN_USAGE_DISABLED 32 /* This bit is set, if channel is disabled */
+#define ISDN_USAGE_EXCLUSIVE 64 /* This bit is set, if channel is exclusive */
+#define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing */
+
+#define ISDN_MODEM_ANZREG 24 /* Number of Modem-Registers */
+#define ISDN_MSNLEN 20
+#define ISDN_LMSNLEN 255 /* Length of tty's Listen-MSN string */
+#define ISDN_CMSGLEN 50 /* Length of CONNECT-Message to add for Modem */
+
+typedef struct {
+ char drvid[25];
+ unsigned long arg;
+} isdn_ioctl_struct;
+
+typedef struct {
+ unsigned long isdndev;
+ unsigned long atmodem[ISDN_MAX_CHANNELS];
+ unsigned long info[ISDN_MAX_CHANNELS];
+} debugvar_addr;
+
+typedef struct {
+ char name[10];
+ char phone[ISDN_MSNLEN];
+ int outgoing;
+} isdn_net_ioctl_phone;
+
+#define NET_DV 0x05 /* Data version for isdn_net_ioctl_cfg */
+#define TTY_DV 0x05 /* Data version for iprofd etc. */
+#define INF_DV 0x01 /* Data version for /dev/isdninfo */
+
+typedef struct {
+ char name[10]; /* Name of interface */
+ char master[10]; /* Name of Master for Bundling */
+ char slave[10]; /* Name of Slave for Bundling */
+ char eaz[256]; /* EAZ/MSN */
+ char drvid[25]; /* DriverId for Bindings */
+ int onhtime; /* Hangup-Timeout */
+ int charge; /* Charge-Units */
+ int l2_proto; /* Layer-2 protocol */
+ int l3_proto; /* Layer-3 protocol */
+ int p_encap; /* Encapsulation */
+ int exclusive; /* Channel, if bound exclusive */
+ int dialmax; /* Dial Retry-Counter */
+ int slavedelay; /* Delay until slave starts up */
+ int cbdelay; /* Delay before Callback */
+ int chargehup; /* Flag: Charge-Hangup */
+ int ihup; /* Flag: Hangup-Timeout on incoming line */
+ int secure; /* Flag: Secure */
+ int callback; /* Flag: Callback */
+ int cbhup; /* Flag: Reject Call before Callback */
+ int pppbind; /* ippp device for bindings */
+ int chargeint; /* Use fixed charge interval length */
+ int triggercps; /* BogoCPS needed for triggering slave */
+ int dialtimeout; /* Dial-Timeout */
+ int dialwait; /* Time to wait after failed dial */
+ int dialmode; /* Flag: off / on / auto */
+} isdn_net_ioctl_cfg;
+
+#define ISDN_NET_DIALMODE_MASK 0xC0 /* bits for status */
+#define ISDN_NET_DM_OFF 0x00 /* this interface is stopped */
+#define ISDN_NET_DM_MANUAL 0x40 /* this interface is on (manual) */
+#define ISDN_NET_DM_AUTO 0x80 /* this interface is autodial */
+#define ISDN_NET_DIALMODE(x) ((&(x))->flags & ISDN_NET_DIALMODE_MASK)
+
+#ifdef __KERNEL__
+
+#ifndef STANDALONE
+#include <linux/config.h>
+#endif
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/malloc.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/fcntl.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+
+#ifdef CONFIG_ISDN_PPP
+
+#ifdef CONFIG_ISDN_PPP_VJ
+# include <net/slhc_vj.h>
+#endif
+
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/if_pppvar.h>
+
+#include <linux/isdn_ppp.h>
+#endif
+
+#ifdef CONFIG_ISDN_X25
+# include <linux/concap.h>
+#endif
+
+#include <linux/isdnif.h>
+
+
+#define ISDN_DRVIOCTL_MASK 0x7f /* Mask for Device-ioctl */
+
+/* Until now unused */
+#define ISDN_SERVICE_VOICE 1
+#define ISDN_SERVICE_AB 1<<1
+#define ISDN_SERVICE_X21 1<<2
+#define ISDN_SERVICE_G4 1<<3
+#define ISDN_SERVICE_BTX 1<<4
+#define ISDN_SERVICE_DFUE 1<<5
+#define ISDN_SERVICE_X25 1<<6
+#define ISDN_SERVICE_TTX 1<<7
+#define ISDN_SERVICE_MIXED 1<<8
+#define ISDN_SERVICE_FW 1<<9
+#define ISDN_SERVICE_GTEL 1<<10
+#define ISDN_SERVICE_BTXN 1<<11
+#define ISDN_SERVICE_BTEL 1<<12
+
+/* Macros checking plain usage */
+#define USG_NONE(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NONE)
+#define USG_RAW(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_RAW)
+#define USG_MODEM(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM)
+#define USG_VOICE(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)
+#define USG_NET(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NET)
+#define USG_FAX(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_FAX)
+#define USG_OUTGOING(x) ((x & ISDN_USAGE_OUTGOING)==ISDN_USAGE_OUTGOING)
+#define USG_MODEMORVOICE(x) (((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) || \
+ ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE) )
+
+/* Timer-delays and scheduling-flags */
+#define ISDN_TIMER_RES 3 /* Main Timer-Resolution */
+#define ISDN_TIMER_02SEC (HZ/(ISDN_TIMER_RES+1)/5) /* Slow-Timer1 .2 sec */
+#define ISDN_TIMER_1SEC (HZ/(ISDN_TIMER_RES+1)) /* Slow-Timer2 1 sec */
+#define ISDN_TIMER_RINGING 5 /* tty RINGs = ISDN_TIMER_1SEC * this factor */
+#define ISDN_TIMER_KEEPINT 10 /* Cisco-Keepalive = ISDN_TIMER_1SEC * this factor */
+#define ISDN_TIMER_MODEMREAD 1
+#define ISDN_TIMER_MODEMPLUS 2
+#define ISDN_TIMER_MODEMRING 4
+#define ISDN_TIMER_MODEMXMIT 8
+#define ISDN_TIMER_NETDIAL 16
+#define ISDN_TIMER_NETHANGUP 32
+#define ISDN_TIMER_IPPP 64
+#define ISDN_TIMER_KEEPALIVE 128 /* Cisco-Keepalive */
+#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */
+#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
+ ISDN_TIMER_MODEMXMIT)
+#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
+ ISDN_TIMER_NETDIAL | ISDN_TIMER_KEEPALIVE | \
+ ISDN_TIMER_CARRIER)
+
+/* Timeout-Values for isdn_net_dial() */
+#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
+#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
+#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
+
+/* GLOBAL_FLAGS */
+#define ISDN_GLOBAL_STOPPED 1
+
+/*=================== Start of ip-over-ISDN stuff =========================*/
+
+/* Feature- and status-flags for a net-interface */
+#define ISDN_NET_CONNECTED 0x01 /* Bound to ISDN-Channel */
+#define ISDN_NET_SECURE 0x02 /* Accept calls from phonelist only */
+#define ISDN_NET_CALLBACK 0x04 /* activate callback */
+#define ISDN_NET_CBHUP 0x08 /* hangup before callback */
+#define ISDN_NET_CBOUT 0x10 /* remote machine does callback */
+#if 0
+/* Unused??? */
+#define ISDN_NET_CLONE 0x08 /* clone a tmp interface when called */
+#define ISDN_NET_TMP 0x10 /* tmp interface until getting an IP */
+#define ISDN_NET_DYNAMIC 0x20 /* this link is dynamically allocated */
+#endif
+
+#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */
+
+/* Phone-list-element */
+typedef struct {
+ void *next;
+ char num[ISDN_MSNLEN];
+} isdn_net_phone;
+
+/*
+ Principles when extending structures for generic encapsulation protocol
+ ("concap") support:
+ - Stuff which is hardware specific (here i4l-specific) goes in
+ the netdev -> local structure (here: isdn_net_local)
+ - Stuff which is encapsulation protocol specific goes in the structure
+ which holds the linux device structure (here: isdn_net_device)
+*/
+
+/* Local interface-data */
+typedef struct isdn_net_local_s {
+ ulong magic;
+ char name[10]; /* Name of device */
+ struct enet_statistics stats; /* Ethernet Statistics */
+ int isdn_device; /* Index to isdn-device */
+ int isdn_channel; /* Index to isdn-channel */
+ int ppp_slot; /* PPPD device slot number */
+ int pre_device; /* Preselected isdn-device */
+ int pre_channel; /* Preselected isdn-channel */
+ int exclusive; /* If non-zero idx to reserved chan.*/
+ int flags; /* Connection-flags */
+ int dialretry; /* Counter for Dialout-retries */
+ int dialmax; /* Max. Number of Dial-retries */
+ int cbdelay; /* Delay before Callback starts */
+ int dtimer; /* Timeout-counter for dialing */
+ char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */
+ u_char cbhup; /* Flag: Reject Call before Callback*/
+ u_char dialstate; /* State for dialing */
+ u_char p_encap; /* Packet encapsulation */
+ /* 0 = Ethernet over ISDN */
+ /* 1 = RAW-IP */
+ /* 2 = IP with type field */
+ u_char l2_proto; /* Layer-2-protocol */
+ /* See ISDN_PROTO_L2..-constants in */
+ /* isdnif.h */
+ /* 0 = X75/LAPB with I-Frames */
+ /* 1 = X75/LAPB with UI-Frames */
+ /* 2 = X75/LAPB with BUI-Frames */
+ /* 3 = HDLC */
+ u_char l3_proto; /* Layer-3-protocol */
+ /* See ISDN_PROTO_L3..-constants in */
+ /* isdnif.h */
+ /* 0 = Transparent */
+ int huptimer; /* Timeout-counter for auto-hangup */
+ int charge; /* Counter for charging units */
+ int chargetime; /* Timer for Charging info */
+ int hupflags; /* Flags for charge-unit-hangup: */
+ /* bit0: chargeint is invalid */
+ /* bit1: Getting charge-interval */
+ /* bit2: Do charge-unit-hangup */
+ /* bit3: Do hangup even on incoming */
+ int outgoing; /* Flag: outgoing call */
+ int onhtime; /* Time to keep link up */
+ int chargeint; /* Interval between charge-infos */
+ int onum; /* Flag: at least 1 outgoing number */
+ int cps; /* current speed of this interface */
+ int transcount; /* byte-counter for cps-calculation */
+ int sqfull; /* Flag: netdev-queue overloaded */
+ ulong sqfull_stamp; /* Start-Time of overload */
+ ulong slavedelay; /* Dynamic bundling delaytime */
+ int triggercps; /* BogoCPS needed for trigger slave */
+ struct device *srobin; /* Ptr to Master device for slaves */
+ isdn_net_phone *phone[2]; /* List of remote-phonenumbers */
+ /* phone[0] = Incoming Numbers */
+ /* phone[1] = Outgoing Numbers */
+ isdn_net_phone *dial; /* Pointer to dialed number */
+ struct device *master; /* Ptr to Master device for slaves */
+ struct device *slave; /* Ptr to Slave device for masters */
+ struct isdn_net_local_s *next; /* Ptr to next link in bundle */
+ struct isdn_net_local_s *last; /* Ptr to last link in bundle */
+ struct isdn_net_dev_s *netdev; /* Ptr to netdev */
+ struct sk_buff *first_skb; /* Ptr to skb that triggers dialing */
+ struct sk_buff *sav_skb; /* Ptr to skb, rejected by LL-driver*/
+ /* Ptr to orig. hard_header_cache */
+ int (*org_hhc)(
+ struct neighbour *neigh,
+ struct hh_cache *hh);
+ /* Ptr to orig. header_cache_update */
+ void (*org_hcu)(struct hh_cache *,
+ struct device *,
+ unsigned char *);
+ int pppbind; /* ippp device for bindings */
+ int dialtimeout; /* How long shall we try on dialing? (jiffies) */
+ int dialwait; /* How long shall we wait after failed attempt? (jiffies) */
+ ulong dialstarted; /* jiffies of first dialing-attempt */
+ ulong dialwait_timer; /* jiffies of earliest next dialing-attempt */
+ int huptimeout; /* How long will the connection be up? (seconds) */
+#ifdef CONFIG_ISDN_X25
+ struct concap_device_ops *dops; /* callbacks used by encapsulator */
+#endif
+ int cisco_loop; /* Loop counter for Cisco-SLARP */
+ ulong cisco_myseq; /* Local keepalive seq. for Cisco */
+ ulong cisco_yourseq; /* Remote keepalive seq. for Cisco */
+} isdn_net_local;
+
+/* the interface itself */
+typedef struct isdn_net_dev_s {
+ isdn_net_local *local;
+ isdn_net_local *queue;
+ void *next; /* Pointer to next isdn-interface */
+ struct device dev; /* interface to upper levels */
+#ifdef CONFIG_ISDN_PPP
+ struct mpqueue *mp_last;
+ struct ippp_bundle ib;
+#endif
+#ifdef CONFIG_ISDN_X25
+ struct concap_proto *cprot; /* connection oriented encapsulation protocol */
+#endif
+
+} isdn_net_dev;
+
+/*===================== End of ip-over-ISDN stuff ===========================*/
+
+/*======================= Start of ISDN-tty stuff ===========================*/
+
+#define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */
+#define ISDN_ASYNC_INITIALIZED 0x80000000 /* port was initialized */
+#define ISDN_ASYNC_CALLOUT_ACTIVE 0x40000000 /* Call out device active */
+#define ISDN_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device active */
+#define ISDN_ASYNC_CLOSING 0x08000000 /* Serial port is closing */
+#define ISDN_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */
+#define ISDN_ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */
+#define ISDN_ASYNC_HUP_NOTIFY 0x0001 /* Notify tty on hangups/closes */
+#define ISDN_ASYNC_SESSION_LOCKOUT 0x0100 /* Lock cua opens on session */
+#define ISDN_ASYNC_PGRP_LOCKOUT 0x0200 /* Lock cua opens on pgrp */
+#define ISDN_ASYNC_CALLOUT_NOHUP 0x0400 /* No hangup for cui */
+#define ISDN_ASYNC_SPLIT_TERMIOS 0x0008 /* Sep. termios for dialin/out */
+#define ISDN_SERIAL_XMIT_SIZE 1024 /* Default bufsize for write */
+#define ISDN_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */
+#define ISDN_SERIAL_TYPE_NORMAL 1
+#define ISDN_SERIAL_TYPE_CALLOUT 2
+
+#ifdef CONFIG_ISDN_AUDIO
+/* For using sk_buffs with audio we need some private variables
+ * within each sk_buff. For this purpose, we declare a struct here,
+ * and put it always at skb->head. A few macros help accessing the
+ * variables. Of course, we need to check skb_headroom prior to
+ * any access.
+ */
+typedef struct isdn_audio_skb {
+ unsigned short dle_count;
+ unsigned char lock;
+} isdn_audio_skb;
+
+#define ISDN_AUDIO_SKB_DLECOUNT(skb) (((isdn_audio_skb*)skb->head)->dle_count)
+#define ISDN_AUDIO_SKB_LOCK(skb) (((isdn_audio_skb*)skb->head)->lock)
+#endif
+
+/* Private data of AT-command-interpreter */
+typedef struct atemu {
+ u_char profile[ISDN_MODEM_ANZREG]; /* Modem-Regs. Profile 0 */
+ u_char mdmreg[ISDN_MODEM_ANZREG]; /* Modem-Registers */
+ char pmsn[ISDN_MSNLEN]; /* EAZ/MSNs Profile 0 */
+ char msn[ISDN_MSNLEN]; /* EAZ/MSN */
+ char plmsn[ISDN_LMSNLEN]; /* Listening MSNs Profile 0 */
+ char lmsn[ISDN_LMSNLEN]; /* Listening MSNs */
+ char cpn[ISDN_MSNLEN]; /* CalledPartyNumber on incoming call */
+ char connmsg[ISDN_CMSGLEN]; /* CONNECT-Msg from HL-Driver */
+#ifdef CONFIG_ISDN_AUDIO
+ u_char vpar[10]; /* Voice-parameters */
+ int lastDLE; /* Flag for voice-coding: DLE seen */
+#endif
+ int mdmcmdl; /* Length of Modem-Commandbuffer */
+ int pluscount; /* Counter for +++ sequence */
+ int lastplus; /* Timestamp of last + */
+ int carrierwait; /* Seconds of carrier waiting */
+ char mdmcmd[255]; /* Modem-Commandbuffer */
+ unsigned int charge; /* Charge units of current connection */
+} atemu;
+
+/* Private data (similar to async_struct in <linux/serial.h>) */
+typedef struct modem_info {
+ int magic;
+ int flags; /* defined in tty.h */
+ int x_char; /* xon/xoff character */
+ int mcr; /* Modem control register */
+ int msr; /* Modem status register */
+ int lsr; /* Line status register */
+ int line;
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ int online; /* 1 = B-Channel is up, drop data */
+ /* 2 = B-Channel is up, deliver d.*/
+ int dialing; /* Dial in progress or ATA */
+ int rcvsched; /* Receive needs schedule */
+ int isdn_driver; /* Index to isdn-driver */
+ int isdn_channel; /* Index to isdn-channel */
+ int drv_index; /* Index to dev->usage */
+ int ncarrier; /* Flag: schedule NO CARRIER */
+ unsigned char last_cause[8]; /* Last cause message */
+ unsigned char last_num[ISDN_MSNLEN];
+ /* Last phone-number */
+ unsigned char last_l2; /* Last layer-2 protocol */
+ unsigned char last_si; /* Last service */
+ unsigned char last_lhup; /* Last hangup local? */
+ unsigned char last_dir; /* Last direction (in or out) */
+ struct timer_list nc_timer; /* Timer for delayed NO CARRIER */
+ int send_outstanding;/* # of outstanding send-requests */
+ int xmit_size; /* max. # of chars in xmit_buf */
+ int xmit_count; /* # of chars in xmit_buf */
+ unsigned char *xmit_buf; /* transmit buffer */
+ struct sk_buff_head xmit_queue; /* transmit queue */
+ atomic_t xmit_lock; /* Semaphore for isdn_tty_write */
+#ifdef CONFIG_ISDN_AUDIO
+ int vonline; /* Voice-channel status */
+ /* Bit 0 = recording */
+ /* Bit 1 = playback */
+ /* Bit 2 = playback, DLE-ETX seen */
+ struct sk_buff_head dtmf_queue; /* queue for dtmf results */
+ void *adpcms; /* state for adpcm decompression */
+ void *adpcmr; /* state for adpcm compression */
+ void *dtmf_state; /* state for dtmf decoder */
+ void *silence_state; /* state for silence detection */
+#endif
+#ifdef CONFIG_ISDN_TTY_FAX
+ struct T30_s *fax; /* T30 Fax Group 3 data/interface */
+ int faxonline; /* Fax-channel status */
+#endif
+ struct tty_struct *tty; /* Pointer to corresponding tty */
+ atemu emu; /* AT-emulator data */
+ struct termios normal_termios; /* For saving termios structs */
+ struct termios callout_termios;
+#ifdef COMPAT_HAS_NEW_WAITQ
+ wait_queue_head_t open_wait, close_wait;
+#else
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+#endif
+ struct semaphore write_sem;
+} modem_info;
+
+#define ISDN_MODEM_WINSIZE 8
+
+/* Description of one ISDN-tty */
+typedef struct {
+ int refcount; /* Number of opens */
+ struct tty_driver tty_modem; /* tty-device */
+ struct tty_driver cua_modem; /* cua-device */
+ struct tty_struct *modem_table[ISDN_MAX_CHANNELS]; /* ?? copied from Orig */
+ struct termios *modem_termios[ISDN_MAX_CHANNELS];
+ struct termios *modem_termios_locked[ISDN_MAX_CHANNELS];
+ modem_info info[ISDN_MAX_CHANNELS]; /* Private data */
+} modem;
+
+/*======================= End of ISDN-tty stuff ============================*/
+
+/*======================== Start of V.110 stuff ============================*/
+#define V110_BUFSIZE 1024
+
+typedef struct {
+ int nbytes; /* 1 Matrixbyte -> nbytes in stream */
+ int nbits; /* Number of used bits in streambyte */
+ unsigned char key; /* Bitmask in stream eg. 11 (nbits=2) */
+ int decodelen; /* Amount of data in decodebuf */
+ int SyncInit; /* Number of sync frames to send */
+ unsigned char *OnlineFrame; /* Precalculated V110 idle frame */
+ unsigned char *OfflineFrame; /* Precalculated V110 sync Frame */
+ int framelen; /* Length of frames */
+ int skbuser; /* Number of unacked userdata skbs */
+ int skbidle; /* Number of unacked idle/sync skbs */
+ int introducer; /* Local vars for decoder */
+ int dbit;
+ unsigned char b;
+ int skbres; /* space to reserve in outgoing skb */
+ int maxsize; /* maxbufsize of lowlevel driver */
+ unsigned char *encodebuf; /* temporary buffer for encoding */
+ unsigned char decodebuf[V110_BUFSIZE]; /* incomplete V110 matrices */
+} isdn_v110_stream;
+
+/*========================= End of V.110 stuff =============================*/
+
+/*======================= Start of general stuff ===========================*/
+
+typedef struct {
+ char *next;
+ char *private;
+} infostruct;
+
+typedef struct isdn_module {
+ struct isdn_module *prev;
+ struct isdn_module *next;
+ char *name;
+ int (*get_free_channel)(int, int, int, int, int);
+ int (*free_channel)(int, int, int);
+ int (*status_callback)(isdn_ctrl *);
+ int (*command)(isdn_ctrl *);
+ int (*receive_callback)(int, int, struct sk_buff *);
+ int (*writebuf_skb)(int, int, int, struct sk_buff *);
+ int (*net_start_xmit)(struct sk_buff *, struct device *);
+ int (*net_receive)(struct device *, struct sk_buff *);
+ int (*net_open)(struct device *);
+ int (*net_close)(struct device *);
+ int priority;
+} isdn_module;
+
+#define DRV_FLAG_RUNNING 1
+#define DRV_FLAG_REJBUS 2
+#define DRV_FLAG_LOADED 4
+
+/* Description of hardware-level-driver */
+typedef struct {
+ ulong online; /* Channel-Online flags */
+ ulong flags; /* Misc driver Flags */
+ int locks; /* Number of locks for this driver */
+ int channels; /* Number of channels */
+#ifdef COMPAT_HAS_NEW_WAITQ
+ wait_queue_head_t st_waitq; /* Wait-Queue for status-read's */
+#else
+ struct wait_queue *st_waitq; /* Wait-Queue for status-read's */
+#endif
+ int maxbufsize; /* Maximum Buffersize supported */
+ unsigned long pktcount; /* Until now: unused */
+ int stavail; /* Chars avail on Status-device */
+ isdn_if *interface; /* Interface to driver */
+ int *rcverr; /* Error-counters for B-Ch.-receive */
+ int *rcvcount; /* Byte-counters for B-Ch.-receive */
+#ifdef CONFIG_ISDN_AUDIO
+ unsigned long DLEflag; /* Flags: Insert DLE at next read */
+#endif
+ struct sk_buff_head *rpqueue; /* Pointers to start of Rcv-Queue */
+#ifdef COMPAT_HAS_NEW_WAITQ
+ wait_queue_head_t *rcv_waitq; /* Wait-Queues for B-Channel-Reads */
+ wait_queue_head_t *snd_waitq; /* Wait-Queue for B-Channel-Send's */
+#else
+ struct wait_queue **rcv_waitq; /* Wait-Queues for B-Channel-Reads */
+ struct wait_queue **snd_waitq; /* Wait-Queue for B-Channel-Send's */
+#endif
+ char msn2eaz[10][ISDN_MSNLEN]; /* Mapping-Table MSN->EAZ */
+} driver;
+
+/* Main driver-data */
+typedef struct isdn_devt {
+ unsigned short flags; /* Bitmapped Flags: */
+ /* */
+ int drivers; /* Current number of drivers */
+ int channels; /* Current number of channels */
+ int net_verbose; /* Verbose-Flag */
+ int modempoll; /* Flag: tty-read active */
+ int tflags; /* Timer-Flags: */
+ /* see ISDN_TIMER_..defines */
+ int global_flags;
+ infostruct *infochain; /* List of open info-devs. */
+#ifdef COMPAT_HAS_NEW_WAITQ
+ wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */
+#else
+ struct wait_queue *info_waitq; /* Wait-Queue for isdninfo */
+#endif
+ struct timer_list timer; /* Misc.-function Timer */
+ int chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel */
+ int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */
+ int usage[ISDN_MAX_CHANNELS]; /* Used by tty/ip/voice */
+ char num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
+ /* Remote number of active ch.*/
+ int m_idx[ISDN_MAX_CHANNELS]; /* Index for mdm.... */
+ driver *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */
+ isdn_net_dev *netdev; /* Linked list of net-if's */
+ char drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID */
+ struct task_struct *profd; /* For iprofd */
+ modem mdm; /* tty-driver-data */
+ isdn_net_dev *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers */
+ isdn_net_dev *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers */
+ ulong ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes */
+ ulong obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes */
+ int v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */
+ atomic_t v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
+ isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */
+ struct semaphore sem; /* serialize list access*/
+ isdn_module *modules;
+} isdn_dev;
+
+extern isdn_dev *dev;
+
+
+/* Utility-Macros */
+#define MIN(a,b) ((a<b)?a:b)
+#define MAX(a,b) ((a>b)?a:b)
+#endif /* __KERNEL__ */
+#endif /* isdn_h */
diff --git a/pfinet/linux-src/include/linux/isdn_compat.h b/pfinet/linux-src/include/linux/isdn_compat.h
new file mode 100644
index 00000000..db002c41
--- /dev/null
+++ b/pfinet/linux-src/include/linux/isdn_compat.h
@@ -0,0 +1,108 @@
+#ifdef __KERNEL__
+/* Compatibility for various Linux kernel versions */
+
+#ifndef _LINUX_ISDN_COMPAT_H
+#define _LINUX_ISDN_COMPAT_H
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+#include <linux/mm.h>
+
+#define ioremap vremap
+#define ioremap_nocache vremap
+#define iounmap vfree
+
+static inline unsigned long copy_from_user(void *to, const void *from, unsigned long n)
+{
+ int i;
+ if ((i = verify_area(VERIFY_READ, from, n)) != 0)
+ return i;
+ memcpy_fromfs(to, from, n);
+ return 0;
+}
+
+static inline unsigned long copy_to_user(void *to, const void *from, unsigned long n)
+{
+ int i;
+ if ((i = verify_area(VERIFY_WRITE, to, n)) != 0)
+ return i;
+ memcpy_tofs(to, from, n);
+ return 0;
+}
+
+#define GET_USER(x, addr) ( x = get_user(addr) )
+#ifdef __alpha__ /* needed for 2.0.x with alpha-patches */
+#define RWTYPE long
+#define LSTYPE long
+#define RWARG unsigned long
+#else
+#define RWTYPE int
+#define LSTYPE int
+#define RWARG int
+#endif
+#define LSARG off_t
+#else
+#include <asm/uaccess.h>
+#define GET_USER get_user
+#define PUT_USER put_user
+#define RWTYPE long
+#define LSTYPE long long
+#define RWARG unsigned long
+#define LSARG long long
+#endif /* LINUX_VERSION_CODE */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,15)
+#define SET_SKB_FREE(x) ( x->free = 1 )
+#define idev_kfree_skb(a,b) dev_kfree_skb(a,b)
+#else
+#define SET_SKB_FREE(x)
+#define idev_kfree_skb(a,b) dev_kfree_skb(a)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,18)
+#define COMPAT_HAS_NEW_SYMTAB
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,31)
+#define CLOSETYPE void
+#define CLOSEVAL
+#else
+#define CLOSETYPE int
+#define CLOSEVAL (0)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,37)
+#define test_and_clear_bit clear_bit
+#define test_and_set_bit set_bit
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,81)
+#define kstat_irqs( PAR ) kstat.interrupts[PAR]
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,91)
+#define COMPAT_HAS_NEW_PCI
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
+#define get_pcibase(ps, nr) ps->base_address[nr]
+#else
+#define get_pcibase(ps, nr) ps->resource[nr].start
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127)
+#define schedule_timeout(a) current->timeout = jiffies + (a); schedule ();
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
+#define COMPAT_HAS_NEW_WAITQ
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_ISDN_COMPAT_H */
diff --git a/pfinet/linux-src/include/linux/isdn_divertif.h b/pfinet/linux-src/include/linux/isdn_divertif.h
new file mode 100644
index 00000000..2892d021
--- /dev/null
+++ b/pfinet/linux-src/include/linux/isdn_divertif.h
@@ -0,0 +1,62 @@
+/*
+ * $Id: isdn_divertif.h,v 1.3 1999/07/05 20:22:00 werner Exp $
+ *
+ * Header for the diversion supplementary interface for i4l.
+ *
+ * Copyright 1998 by Werner Cornelius (werner@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: isdn_divertif.h,v $
+ * Revision 1.3 1999/07/05 20:22:00 werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.2 1999/07/04 21:38:38 werner
+ * ported from kernel version 2.0
+ *
+ *
+ */
+
+
+/***********************************************************/
+/* magic value is also used to control version information */
+/***********************************************************/
+#define DIVERT_IF_MAGIC 0x25873401
+#define DIVERT_CMD_REG 0x00 /* register command */
+#define DIVERT_CMD_REL 0x01 /* release command */
+#define DIVERT_NO_ERR 0x00 /* return value no error */
+#define DIVERT_CMD_ERR 0x01 /* invalid cmd */
+#define DIVERT_VER_ERR 0x02 /* magic/version invalid */
+#define DIVERT_REG_ERR 0x03 /* module already registered */
+#define DIVERT_REL_ERR 0x04 /* module not registered */
+#define DIVERT_REG_NAME isdn_register_divert
+
+/***************************************************************/
+/* structure exchanging data between isdn hl and divert module */
+/***************************************************************/
+typedef struct
+ { ulong if_magic; /* magic info and version */
+ int cmd; /* command */
+ int (*stat_callback)(isdn_ctrl *); /* supplied by divert module when calling */
+ int (*ll_cmd)(isdn_ctrl *); /* supplied by hl on return */
+ char * (*drv_to_name)(int); /* map a driver id to name, supplied by hl */
+ int (*name_to_drv)(char *); /* map a driver id to name, supplied by hl */
+ } isdn_divert_if;
+
+/*********************/
+/* function register */
+/*********************/
+extern int DIVERT_REG_NAME(isdn_divert_if *);
diff --git a/pfinet/linux-src/include/linux/isdn_ppp.h b/pfinet/linux-src/include/linux/isdn_ppp.h
new file mode 100644
index 00000000..a62101d0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/isdn_ppp.h
@@ -0,0 +1,240 @@
+/* -*- mode: c; c-basic-offset: 2 -*- */
+
+#ifndef _LINUX_ISDN_PPP_H
+#define _LINUX_ISDN_PPP_H
+
+#include <linux/isdn_compat.h>
+
+#define CALLTYPE_INCOMING 0x1
+#define CALLTYPE_OUTGOING 0x2
+#define CALLTYPE_CALLBACK 0x4
+
+#define IPPP_VERSION "2.2.0"
+
+struct pppcallinfo
+{
+ int calltype;
+ unsigned char local_num[64];
+ unsigned char remote_num[64];
+ int charge_units;
+};
+
+#define PPPIOCGCALLINFO _IOWR('t',128,struct pppcallinfo)
+#define PPPIOCBUNDLE _IOW('t',129,int)
+#define PPPIOCGMPFLAGS _IOR('t',130,int)
+#define PPPIOCSMPFLAGS _IOW('t',131,int)
+#define PPPIOCSMPMTU _IOW('t',132,int)
+#define PPPIOCSMPMRU _IOW('t',133,int)
+#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long [8])
+#define PPPIOCSCOMPRESSOR _IOW('t',135,int)
+#define PPPIOCGIFNAME _IOR('t',136, char [IFNAMSIZ] )
+
+#define PPP_MP 0x003d
+#define PPP_LINK_COMP 0x00fb
+#define PPP_LINK_CCP 0x80fb
+
+#define SC_MP_PROT 0x00000200
+#define SC_REJ_MP_PROT 0x00000400
+#define SC_OUT_SHORT_SEQ 0x00000800
+#define SC_IN_SHORT_SEQ 0x00004000
+
+#define SC_DECOMP_ON 0x01
+#define SC_COMP_ON 0x02
+#define SC_DECOMP_DISCARD 0x04
+#define SC_COMP_DISCARD 0x08
+#define SC_LINK_DECOMP_ON 0x10
+#define SC_LINK_COMP_ON 0x20
+#define SC_LINK_DECOMP_DISCARD 0x40
+#define SC_LINK_COMP_DISCARD 0x80
+
+#define DECOMP_ERR_NOMEM (-10)
+
+#define MP_END_FRAG 0x40
+#define MP_BEGIN_FRAG 0x80
+
+#define ISDN_PPP_COMP_MAX_OPTIONS 16
+
+#define IPPP_COMP_FLAG_XMIT 0x1
+#define IPPP_COMP_FLAG_LINK 0x2
+
+struct isdn_ppp_comp_data {
+ int num;
+ unsigned char options[ISDN_PPP_COMP_MAX_OPTIONS];
+ int optlen;
+ int flags;
+};
+
+#ifdef __KERNEL__
+
+/*
+ * We need a way for the decompressor to influence the generation of CCP
+ * Reset-Requests in a variety of ways. The decompressor is already returning
+ * a lot of information (generated skb length, error conditions) so we use
+ * another parameter. This parameter is a pointer to a structure which is
+ * to be marked valid by the decompressor and only in this case is ever used.
+ * Furthermore, the only case where this data is used is when the decom-
+ * pressor returns DECOMP_ERROR.
+ *
+ * We use this same struct for the reset entry of the compressor to commu-
+ * nicate to its caller how to deal with sending of a Reset Ack. In this
+ * case, expra is not used, but other options still apply (supressing
+ * sending with rsend, appending arbitrary data, etc).
+ */
+
+#define IPPP_RESET_MAXDATABYTES 32
+
+struct isdn_ppp_resetparams {
+ unsigned char valid:1; /* rw Is this structure filled at all ? */
+ unsigned char rsend:1; /* rw Should we send one at all ? */
+ unsigned char idval:1; /* rw Is the id field valid ? */
+ unsigned char dtval:1; /* rw Is the data field valid ? */
+ unsigned char expra:1; /* rw Is an Ack expected for this Req ? */
+ unsigned char id; /* wo Send CCP ResetReq with this id */
+ unsigned short maxdlen; /* ro Max bytes to be stored in data field */
+ unsigned short dlen; /* rw Bytes stored in data field */
+ unsigned char *data; /* wo Data for ResetReq info field */
+};
+
+/*
+ * this is an 'old friend' from ppp-comp.h under a new name
+ * check the original include for more information
+ */
+struct isdn_ppp_compressor {
+ struct isdn_ppp_compressor *next, *prev;
+ int num; /* CCP compression protocol number */
+
+ void *(*alloc) (struct isdn_ppp_comp_data *);
+ void (*free) (void *state);
+ int (*init) (void *state, struct isdn_ppp_comp_data *,
+ int unit,int debug);
+
+ /* The reset entry needs to get more exact information about the
+ ResetReq or ResetAck it was called with. The parameters are
+ obvious. If reset is called without a Req or Ack frame which
+ could be handed into it, code MUST be set to 0. Using rsparm,
+ the reset entry can control if and how a ResetAck is returned. */
+
+ void (*reset) (void *state, unsigned char code, unsigned char id,
+ unsigned char *data, unsigned len,
+ struct isdn_ppp_resetparams *rsparm);
+
+ int (*compress) (void *state, struct sk_buff *in,
+ struct sk_buff *skb_out, int proto);
+
+ int (*decompress) (void *state,struct sk_buff *in,
+ struct sk_buff *skb_out,
+ struct isdn_ppp_resetparams *rsparm);
+
+ void (*incomp) (void *state, struct sk_buff *in,int proto);
+ void (*stat) (void *state, struct compstat *stats);
+};
+
+extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *);
+extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *);
+extern int isdn_ppp_dial_slave(char *);
+extern int isdn_ppp_hangup_slave(char *);
+
+struct ippp_bundle {
+ int mp_mrru; /* unused */
+ struct mpqueue *last; /* currently defined in isdn_net_dev */
+ int min; /* currently calculated 'on the fly' */
+ long next_num; /* we wanna see this seq.-number next */
+ struct sqqueue *sq;
+ int modify:1; /* set to 1 while modifying sqqueue */
+ int bundled:1; /* bundle active ? */
+};
+
+#define NUM_RCV_BUFFS 64
+
+struct sqqueue {
+ struct sqqueue *next;
+ long sqno_start;
+ long sqno_end;
+ struct sk_buff *skb;
+ long timer;
+};
+
+struct mpqueue {
+ struct mpqueue *next;
+ struct mpqueue *last;
+ long sqno;
+ struct sk_buff *skb;
+ int BEbyte;
+ unsigned long time;
+};
+
+struct ippp_buf_queue {
+ struct ippp_buf_queue *next;
+ struct ippp_buf_queue *last;
+ char *buf; /* NULL here indicates end of queue */
+ int len;
+};
+
+/* The data structure for one CCP reset transaction */
+enum ippp_ccp_reset_states {
+ CCPResetIdle,
+ CCPResetSentReq,
+ CCPResetRcvdReq,
+ CCPResetSentAck,
+ CCPResetRcvdAck
+};
+
+struct ippp_ccp_reset_state {
+ enum ippp_ccp_reset_states state; /* State of this transaction */
+ struct ippp_struct *is; /* Backlink to device stuff */
+ unsigned char id; /* Backlink id index */
+ unsigned char ta:1; /* The timer is active (flag) */
+ unsigned char expra:1; /* We expect a ResetAck at all */
+ int dlen; /* Databytes stored in data */
+ struct timer_list timer; /* For timeouts/retries */
+ /* This is a hack but seems sufficient for the moment. We do not want
+ to have this be yet another allocation for some bytes, it is more
+ memory management overhead than the whole mess is worth. */
+ unsigned char data[IPPP_RESET_MAXDATABYTES];
+};
+
+/* The data structure keeping track of the currently outstanding CCP Reset
+ transactions. */
+struct ippp_ccp_reset {
+ struct ippp_ccp_reset_state *rs[256]; /* One per possible id */
+ unsigned char lastid; /* Last id allocated by the engine */
+};
+
+struct ippp_struct {
+ struct ippp_struct *next_link;
+ int state;
+ struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
+ struct ippp_buf_queue *first; /* pointer to (current) first packet */
+ struct ippp_buf_queue *last; /* pointer to (current) last used packet in queue */
+#ifdef COMPAT_HAS_NEW_WAITQ
+ wait_queue_head_t wq;
+#else
+ struct wait_queue *wq;
+#endif
+ struct task_struct *tk;
+ unsigned int mpppcfg;
+ unsigned int pppcfg;
+ unsigned int mru;
+ unsigned int mpmru;
+ unsigned int mpmtu;
+ unsigned int maxcid;
+ struct isdn_net_local_s *lp;
+ int unit;
+ int minor;
+ long last_link_seqno;
+ long mp_seqno;
+ long range;
+#ifdef CONFIG_ISDN_PPP_VJ
+ unsigned char *cbuf;
+ struct slcompress *slcomp;
+#endif
+ unsigned long debug;
+ struct isdn_ppp_compressor *compressor,*decompressor;
+ struct isdn_ppp_compressor *link_compressor,*link_decompressor;
+ void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
+ struct ippp_ccp_reset *reset; /* Allocated on demand, may never be needed */
+ unsigned long compflags;
+};
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_ISDN_PPP_H */
diff --git a/pfinet/linux-src/include/linux/isdnif.h b/pfinet/linux-src/include/linux/isdnif.h
new file mode 100644
index 00000000..aeb177ab
--- /dev/null
+++ b/pfinet/linux-src/include/linux/isdnif.h
@@ -0,0 +1,622 @@
+/* $Id: isdnif.h,v 1.29 1999/07/31 13:00:02 armin Exp $
+ *
+ * Linux ISDN subsystem
+ *
+ * Definition of the interface between the subsystem and its low-level drivers.
+ *
+ * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: isdnif.h,v $
+ * Revision 1.29 1999/07/31 13:00:02 armin
+ * Added tty fax capabilities.
+ *
+ * Revision 1.28 1999/07/13 20:57:48 werner
+ * added callback ISDN_STAT_DISCH for limiting b-channel resources.
+ *
+ * Revision 1.27 1999/07/11 17:07:39 armin
+ * Added tty modem register S23.
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ *
+ * Revision 1.26 1999/07/01 08:35:44 keil
+ * compatibility to 2.3
+ *
+ * Revision 1.25 1998/06/17 19:51:55 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.24 1998/03/19 13:18:57 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 1.23 1998/02/20 17:36:52 fritz
+ * Added L2-protocols for V.110, changed FEATURE-Flag-constants.
+ *
+ * Revision 1.22 1998/01/31 22:14:12 keil
+ * changes for 2.1.82
+ *
+ * Revision 1.21 1997/10/09 21:28:13 fritz
+ * New HL<->LL interface:
+ * New BSENT callback with nr. of bytes included.
+ * Sending without ACK.
+ * New L1 error status (not yet in use).
+ * Cleaned up obsolete structures.
+ * Implemented Cisco-SLARP.
+ * Changed local net-interface data to be dynamically allocated.
+ * Removed old 2.0 compatibility stuff.
+ *
+ * Revision 1.20 1997/05/27 15:18:06 fritz
+ * Added changes for recent 2.1.x kernels:
+ * changed return type of isdn_close
+ * queue_task_* -> queue_task
+ * clear/set_bit -> test_and_... where apropriate.
+ * changed type of hard_header_cache parameter.
+ *
+ * Revision 1.19 1997/03/25 23:13:56 keil
+ * NI-1 US protocol
+ *
+ * Revision 1.18 1997/03/04 22:09:18 calle
+ * Change macros copy_from_user and copy_to_user in inline function.
+ * These are now correct replacements of the functions for 2.1.xx
+ *
+ * Revision 1.17 1997/02/10 21:12:53 fritz
+ * More setup-interface changes.
+ *
+ * Revision 1.16 1997/02/10 19:42:57 fritz
+ * New interface for reporting incoming calls.
+ *
+ * Revision 1.15 1997/02/09 00:18:42 keil
+ * leased line support
+ *
+ * Revision 1.14 1997/02/03 23:43:00 fritz
+ * Misc changes for Kernel 2.1.X compatibility.
+ *
+ * Revision 1.13 1996/11/13 02:39:59 fritz
+ * More compatibility changes.
+ *
+ * Revision 1.12 1996/11/06 17:38:48 keil
+ * more changes for 2.1.X
+ *
+ * Revision 1.11 1996/10/23 11:59:42 fritz
+ * More compatibility changes.
+ *
+ * Revision 1.10 1996/10/22 23:14:19 fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
+ * Revision 1.9 1996/06/06 21:24:24 fritz
+ * Started adding support for suspend/resume.
+ *
+ * Revision 1.8 1996/05/18 01:45:37 fritz
+ * More spelling corrections.
+ *
+ * Revision 1.7 1996/05/18 01:37:19 fritz
+ * Added spelling corrections and some minor changes
+ * to stay in sync with kernel.
+ *
+ * Revision 1.6 1996/05/17 03:59:28 fritz
+ * Marked rcvcallb and writebuf obsolete.
+ *
+ * Revision 1.5 1996/05/01 11:43:54 fritz
+ * Removed STANDALONE
+ *
+ * Revision 1.4 1996/05/01 11:38:40 fritz
+ * Added ISDN_FEATURE_L2_TRANS
+ *
+ * Revision 1.3 1996/04/29 22:57:54 fritz
+ * Added driverId and channel parameters to
+ * writecmd() and readstat().
+ * Added constant for voice-support.
+ *
+ * Revision 1.2 1996/04/20 17:02:40 fritz
+ * Changes to support skbuffs for Lowlevel-Drivers.
+ * Misc. typos
+ *
+ * Revision 1.1 1996/01/09 05:50:51 fritz
+ * Initial revision
+ *
+ */
+
+#ifndef isdnif_h
+#define isdnif_h
+
+#include <linux/isdn_compat.h>
+
+/*
+ * Values for general protocol-selection
+ */
+#define ISDN_PTYPE_UNKNOWN 0 /* Protocol undefined */
+#define ISDN_PTYPE_1TR6 1 /* german 1TR6-protocol */
+#define ISDN_PTYPE_EURO 2 /* EDSS1-protocol */
+#define ISDN_PTYPE_LEASED 3 /* for leased lines */
+#define ISDN_PTYPE_NI1 4 /* US NI-1 protocol */
+#define ISDN_PTYPE_MAX 7 /* Max. 8 Protocols */
+
+/*
+ * Values for Layer-2-protocol-selection
+ */
+#define ISDN_PROTO_L2_X75I 0 /* X75/LAPB with I-Frames */
+#define ISDN_PROTO_L2_X75UI 1 /* X75/LAPB with UI-Frames */
+#define ISDN_PROTO_L2_X75BUI 2 /* X75/LAPB with UI-Frames */
+#define ISDN_PROTO_L2_HDLC 3 /* HDLC */
+#define ISDN_PROTO_L2_TRANS 4 /* Transparent (Voice) */
+#define ISDN_PROTO_L2_X25DTE 5 /* X25/LAPB DTE mode */
+#define ISDN_PROTO_L2_X25DCE 6 /* X25/LAPB DCE mode */
+#define ISDN_PROTO_L2_V11096 7 /* V.110 bitrate adaption 9600 Baud */
+#define ISDN_PROTO_L2_V11019 8 /* V.110 bitrate adaption 19200 Baud */
+#define ISDN_PROTO_L2_V11038 9 /* V.110 bitrate adaption 38400 Baud */
+#define ISDN_PROTO_L2_MODEM 10 /* Analog Modem on Board */
+#define ISDN_PROTO_L2_FAX 11 /* Fax Group 2/3 */
+#define ISDN_PROTO_L2_MAX 15 /* Max. 16 Protocols */
+
+/*
+ * Values for Layer-3-protocol-selection
+ */
+#define ISDN_PROTO_L3_TRANS 0 /* Transparent */
+#define ISDN_PROTO_L3_TRANSDSP 1 /* Transparent with DSP */
+#define ISDN_PROTO_L3_FAX 2 /* Fax Group 2/3 */
+#define ISDN_PROTO_L3_MAX 7 /* Max. 8 Protocols */
+
+#ifdef __KERNEL__
+
+#include <linux/skbuff.h>
+
+/***************************************************************************/
+/* Extensions made by Werner Cornelius (werner@ikt.de) */
+/* */
+/* The proceed command holds a incoming call in a state to leave processes */
+/* enough time to check whether ist should be accepted. */
+/* The PROT_IO Command extends the interface to make protocol dependant */
+/* features available (call diversion, call waiting...). */
+/* */
+/* The PROT_IO Command is executed with the desired driver id and the arg */
+/* parameter coded as follows: */
+/* The lower 8 bits of arg contain the desired protocol from ISDN_PTYPE */
+/* definitions. The upper 24 bits represent the protocol specific cmd/stat.*/
+/* Any additional data is protocol and command specific. */
+/* This mechanism also applies to the statcallb callback STAT_PROT. */
+/* */
+/* This suggested extension permits an easy expansion of protocol specific */
+/* handling. Extensions may be added at any time without changing the HL */
+/* driver code and not getting conflicts without certifications. */
+/* The well known CAPI 2.0 interface handles such extensions in a similar */
+/* way. Perhaps a protocol specific module may be added and separately */
+/* loaded and linked to the basic isdn module for handling. */
+/***************************************************************************/
+
+/*****************/
+/* DSS1 commands */
+/*****************/
+#define DSS1_CMD_INVOKE ((0x00 << 8) | ISDN_PTYPE_EURO) /* invoke a supplementary service */
+#define DSS1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_EURO) /* abort a invoke cmd */
+
+/*******************************/
+/* DSS1 Status callback values */
+/*******************************/
+#define DSS1_STAT_INVOKE_RES ((0x80 << 8) | ISDN_PTYPE_EURO) /* Result for invocation */
+#define DSS1_STAT_INVOKE_ERR ((0x81 << 8) | ISDN_PTYPE_EURO) /* Error Return for invocation */
+#define DSS1_STAT_INVOKE_BRD ((0x82 << 8) | ISDN_PTYPE_EURO) /* Deliver invoke broadcast info */
+
+
+/*********************************************************************/
+/* structures for DSS1 commands and callback */
+/* */
+/* An action is invoked by sending a DSS1_CMD_INVOKE. The ll_id, proc*/
+/* timeout, datalen and data fields must be set before calling. */
+/* */
+/* The return value is a positive hl_id value also delivered in the */
+/* hl_id field. A value of zero signals no more left hl_id capacitys.*/
+/* A negative return value signals errors in LL. So if the return */
+/* value is <= 0 no action in LL will be taken -> request ignored */
+/* */
+/* The timeout field must be filled with a positive value specifying */
+/* the amount of time the INVOKED process waits for a reaction from */
+/* the network. */
+/* If a response (either error or result) is received during this */
+/* intervall, a reporting callback is initiated and the process will */
+/* be deleted, the hl identifier will be freed. */
+/* If no response is received during the specified intervall, a error*/
+/* callback is initiated with timeout set to -1 and a datalen set */
+/* to 0. */
+/* If timeout is set to a value <= 0 during INVOCATION the process is*/
+/* immediately deleted after sending the data. No callback occurs ! */
+/* */
+/* A currently waiting process may be aborted with INVOKE_ABORT. No */
+/* callback will occur when a process has been aborted. */
+/* */
+/* Broadcast invoke frames from the network are reported via the */
+/* STAT_INVOKE_BRD callback. The ll_id is set to 0, the other fields */
+/* are supplied by the network and not by the HL. */
+/*********************************************************************/
+typedef struct
+ { ulong ll_id; /* ID supplied by LL when executing */
+ /* a command and returned by HL for */
+ /* INVOKE_RES and INVOKE_ERR */
+ int hl_id; /* ID supplied by HL when called */
+ /* for executing a cmd and delivered */
+ /* for results and errors */
+ /* must be supplied by LL when aborting*/
+ int proc; /* invoke procedure used by CMD_INVOKE */
+ /* returned by callback and broadcast */
+ int timeout; /* timeout for INVOKE CMD in ms */
+ /* -1 in stat callback when timed out */
+ /* error value when error callback */
+ int datalen; /* length of cmd or stat data */
+ u_char *data;/* pointer to data delivered or send */
+ } dss1_cmd_stat;
+
+/*
+ * Commands from linklevel to lowlevel
+ *
+ */
+#define ISDN_CMD_IOCTL 0 /* Perform ioctl */
+#define ISDN_CMD_DIAL 1 /* Dial out */
+#define ISDN_CMD_ACCEPTD 2 /* Accept an incoming call on D-Chan. */
+#define ISDN_CMD_ACCEPTB 3 /* Request B-Channel connect. */
+#define ISDN_CMD_HANGUP 4 /* Hangup */
+#define ISDN_CMD_CLREAZ 5 /* Clear EAZ(s) of channel */
+#define ISDN_CMD_SETEAZ 6 /* Set EAZ(s) of channel */
+#define ISDN_CMD_GETEAZ 7 /* Get EAZ(s) of channel */
+#define ISDN_CMD_SETSIL 8 /* Set Service-Indicator-List of channel */
+#define ISDN_CMD_GETSIL 9 /* Get Service-Indicator-List of channel */
+#define ISDN_CMD_SETL2 10 /* Set B-Chan. Layer2-Parameter */
+#define ISDN_CMD_GETL2 11 /* Get B-Chan. Layer2-Parameter */
+#define ISDN_CMD_SETL3 12 /* Set B-Chan. Layer3-Parameter */
+#define ISDN_CMD_GETL3 13 /* Get B-Chan. Layer3-Parameter */
+#define ISDN_CMD_LOCK 14 /* Signal usage by upper levels */
+#define ISDN_CMD_UNLOCK 15 /* Release usage-lock */
+#define ISDN_CMD_SUSPEND 16 /* Suspend connection */
+#define ISDN_CMD_RESUME 17 /* Resume connection */
+#define ISDN_CMD_PROCEED 18 /* Proceed with call establishment */
+#define ISDN_CMD_ALERT 19 /* Alert after Proceeding */
+#define ISDN_CMD_REDIR 20 /* Redir a incoming call */
+#define ISDN_CMD_PROT_IO 21 /* Protocol specific commands */
+#define CAPI_PUT_MESSAGE 22 /* CAPI message send down or up */
+#define ISDN_CMD_FAXCMD 23 /* FAX commands to HL-driver */
+#define ISDN_CMD_AUDIO 24 /* DSP, DTMF, ... settings */
+
+/*
+ * Status-Values delivered from lowlevel to linklevel via
+ * statcallb().
+ *
+ */
+#define ISDN_STAT_STAVAIL 256 /* Raw status-data available */
+#define ISDN_STAT_ICALL 257 /* Incoming call detected */
+#define ISDN_STAT_RUN 258 /* Signal protocol-code is running */
+#define ISDN_STAT_STOP 259 /* Signal halt of protocol-code */
+#define ISDN_STAT_DCONN 260 /* Signal D-Channel connect */
+#define ISDN_STAT_BCONN 261 /* Signal B-Channel connect */
+#define ISDN_STAT_DHUP 262 /* Signal D-Channel disconnect */
+#define ISDN_STAT_BHUP 263 /* Signal B-Channel disconnect */
+#define ISDN_STAT_CINF 264 /* Charge-Info */
+#define ISDN_STAT_LOAD 265 /* Signal new lowlevel-driver is loaded */
+#define ISDN_STAT_UNLOAD 266 /* Signal unload of lowlevel-driver */
+#define ISDN_STAT_BSENT 267 /* Signal packet sent */
+#define ISDN_STAT_NODCH 268 /* Signal no D-Channel */
+#define ISDN_STAT_ADDCH 269 /* Add more Channels */
+#define ISDN_STAT_CAUSE 270 /* Cause-Message */
+#define ISDN_STAT_ICALLW 271 /* Incoming call without B-chan waiting */
+#define ISDN_STAT_REDIR 272 /* Redir result */
+#define ISDN_STAT_PROT 273 /* protocol IO specific callback */
+#define ISDN_STAT_DISPLAY 274 /* deliver a received display message */
+#define ISDN_STAT_L1ERR 275 /* Signal Layer-1 Error */
+#define ISDN_STAT_FAXIND 276 /* FAX indications from HL-driver */
+#define ISDN_STAT_AUDIO 277 /* DTMF, DSP indications */
+#define ISDN_STAT_DISCH 278 /* Disable/Enable channel usage */
+
+/*
+ * Audio commands
+ */
+#define ISDN_AUDIO_SETDD 0 /* Set DTMF detection */
+#define ISDN_AUDIO_DTMF 1 /* Rx/Tx DTMF */
+
+/*
+ * Values for errcode field
+ */
+#define ISDN_STAT_L1ERR_SEND 1
+#define ISDN_STAT_L1ERR_RECV 2
+
+/*
+ * Values for feature-field of interface-struct.
+ */
+/* Layer 2 */
+#define ISDN_FEATURE_L2_X75I (0x0001 << ISDN_PROTO_L2_X75I)
+#define ISDN_FEATURE_L2_X75UI (0x0001 << ISDN_PROTO_L2_X75UI)
+#define ISDN_FEATURE_L2_X75BUI (0x0001 << ISDN_PROTO_L2_X75BUI)
+#define ISDN_FEATURE_L2_HDLC (0x0001 << ISDN_PROTO_L2_HDLC)
+#define ISDN_FEATURE_L2_TRANS (0x0001 << ISDN_PROTO_L2_TRANS)
+#define ISDN_FEATURE_L2_X25DTE (0x0001 << ISDN_PROTO_L2_X25DTE)
+#define ISDN_FEATURE_L2_X25DCE (0x0001 << ISDN_PROTO_L2_X25DCE)
+#define ISDN_FEATURE_L2_V11096 (0x0001 << ISDN_PROTO_L2_V11096)
+#define ISDN_FEATURE_L2_V11019 (0x0001 << ISDN_PROTO_L2_V11019)
+#define ISDN_FEATURE_L2_V11038 (0x0001 << ISDN_PROTO_L2_V11038)
+#define ISDN_FEATURE_L2_MODEM (0x0001 << ISDN_PROTO_L2_MODEM)
+#define ISDN_FEATURE_L2_FAX (0x0001 << ISDN_PROTO_L2_FAX)
+
+#define ISDN_FEATURE_L2_MASK (0x0FFFF) /* Max. 16 protocols */
+#define ISDN_FEATURE_L2_SHIFT (0)
+
+/* Layer 3 */
+#define ISDN_FEATURE_L3_TRANS (0x10000 << ISDN_PROTO_L3_TRANS)
+#define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP)
+#define ISDN_FEATURE_L3_FAX (0x10000 << ISDN_PROTO_L3_FAX)
+
+#define ISDN_FEATURE_L3_MASK (0x0FF0000) /* Max. 8 Protocols */
+#define ISDN_FEATURE_L3_SHIFT (16)
+
+/* Signaling */
+#define ISDN_FEATURE_P_UNKNOWN (0x1000000 << ISDN_PTYPE_UNKNOWN)
+#define ISDN_FEATURE_P_1TR6 (0x1000000 << ISDN_PTYPE_1TR6)
+#define ISDN_FEATURE_P_EURO (0x1000000 << ISDN_PTYPE_EURO)
+#define ISDN_FEATURE_P_NI1 (0x1000000 << ISDN_PTYPE_NI1)
+
+#define ISDN_FEATURE_P_MASK (0x0FF000000) /* Max. 8 Protocols */
+#define ISDN_FEATURE_P_SHIFT (24)
+
+typedef struct setup_parm {
+ unsigned char phone[32]; /* Remote Phone-Number */
+ unsigned char eazmsn[32]; /* Local EAZ or MSN */
+ unsigned char si1; /* Service Indicator 1 */
+ unsigned char si2; /* Service Indicator 2 */
+ unsigned char plan; /* Numbering plan */
+ unsigned char screen; /* Screening info */
+} setup_parm;
+
+
+#ifdef CONFIG_ISDN_TTY_FAX
+/* T.30 Fax G3 */
+
+#define FAXIDLEN 21
+
+typedef struct T30_s {
+ /* session parameters */
+ __u8 resolution __attribute__ ((packed));
+ __u8 rate __attribute__ ((packed));
+ __u8 width __attribute__ ((packed));
+ __u8 length __attribute__ ((packed));
+ __u8 compression __attribute__ ((packed));
+ __u8 ecm __attribute__ ((packed));
+ __u8 binary __attribute__ ((packed));
+ __u8 scantime __attribute__ ((packed));
+ __u8 id[FAXIDLEN] __attribute__ ((packed));
+ /* additional parameters */
+ __u8 phase __attribute__ ((packed));
+ __u8 direction __attribute__ ((packed));
+ __u8 code __attribute__ ((packed));
+ __u8 badlin __attribute__ ((packed));
+ __u8 badmul __attribute__ ((packed));
+ __u8 bor __attribute__ ((packed));
+ __u8 fet __attribute__ ((packed));
+ __u8 pollid[FAXIDLEN] __attribute__ ((packed));
+ __u8 cq __attribute__ ((packed));
+ __u8 cr __attribute__ ((packed));
+ __u8 ctcrty __attribute__ ((packed));
+ __u8 minsp __attribute__ ((packed));
+ __u8 phcto __attribute__ ((packed));
+ __u8 rel __attribute__ ((packed));
+ __u8 nbc __attribute__ ((packed));
+ /* remote station parameters */
+ __u8 r_resolution __attribute__ ((packed));
+ __u8 r_rate __attribute__ ((packed));
+ __u8 r_width __attribute__ ((packed));
+ __u8 r_length __attribute__ ((packed));
+ __u8 r_compression __attribute__ ((packed));
+ __u8 r_ecm __attribute__ ((packed));
+ __u8 r_binary __attribute__ ((packed));
+ __u8 r_scantime __attribute__ ((packed));
+ __u8 r_id[FAXIDLEN] __attribute__ ((packed));
+ __u8 r_code __attribute__ ((packed));
+} T30_s;
+
+#define ISDN_TTY_FAX_CONN_IN 0
+#define ISDN_TTY_FAX_CONN_OUT 1
+
+#define ISDN_TTY_FAX_FCON 0
+#define ISDN_TTY_FAX_DIS 1
+#define ISDN_TTY_FAX_FTT 2
+#define ISDN_TTY_FAX_MCF 3
+#define ISDN_TTY_FAX_DCS 4
+#define ISDN_TTY_FAX_TRAIN_OK 5
+#define ISDN_TTY_FAX_EOP 6
+#define ISDN_TTY_FAX_EOM 7
+#define ISDN_TTY_FAX_MPS 8
+#define ISDN_TTY_FAX_DTC 9
+#define ISDN_TTY_FAX_RID 10
+#define ISDN_TTY_FAX_HNG 11
+#define ISDN_TTY_FAX_DT 12
+#define ISDN_TTY_FAX_FCON_I 13
+#define ISDN_TTY_FAX_DR 14
+#define ISDN_TTY_FAX_ET 15
+#define ISDN_TTY_FAX_CFR 16
+#define ISDN_TTY_FAX_PTS 17
+#define ISDN_TTY_FAX_SENT 18
+
+#define ISDN_FAX_PHASE_IDLE 0
+#define ISDN_FAX_PHASE_A 1
+#define ISDN_FAX_PHASE_B 2
+#define ISDN_FAX_PHASE_C 3
+#define ISDN_FAX_PHASE_D 4
+#define ISDN_FAX_PHASE_E 5
+
+#endif /* TTY_FAX */
+
+/* CAPI structs */
+
+/* this is compatible to the old union size */
+#define MAX_CAPI_PARA_LEN 50
+
+typedef struct {
+ /* Header */
+ __u16 Length;
+ __u16 ApplId;
+ __u8 Command;
+ __u8 Subcommand;
+ __u16 Messagenumber;
+
+ /* Parameter */
+ union {
+ __u32 Controller;
+ __u32 PLCI;
+ __u32 NCCI;
+ } adr;
+ __u8 para[MAX_CAPI_PARA_LEN];
+} capi_msg;
+
+/*
+ * Structure for exchanging above infos
+ *
+ */
+typedef struct {
+ int driver; /* Lowlevel-Driver-ID */
+ int command; /* Command or Status (see above) */
+ ulong arg; /* Additional Data */
+ union {
+ ulong errcode; /* Type of error with STAT_L1ERR */
+ int length; /* Amount of bytes sent with STAT_BSENT */
+ u_char num[50];/* Additional Data */
+ setup_parm setup;/* For SETUP msg */
+ capi_msg cmsg; /* For CAPI like messages */
+ char display[85];/* display message data */
+ dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result */
+#ifdef CONFIG_ISDN_TTY_FAX
+ T30_s *fax; /* Pointer to ttys fax struct */
+#endif
+ } parm;
+} isdn_ctrl;
+
+/*
+ * The interface-struct itself (initialized at load-time of lowlevel-driver)
+ *
+ * See Documentation/isdn/INTERFACE for a description, how the communication
+ * between the ISDN subsystem and its drivers is done.
+ *
+ */
+typedef struct {
+ /* Number of channels supported by this driver
+ */
+ int channels;
+
+ /*
+ * Maximum Size of transmit/receive-buffer this driver supports.
+ */
+ int maxbufsize;
+
+ /* Feature-Flags for this driver.
+ * See defines ISDN_FEATURE_... for Values
+ */
+ unsigned long features;
+
+ /*
+ * Needed for calculating
+ * dev->hard_header_len = linklayer header + hl_hdrlen;
+ * Drivers, not supporting sk_buff's should set this to 0.
+ */
+ unsigned short hl_hdrlen;
+
+ /*
+ * Receive-Callback using sk_buff's
+ * Parameters:
+ * int Driver-ID
+ * int local channel-number (0 ...)
+ * struct sk_buff *skb received Data
+ */
+ void (*rcvcallb_skb)(int, int, struct sk_buff *);
+
+ /* Status-Callback
+ * Parameters:
+ * isdn_ctrl*
+ * driver = Driver ID.
+ * command = One of above ISDN_STAT_... constants.
+ * arg = depending on status-type.
+ * num = depending on status-type.
+ */
+ int (*statcallb)(isdn_ctrl*);
+
+ /* Send command
+ * Parameters:
+ * isdn_ctrl*
+ * driver = Driver ID.
+ * command = One of above ISDN_CMD_... constants.
+ * arg = depending on command.
+ * num = depending on command.
+ */
+ int (*command)(isdn_ctrl*);
+
+ /*
+ * Send data using sk_buff's
+ * Parameters:
+ * int driverId
+ * int local channel-number (0...)
+ * int Flag: Need ACK for this packet.
+ * struct sk_buff *skb Data to send
+ */
+ int (*writebuf_skb) (int, int, int, struct sk_buff *);
+
+ /* Send raw D-Channel-Commands
+ * Parameters:
+ * u_char pointer data
+ * int length of data
+ * int Flag: 0 = Call form Kernel-Space (use memcpy,
+ * no schedule allowed)
+ * 1 = Data is in User-Space (use memcpy_fromfs,
+ * may schedule)
+ * int driverId
+ * int local channel-number (0 ...)
+ */
+ int (*writecmd)(const u_char*, int, int, int, int);
+
+ /* Read raw Status replies
+ * u_char pointer data (volatile)
+ * int length of buffer
+ * int Flag: 0 = Call form Kernel-Space (use memcpy,
+ * no schedule allowed)
+ * 1 = Data is in User-Space (use memcpy_fromfs,
+ * may schedule)
+ * int driverId
+ * int local channel-number (0 ...)
+ */
+ int (*readstat)(u_char*, int, int, int, int);
+
+ char id[20];
+} isdn_if;
+
+/*
+ * Function which must be called by lowlevel-driver at loadtime with
+ * the following fields of above struct set:
+ *
+ * channels Number of channels that will be supported.
+ * hl_hdrlen Space to preserve in sk_buff's when sending. Drivers, not
+ * supporting sk_buff's should set this to 0.
+ * command Address of Command-Handler.
+ * features Bitwise coded Features of this driver. (use ISDN_FEATURE_...)
+ * writebuf_skb Address of Skbuff-Send-Handler.
+ * writecmd " " D-Channel " which accepts raw D-Ch-Commands.
+ * readstat " " D-Channel " which delivers raw Status-Data.
+ *
+ * The linklevel-driver fills the following fields:
+ *
+ * channels Driver-ID assigned to this driver. (Must be used on all
+ * subsequent callbacks.
+ * rcvcallb_skb Address of handler for received Skbuff's.
+ * statcallb " " " for status-changes.
+ *
+ */
+extern int register_isdn(isdn_if*);
+#include <asm/uaccess.h>
+
+#endif /* __KERNEL__ */
+#endif /* isdnif_h */
diff --git a/pfinet/linux-src/include/linux/isicom.h b/pfinet/linux-src/include/linux/isicom.h
new file mode 100644
index 00000000..58372fdc
--- /dev/null
+++ b/pfinet/linux-src/include/linux/isicom.h
@@ -0,0 +1,310 @@
+#ifndef _LINUX_ISICOM_H
+#define _LINUX_ISICOM_H
+
+/*#define ISICOM_DEBUG*/
+/*#define ISICOM_DEBUG_DTR_RTS*/
+
+
+/*
+ * Firmware Loader definitions ...
+ */
+
+#define __MultiTech ('M'<<8)
+#define MIOCTL_LOAD_FIRMWARE (__MultiTech | 0x01)
+#define MIOCTL_READ_FIRMWARE (__MultiTech | 0x02)
+#define MIOCTL_XFER_CTRL (__MultiTech | 0x03)
+#define MIOCTL_RESET_CARD (__MultiTech | 0x04)
+
+#define DATA_SIZE 16
+
+typedef struct {
+ unsigned short exec_segment;
+ unsigned short exec_addr;
+} exec_record;
+
+typedef struct {
+ int board; /* Board to load */
+ unsigned short addr;
+ unsigned short count;
+} bin_header;
+
+typedef struct {
+ int board; /* Board to load */
+ unsigned short addr;
+ unsigned short count;
+ unsigned short segment;
+ unsigned char bin_data[DATA_SIZE];
+} bin_frame;
+
+#ifdef __KERNEL__
+
+#define YES 1
+#define NO 0
+
+#define ISILOAD_MISC_MINOR 155 /* /dev/isctl */
+#define ISILOAD_NAME "ISILoad"
+
+/*
+ * ISICOM Driver definitions ...
+ *
+ */
+
+#define ISICOM_NAME "ISICom"
+
+/*
+ * PCI definitions
+ */
+
+ #define DEVID_COUNT 9
+ #define VENDOR_ID 0x10b5
+
+/*
+ * These are now officially allocated numbers
+ */
+
+#define ISICOM_NMAJOR 112 /* normal */
+#define ISICOM_CMAJOR 113 /* callout */
+#define ISICOM_MAGIC (('M' << 8) | 'T')
+
+#define WAKEUP_CHARS 256 /* hard coded for now */
+#define TX_SIZE 254
+
+#define BOARD_COUNT 4
+#define PORT_COUNT (BOARD_COUNT*16)
+
+#define SERIAL_TYPE_NORMAL 1
+#define SERIAL_TYPE_CALLOUT 2
+
+/* character sizes */
+
+#define ISICOM_CS5 0x0000
+#define ISICOM_CS6 0x0001
+#define ISICOM_CS7 0x0002
+#define ISICOM_CS8 0x0003
+
+/* stop bits */
+
+#define ISICOM_1SB 0x0000
+#define ISICOM_2SB 0x0004
+
+/* parity */
+
+#define ISICOM_NOPAR 0x0000
+#define ISICOM_ODPAR 0x0008
+#define ISICOM_EVPAR 0x0018
+
+/* flow control */
+
+#define ISICOM_CTSRTS 0x03
+#define ISICOM_INITIATE_XONXOFF 0x04
+#define ISICOM_RESPOND_XONXOFF 0x08
+
+#define InterruptTheCard(base) (outw(0,(base)+0xc))
+#define ClearInterrupt(base) (inw((base)+0x0a))
+
+#define BOARD(line) (((line) >> 4) & 0x3)
+#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
+
+ /* isi kill queue bitmap */
+
+#define ISICOM_KILLTX 0x01
+#define ISICOM_KILLRX 0x02
+
+ /* isi_board status bitmap */
+
+#define FIRMWARE_LOADED 0x0001
+#define BOARD_ACTIVE 0x0002
+
+ /* isi_port status bitmap */
+
+#define ISI_CTS 0x1000
+#define ISI_DSR 0x2000
+#define ISI_RI 0x4000
+#define ISI_DCD 0x8000
+#define ISI_DTR 0x0100
+#define ISI_RTS 0x0200
+
+
+#define ISI_TXOK 0x0001
+
+struct isi_board {
+ unsigned short base;
+ unsigned char irq;
+ unsigned char port_count;
+ unsigned short status;
+ unsigned short port_status; /* each bit represents a single port */
+ unsigned short shift_count;
+ struct isi_port * ports;
+ signed char count;
+ unsigned char isa;
+};
+
+struct isi_port {
+ unsigned short magic;
+ unsigned int flags;
+ int count;
+ int blocked_open;
+ int close_delay;
+ unsigned short channel;
+ unsigned short status;
+ unsigned short closing_wait;
+ long session;
+ long pgrp;
+ struct isi_board * card;
+ struct tty_struct * tty;
+ struct wait_queue * close_wait;
+ struct wait_queue * open_wait;
+ struct tq_struct hangup_tq;
+ struct tq_struct bh_tqueue;
+ unsigned char * xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ struct termios normal_termios;
+ struct termios callout_termios;
+};
+
+
+/*
+ * ISI Card specific ops ...
+ */
+
+extern inline void raise_dtr(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ unsigned short base = card->base;
+ unsigned char channel = port->channel;
+ short wait=400;
+ while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+ if (wait <= 0) {
+ printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr.\n");
+ return;
+ }
+#ifdef ISICOM_DEBUG_DTR_RTS
+ printk(KERN_DEBUG "ISICOM: raise_dtr.\n");
+#endif
+ outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x0504, base);
+ InterruptTheCard(base);
+ port->status |= ISI_DTR;
+}
+
+extern inline void drop_dtr(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ unsigned short base = card->base;
+ unsigned char channel = port->channel;
+ short wait=400;
+ while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+ if (wait <= 0) {
+ printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr.\n");
+ return;
+ }
+#ifdef ISICOM_DEBUG_DTR_RTS
+ printk(KERN_DEBUG "ISICOM: drop_dtr.\n");
+#endif
+ outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x0404, base);
+ InterruptTheCard(base);
+ port->status &= ~ISI_DTR;
+}
+extern inline void raise_rts(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ unsigned short base = card->base;
+ unsigned char channel = port->channel;
+ short wait=400;
+ while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+ if (wait <= 0) {
+ printk(KERN_WARNING "ISICOM: Card found busy in raise_rts.\n");
+ return;
+ }
+#ifdef ISICOM_DEBUG_DTR_RTS
+ printk(KERN_DEBUG "ISICOM: raise_rts.\n");
+#endif
+ outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x0a04, base);
+ InterruptTheCard(base);
+ port->status |= ISI_RTS;
+}
+extern inline void drop_rts(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ unsigned short base = card->base;
+ unsigned char channel = port->channel;
+ short wait=400;
+ while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+ if (wait <= 0) {
+ printk(KERN_WARNING "ISICOM: Card found busy in drop_rts.\n");
+ return;
+ }
+#ifdef ISICOM_DEBUG_DTR_RTS
+ printk(KERN_DEBUG "ISICOM: drop_rts.\n");
+#endif
+ outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x0804, base);
+ InterruptTheCard(base);
+ port->status &= ~ISI_RTS;
+}
+extern inline void raise_dtr_rts(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ unsigned short base = card->base;
+ unsigned char channel = port->channel;
+ short wait=400;
+ while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+ if (wait <= 0) {
+ printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr_rts.\n");
+ return;
+ }
+#ifdef ISICOM_DEBUG_DTR_RTS
+ printk(KERN_DEBUG "ISICOM: raise_dtr_rts.\n");
+#endif
+ outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x0f04, base);
+ InterruptTheCard(base);
+ port->status |= (ISI_DTR | ISI_RTS);
+}
+extern inline void drop_dtr_rts(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ unsigned short base = card->base;
+ unsigned char channel = port->channel;
+ short wait=400;
+ while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+ if (wait <= 0) {
+ printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr_rts.\n");
+ return;
+ }
+#ifdef ISICOM_DEBUG_DTR_RTS
+ printk(KERN_DEBUG "ISICOM: drop_dtr_rts.\n");
+#endif
+ outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x0c04, base);
+ InterruptTheCard(base);
+ port->status &= ~(ISI_RTS | ISI_DTR);
+}
+
+extern inline void kill_queue(struct isi_port * port, short queue)
+{
+ struct isi_board * card = port->card;
+ unsigned short base = card->base;
+ unsigned char channel = port->channel;
+ short wait=400;
+ while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+ if (wait <= 0) {
+ printk(KERN_WARNING "ISICOM: Card found busy in kill_queue.\n");
+ return;
+ }
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: kill_queue 0x%x.\n", queue);
+#endif
+ outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw((queue << 8) | 0x06, base);
+ InterruptTheCard(base);
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* ISICOM_H */
+
diff --git a/pfinet/linux-src/include/linux/iso_fs.h b/pfinet/linux-src/include/linux/iso_fs.h
new file mode 100644
index 00000000..0fcb4b82
--- /dev/null
+++ b/pfinet/linux-src/include/linux/iso_fs.h
@@ -0,0 +1,230 @@
+
+#ifndef _ISOFS_FS_H
+#define _ISOFS_FS_H
+
+#include <linux/types.h>
+/*
+ * The isofs filesystem constants/structures
+ */
+
+/* This part borrowed from the bsd386 isofs */
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_volume_descriptor {
+ char type[ISODCL(1,1)]; /* 711 */
+ char id[ISODCL(2,6)];
+ char version[ISODCL(7,7)];
+ char data[ISODCL(8,2048)];
+};
+
+/* volume descriptor types */
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_SUPPLEMENTARY 2
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+struct iso_primary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char unused1 [ISODCL ( 8, 8)];
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char unused3 [ISODCL ( 89, 120)];
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+/* Almost the same as the primary descriptor but two fields are specified */
+struct iso_supplementary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char flags [ISODCL ( 8, 8)]; /* 853 */
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char escape [ISODCL ( 89, 120)]; /* 856 */
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+
+#define HS_STANDARD_ID "CDROM"
+
+struct hs_volume_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char data[ISODCL(16,2048)];
+};
+
+
+struct hs_primary_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char unused1 [ISODCL ( 16, 16)]; /* 711 */
+ char system_id [ISODCL ( 17, 48)]; /* achars */
+ char volume_id [ISODCL ( 49, 80)]; /* dchars */
+ char unused2 [ISODCL ( 81, 88)]; /* 733 */
+ char volume_space_size [ISODCL ( 89, 96)]; /* 733 */
+ char unused3 [ISODCL ( 97, 128)]; /* 733 */
+ char volume_set_size [ISODCL (129, 132)]; /* 723 */
+ char volume_sequence_number [ISODCL (133, 136)]; /* 723 */
+ char logical_block_size [ISODCL (137, 140)]; /* 723 */
+ char path_table_size [ISODCL (141, 148)]; /* 733 */
+ char type_l_path_table [ISODCL (149, 152)]; /* 731 */
+ char unused4 [ISODCL (153, 180)]; /* 733 */
+ char root_directory_record [ISODCL (181, 214)]; /* 9.1 */
+};
+
+/* We use this to help us look up the parent inode numbers. */
+
+struct iso_path_table{
+ unsigned char name_len[2]; /* 721 */
+ char extent[4]; /* 731 */
+ char parent[2]; /* 721 */
+ char name[0];
+};
+
+/* high sierra is identical to iso, except that the date is only 6 bytes, and
+ there is an extra reserved byte after the flags */
+
+struct iso_directory_record {
+ char length [ISODCL (1, 1)]; /* 711 */
+ char ext_attr_length [ISODCL (2, 2)]; /* 711 */
+ char extent [ISODCL (3, 10)]; /* 733 */
+ char size [ISODCL (11, 18)]; /* 733 */
+ char date [ISODCL (19, 25)]; /* 7 by 711 */
+ char flags [ISODCL (26, 26)];
+ char file_unit_size [ISODCL (27, 27)]; /* 711 */
+ char interleave [ISODCL (28, 28)]; /* 711 */
+ char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
+ unsigned char name_len [ISODCL (33, 33)]; /* 711 */
+ char name [0];
+};
+
+#define ISOFS_BLOCK_BITS 11
+#define ISOFS_BLOCK_SIZE 2048
+
+#define ISOFS_BUFFER_SIZE(INODE) ((INODE)->i_sb->s_blocksize)
+#define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits)
+#define ISOFS_ZONE_BITS(INODE) ((INODE)->i_sb->u.isofs_sb.s_log_zone_size)
+
+#define ISOFS_SUPER_MAGIC 0x9660
+
+#ifdef __KERNEL__
+extern int isonum_711(char *);
+extern int isonum_712(char *);
+extern int isonum_721(char *);
+extern int isonum_722(char *);
+extern int isonum_723(char *);
+extern int isonum_731(char *);
+extern int isonum_732(char *);
+extern int isonum_733(char *);
+extern int iso_date(char *, int);
+
+extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
+extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
+
+extern char * get_rock_ridge_symlink(struct inode *);
+extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *);
+
+int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *);
+int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
+
+/* The stuff that follows may be totally unneeded. I have not checked to see
+ which prototypes we are still using. */
+
+extern int isofs_open(struct inode * inode, struct file * filp);
+extern void isofs_release(struct inode * inode, struct file * filp);
+extern struct dentry *isofs_lookup(struct inode * dir, struct dentry *);
+extern unsigned long isofs_count_free_inodes(struct super_block *sb);
+extern int isofs_new_block(int dev);
+extern int isofs_free_block(int dev, int block);
+extern int isofs_bmap(struct inode *,int);
+
+extern void isofs_put_super(struct super_block *);
+extern struct super_block *isofs_read_super(struct super_block *,void *,int);
+extern int init_iso9660_fs(void);
+extern void isofs_read_inode(struct inode *);
+extern void isofs_put_inode(struct inode *);
+extern int isofs_statfs(struct super_block *, struct statfs *, int);
+
+extern int isofs_lseek(struct inode *, struct file *, off_t, int);
+extern int isofs_read(struct inode *, struct file *, char *, int);
+extern int isofs_lookup_grandparent(struct inode *, int);
+
+extern struct inode_operations isofs_file_inode_operations;
+extern struct inode_operations isofs_dir_inode_operations;
+extern struct inode_operations isofs_symlink_inode_operations;
+extern struct inode_operations isofs_chrdev_inode_operations;
+extern struct inode_operations isofs_blkdev_inode_operations;
+extern struct inode_operations isofs_fifo_inode_operations;
+
+/* The following macros are used to check for memory leaks. */
+#ifdef LEAK_CHECK
+#define free_s leak_check_free_s
+#define malloc leak_check_malloc
+#define bread leak_check_bread
+#define brelse leak_check_brelse
+extern void * leak_check_malloc(unsigned int size);
+extern void leak_check_free_s(void * obj, int size);
+extern struct buffer_head * leak_check_bread(int dev, int block, int size);
+extern void leak_check_brelse(struct buffer_head * bh);
+#endif /* LEAK_CHECK */
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/iso_fs_i.h b/pfinet/linux-src/include/linux/iso_fs_i.h
new file mode 100644
index 00000000..02f17e07
--- /dev/null
+++ b/pfinet/linux-src/include/linux/iso_fs_i.h
@@ -0,0 +1,14 @@
+#ifndef _ISO_FS_I
+#define _ISO_FS_I
+
+/*
+ * iso fs inode data in memory
+ */
+struct iso_inode_info {
+ unsigned int i_first_extent;
+ unsigned char i_file_format;
+ unsigned long i_next_section_ino;
+ off_t i_section_size;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/iso_fs_sb.h b/pfinet/linux-src/include/linux/iso_fs_sb.h
new file mode 100644
index 00000000..7bb55a50
--- /dev/null
+++ b/pfinet/linux-src/include/linux/iso_fs_sb.h
@@ -0,0 +1,31 @@
+#ifndef _ISOFS_FS_SB
+#define _ISOFS_FS_SB
+
+/*
+ * iso9660 super-block data in memory
+ */
+struct isofs_sb_info {
+ unsigned long s_ninodes;
+ unsigned long s_nzones;
+ unsigned long s_firstdatazone;
+ unsigned long s_log_zone_size;
+ unsigned long s_max_size;
+
+ unsigned char s_high_sierra; /* A simple flag */
+ unsigned char s_mapping;
+ unsigned char s_rock;
+ unsigned char s_joliet_level;
+ unsigned char s_utf8;
+ unsigned char s_cruft; /* Broken disks with high
+ byte of length containing
+ junk */
+ unsigned char s_unhide;
+ unsigned char s_nosuid;
+ unsigned char s_nodev;
+ mode_t s_mode;
+ gid_t s_gid;
+ uid_t s_uid;
+ struct nls_table *s_nls_iocharset; /* Native language support table */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/istallion.h b/pfinet/linux-src/include/linux/istallion.h
new file mode 100644
index 00000000..269ef88b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/istallion.h
@@ -0,0 +1,134 @@
+/*****************************************************************************/
+
+/*
+ * istallion.h -- stallion intelligent multiport serial driver.
+ *
+ * Copyright (C) 1996-1998 Stallion Technologies (support@stallion.oz.au).
+ * Copyright (C) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*****************************************************************************/
+#ifndef _ISTALLION_H
+#define _ISTALLION_H
+/*****************************************************************************/
+
+/*
+ * Define important driver constants here.
+ */
+#define STL_MAXBRDS 4
+#define STL_MAXPANELS 4
+#define STL_MAXPORTS 64
+#define STL_MAXCHANS (STL_MAXPORTS + 1)
+#define STL_MAXDEVS (STL_MAXBRDS * STL_MAXPORTS)
+
+
+/*
+ * Define a set of structures to hold all the board/panel/port info
+ * for our ports. These will be dynamically allocated as required at
+ * driver initialization time.
+ */
+
+/*
+ * Port and board structures to hold status info about each object.
+ * The board structure contains pointers to structures for each port
+ * connected to it. Panels are not distinguished here, since
+ * communication with the slave board will always be on a per port
+ * basis.
+ */
+typedef struct {
+ unsigned long magic;
+ int portnr;
+ int panelnr;
+ int brdnr;
+ unsigned long state;
+ int devnr;
+ int flags;
+ int baud_base;
+ int custom_divisor;
+ int close_delay;
+ int closing_wait;
+ int refcount;
+ int openwaitcnt;
+ int rc;
+ int argsize;
+ void *argp;
+ long session;
+ long pgrp;
+ unsigned int rxmarkmsk;
+ struct tty_struct *tty;
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+ struct wait_queue *raw_wait;
+ struct tq_struct tqhangup;
+ struct termios normaltermios;
+ struct termios callouttermios;
+ asysigs_t asig;
+ unsigned long addr;
+ unsigned long rxoffset;
+ unsigned long txoffset;
+ unsigned long sigs;
+ unsigned long pflag;
+ unsigned int rxsize;
+ unsigned int txsize;
+ unsigned char reqbit;
+ unsigned char portidx;
+ unsigned char portbit;
+} stliport_t;
+
+/*
+ * Use a structure of function pointers to do board level operations.
+ * These include, enable/disable, paging shared memory, interrupting, etc.
+ */
+typedef struct stlibrd {
+ unsigned long magic;
+ int brdnr;
+ int brdtype;
+ int state;
+ int nrpanels;
+ int nrports;
+ int nrdevs;
+ unsigned int iobase;
+ int iosize;
+ unsigned long memaddr;
+ void *membase;
+ int memsize;
+ int pagesize;
+ int hostoffset;
+ int slaveoffset;
+ int bitsize;
+ int enabval;
+ int panels[STL_MAXPANELS];
+ int panelids[STL_MAXPANELS];
+ void (*init)(struct stlibrd *brdp);
+ void (*enable)(struct stlibrd *brdp);
+ void (*reenable)(struct stlibrd *brdp);
+ void (*disable)(struct stlibrd *brdp);
+ char *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line);
+ void (*intr)(struct stlibrd *brdp);
+ void (*reset)(struct stlibrd *brdp);
+ stliport_t *ports[STL_MAXPORTS];
+} stlibrd_t;
+
+
+/*
+ * Define MAGIC numbers used for above structures.
+ */
+#define STLI_PORTMAGIC 0xe671c7a1
+#define STLI_BOARDMAGIC 0x4bc6c825
+
+/*****************************************************************************/
+#endif
diff --git a/pfinet/linux-src/include/linux/joystick.h b/pfinet/linux-src/include/linux/joystick.h
new file mode 100644
index 00000000..c1794ca2
--- /dev/null
+++ b/pfinet/linux-src/include/linux/joystick.h
@@ -0,0 +1,299 @@
+#ifndef _LINUX_JOYSTICK_H
+#define _LINUX_JOYSTICK_H
+
+/*
+ * /usr/include/linux/joystick.h Version 1.2
+ *
+ * Copyright (C) 1996-1998 Vojtech Pavlik
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <asm/types.h>
+#include <linux/module.h>
+
+/*
+ * Version
+ */
+
+#define JS_VERSION 0x01020d
+
+/*
+ * Types and constants for reading from /dev/js
+ */
+
+#define JS_EVENT_BUTTON 0x01 /* button pressed/released */
+#define JS_EVENT_AXIS 0x02 /* joystick moved */
+#define JS_EVENT_INIT 0x80 /* initial state of device */
+
+struct js_event {
+ __u32 time; /* event timestamp in miliseconds */
+ __s16 value; /* value */
+ __u8 type; /* event type */
+ __u8 number; /* axis/button number */
+};
+
+/*
+ * IOCTL commands for joystick driver
+ */
+
+#define JSIOCGVERSION _IOR('j', 0x01, __u32) /* get driver version */
+
+#define JSIOCGAXES _IOR('j', 0x11, __u8) /* get number of axes */
+#define JSIOCGBUTTONS _IOR('j', 0x12, __u8) /* get number of buttons */
+#define JSIOCGNAME(len) _IOC(_IOC_READ, 'j', 0x13, len) /* get identifier string */
+
+#define JSIOCSCORR _IOW('j', 0x21, struct js_corr) /* set correction values */
+#define JSIOCGCORR _IOR('j', 0x22, struct js_corr) /* get correction values */
+
+/*
+ * Types and constants for get/set correction
+ */
+
+#define JS_CORR_NONE 0x00 /* returns raw values */
+#define JS_CORR_BROKEN 0x01 /* broken line */
+
+struct js_corr {
+ __s32 coef[8];
+ __s16 prec;
+ __u16 type;
+};
+
+/*
+ * v0.x compatibility definitions
+ */
+
+#define JS_RETURN sizeof(struct JS_DATA_TYPE)
+#define JS_TRUE 1
+#define JS_FALSE 0
+#define JS_X_0 0x01
+#define JS_Y_0 0x02
+#define JS_X_1 0x04
+#define JS_Y_1 0x08
+#define JS_MAX 2
+
+#define JS_DEF_TIMEOUT 0x1300
+#define JS_DEF_CORR 0
+#define JS_DEF_TIMELIMIT 10L
+
+#define JS_SET_CAL 1
+#define JS_GET_CAL 2
+#define JS_SET_TIMEOUT 3
+#define JS_GET_TIMEOUT 4
+#define JS_SET_TIMELIMIT 5
+#define JS_GET_TIMELIMIT 6
+#define JS_GET_ALL 7
+#define JS_SET_ALL 8
+
+struct JS_DATA_TYPE {
+ int buttons;
+ int x;
+ int y;
+};
+
+struct JS_DATA_SAVE_TYPE {
+ int JS_TIMEOUT;
+ int BUSY;
+ long JS_EXPIRETIME;
+ long JS_TIMELIMIT;
+ struct JS_DATA_TYPE JS_SAVE;
+ struct JS_DATA_TYPE JS_CORR;
+};
+
+/*
+ * Internal definitions
+ */
+
+#ifdef __KERNEL__
+
+#define JS_BUFF_SIZE 64 /* output buffer size */
+
+#include <linux/version.h>
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+#ifndef LINUX_VERSION_CODE
+#error "You need to use at least 2.0 Linux kernel."
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,0,0)
+#error "You need to use at least 2.0 Linux kernel."
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#define JS_HAS_RDTSC (current_cpu_data.x86_capability & 0x10)
+#include <linux/init.h>
+#else
+#ifdef MODULE
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,35)
+#define JS_HAS_RDTSC (x86_capability & 0x10)
+#else
+#define JS_HAS_RDTSC 0
+#endif
+#else
+#define JS_HAS_RDTSC (x86_capability & 0x10)
+#endif
+#define __initdata
+#define __init
+#define __cli cli
+#define __save_flags(flags) save_flags(flags)
+#define __restore_flags(flags) restore_flags(flags)
+#define spin_lock_irqsave(x, flags) do { save_flags(flags); cli(); } while (0)
+#define spin_unlock_irqrestore(x, flags) restore_flags(flags)
+#define spin_lock_init(x) do { } while (0)
+typedef struct { int something; } spinlock_t;
+#define SPIN_LOCK_UNLOCKED { 0 }
+#define MODULE_AUTHOR(x)
+#define MODULE_PARM(x,y)
+#define MODULE_SUPPORTED_DEVICE(x)
+#define signal_pending(x) (((x)->signal) & ~((x)->blocked))
+#endif
+
+/*
+ * Parport stuff
+ */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#define USE_PARPORT
+#endif
+
+#ifdef USE_PARPORT
+#include <linux/parport.h>
+#define JS_PAR_DATA_IN(y) parport_read_data(y->port)
+#define JS_PAR_DATA_OUT(x,y) parport_write_data(y->port, x)
+#define JS_PAR_STATUS(y) parport_read_status(y->port)
+#define JS_PAR_CTRL_IN(y) parport_read_control(y->port)
+#define JS_PAR_CTRL_OUT(x,y) parport_write_control(y->port, x)
+#define JS_PAR_ECTRL_OUT(x,y) parport_write_econtrol(y->port, x)
+#else
+#define JS_PAR_DATA_IN(y) inb(y)
+#define JS_PAR_DATA_OUT(x,y) outb(x,y)
+#define JS_PAR_STATUS(y) inb(y+1)
+#define JS_PAR_CTRL_IN(y) inb(y+2)
+#define JS_PAR_CTRL_OUT(x,y) outb(x,y+2)
+#define JS_PAR_ECTRL_OUT(x,y) outb(x,y+0x402)
+#endif
+
+#define JS_PAR_STATUS_INVERT (0x80)
+#define JS_PAR_CTRL_INVERT (0x04)
+
+/*
+ * Internal types
+ */
+
+struct js_dev;
+
+typedef int (*js_read_func)(void *info, int **axes, int **buttons);
+typedef unsigned int (*js_time_func)(void);
+typedef int (*js_delta_func)(unsigned int x, unsigned int y);
+typedef int (*js_ops_func)(struct js_dev *dev);
+
+struct js_data {
+ int *axes;
+ int *buttons;
+};
+
+struct js_dev {
+ struct js_dev *next;
+ struct js_list *list;
+ struct js_port *port;
+ struct wait_queue *wait;
+ struct js_data cur;
+ struct js_data new;
+ struct js_corr *corr;
+ struct js_event buff[JS_BUFF_SIZE];
+ js_ops_func open;
+ js_ops_func close;
+ int ahead;
+ int bhead;
+ int tail;
+ int num_axes;
+ int num_buttons;
+ char *name;
+};
+
+struct js_list {
+ struct js_list *next;
+ struct js_dev *dev;
+ int tail;
+ int startup;
+};
+
+struct js_port {
+ struct js_port *next;
+ struct js_port *prev;
+ js_read_func read;
+ struct js_dev **devs;
+ int **axes;
+ int **buttons;
+ struct js_corr **corr;
+ void *info;
+ int ndevs;
+};
+
+/*
+ * Sub-module interface
+ */
+
+extern unsigned int js_time_speed;
+extern js_time_func js_get_time;
+extern js_delta_func js_delta;
+
+extern unsigned int js_time_speed_a;
+extern js_time_func js_get_time_a;
+extern js_delta_func js_delta_a;
+
+extern struct js_port *js_register_port(struct js_port *port, void *info,
+ int devs, int infos, js_read_func read);
+extern struct js_port *js_unregister_port(struct js_port *port);
+
+extern int js_register_device(struct js_port *port, int number, int axes,
+ int buttons, char *name, js_ops_func open, js_ops_func close);
+extern void js_unregister_device(struct js_dev *dev);
+
+/*
+ * Kernel interface
+ */
+
+extern int js_init(void);
+extern int js_am_init(void);
+extern int js_an_init(void);
+extern int js_as_init(void);
+extern int js_console_init(void);
+extern int js_db9_init(void);
+extern int js_gr_init(void);
+extern int js_l4_init(void);
+extern int js_lt_init(void);
+extern int js_sw_init(void);
+extern int js_tm_init(void);
+
+extern void js_am_setup(char *str, int *ints);
+extern void js_an_setup(char *str, int *ints);
+extern void js_as_setup(char *str, int *ints);
+extern void js_console_setup(char *str, int *ints);
+extern void js_db9_setup(char *str, int *ints);
+extern void js_l4_setup(char *str, int *ints);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_JOYSTICK_H */
diff --git a/pfinet/linux-src/include/linux/kbd_diacr.h b/pfinet/linux-src/include/linux/kbd_diacr.h
new file mode 100644
index 00000000..1c1a3ff0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kbd_diacr.h
@@ -0,0 +1,8 @@
+#ifndef _DIACR_H
+#define _DIACR_H
+#include <linux/kd.h>
+
+extern struct kbdiacr accent_table[];
+extern unsigned int accent_table_size;
+
+#endif /* _DIACR_H */
diff --git a/pfinet/linux-src/include/linux/kbd_kern.h b/pfinet/linux-src/include/linux/kbd_kern.h
new file mode 100644
index 00000000..f5ae9ed9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kbd_kern.h
@@ -0,0 +1,164 @@
+#ifndef _KBD_KERN_H
+#define _KBD_KERN_H
+
+#include <linux/interrupt.h>
+#include <linux/keyboard.h>
+
+extern int shift_state;
+
+extern char *func_table[MAX_NR_FUNC];
+extern char func_buf[];
+extern char *funcbufptr;
+extern int funcbufsize, funcbufleft;
+
+/*
+ * kbd->xxx contains the VC-local things (flag settings etc..)
+ *
+ * Note: externally visible are LED_SCR, LED_NUM, LED_CAP defined in kd.h
+ * The code in KDGETLED / KDSETLED depends on the internal and
+ * external order being the same.
+ *
+ * Note: lockstate is used as index in the array key_map.
+ */
+struct kbd_struct {
+
+ unsigned char lockstate;
+/* 8 modifiers - the names do not have any meaning at all;
+ they can be associated to arbitrarily chosen keys */
+#define VC_SHIFTLOCK KG_SHIFT /* shift lock mode */
+#define VC_ALTGRLOCK KG_ALTGR /* altgr lock mode */
+#define VC_CTRLLOCK KG_CTRL /* control lock mode */
+#define VC_ALTLOCK KG_ALT /* alt lock mode */
+#define VC_SHIFTLLOCK KG_SHIFTL /* shiftl lock mode */
+#define VC_SHIFTRLOCK KG_SHIFTR /* shiftr lock mode */
+#define VC_CTRLLLOCK KG_CTRLL /* ctrll lock mode */
+#define VC_CTRLRLOCK KG_CTRLR /* ctrlr lock mode */
+ unsigned char slockstate; /* for `sticky' Shift, Ctrl, etc. */
+
+ unsigned char ledmode:2; /* one 2-bit value */
+#define LED_SHOW_FLAGS 0 /* traditional state */
+#define LED_SHOW_IOCTL 1 /* only change leds upon ioctl */
+#define LED_SHOW_MEM 2 /* `heartbeat': peek into memory */
+
+ unsigned char ledflagstate:3; /* flags, not lights */
+ unsigned char default_ledflagstate:3;
+#define VC_SCROLLOCK 0 /* scroll-lock mode */
+#define VC_NUMLOCK 1 /* numeric lock mode */
+#define VC_CAPSLOCK 2 /* capslock mode */
+
+ unsigned char kbdmode:2; /* one 2-bit value */
+#define VC_XLATE 0 /* translate keycodes using keymap */
+#define VC_MEDIUMRAW 1 /* medium raw (keycode) mode */
+#define VC_RAW 2 /* raw (scancode) mode */
+#define VC_UNICODE 3 /* Unicode mode */
+
+ unsigned char modeflags:5;
+#define VC_APPLIC 0 /* application key mode */
+#define VC_CKMODE 1 /* cursor key mode */
+#define VC_REPEAT 2 /* keyboard repeat */
+#define VC_CRLF 3 /* 0 - enter sends CR, 1 - enter sends CRLF */
+#define VC_META 4 /* 0 - meta, 1 - meta=prefix with ESC */
+};
+
+extern struct kbd_struct kbd_table[];
+
+extern int kbd_init(void);
+
+extern unsigned char getledstate(void);
+extern void setledstate(struct kbd_struct *kbd, unsigned int led);
+
+extern int do_poke_blanked_console;
+
+extern inline void show_console(void)
+{
+ do_poke_blanked_console = 1;
+ mark_bh(CONSOLE_BH);
+}
+
+extern inline void set_console(int nr)
+{
+ want_console = nr;
+ mark_bh(CONSOLE_BH);
+}
+
+extern inline void set_leds(void)
+{
+ mark_bh(KEYBOARD_BH);
+}
+
+extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag)
+{
+ return ((kbd->modeflags >> flag) & 1);
+}
+
+extern inline int vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+ return ((kbd->ledflagstate >> flag) & 1);
+}
+
+extern inline void set_vc_kbd_mode(struct kbd_struct * kbd, int flag)
+{
+ kbd->modeflags |= 1 << flag;
+}
+
+extern inline void set_vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+ kbd->ledflagstate |= 1 << flag;
+}
+
+extern inline void clr_vc_kbd_mode(struct kbd_struct * kbd, int flag)
+{
+ kbd->modeflags &= ~(1 << flag);
+}
+
+extern inline void clr_vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+ kbd->ledflagstate &= ~(1 << flag);
+}
+
+extern inline void chg_vc_kbd_lock(struct kbd_struct * kbd, int flag)
+{
+ kbd->lockstate ^= 1 << flag;
+}
+
+extern inline void chg_vc_kbd_slock(struct kbd_struct * kbd, int flag)
+{
+ kbd->slockstate ^= 1 << flag;
+}
+
+extern inline void chg_vc_kbd_mode(struct kbd_struct * kbd, int flag)
+{
+ kbd->modeflags ^= 1 << flag;
+}
+
+extern inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag)
+{
+ kbd->ledflagstate ^= 1 << flag;
+}
+
+#define U(x) ((x) ^ 0xf000)
+
+/* keyboard.c */
+
+struct console;
+
+int getkeycode(unsigned int scancode);
+int setkeycode(unsigned int scancode, unsigned int keycode);
+void compute_shiftstate(void);
+int keyboard_wait_for_keypress(struct console *);
+
+/* defkeymap.c */
+
+extern unsigned int keymap_count;
+
+/* console.c */
+
+extern task_queue con_task_queue;
+
+extern inline void con_schedule_flip(struct tty_struct *t)
+{
+ queue_task(&t->flip.tqueue, &con_task_queue);
+ mark_bh(CONSOLE_BH);
+}
+
+#endif
diff --git a/pfinet/linux-src/include/linux/kbd_ll.h b/pfinet/linux-src/include/linux/kbd_ll.h
new file mode 100644
index 00000000..02ebf8ec
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kbd_ll.h
@@ -0,0 +1,12 @@
+/*
+ * Interface between the low-level keyboard driver and the keymapper
+ */
+
+#ifndef _KBD_LL_H
+#define _KBD_LL_H
+
+extern struct pt_regs *kbd_pt_regs;
+
+void handle_scancode(unsigned char scancode, int down);
+
+#endif /* _KBD_LL_H */
diff --git a/pfinet/linux-src/include/linux/kd.h b/pfinet/linux-src/include/linux/kd.h
new file mode 100644
index 00000000..c717c198
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kd.h
@@ -0,0 +1,180 @@
+#ifndef _LINUX_KD_H
+#define _LINUX_KD_H
+#include <linux/types.h>
+
+/* 0x4B is 'K', to avoid collision with termios and vt */
+
+#define GIO_FONT 0x4B60 /* gets font in expanded form */
+#define PIO_FONT 0x4B61 /* use font in expanded form */
+
+#define GIO_FONTX 0x4B6B /* get font using struct consolefontdesc */
+#define PIO_FONTX 0x4B6C /* set font using struct consolefontdesc */
+struct consolefontdesc {
+ unsigned short charcount; /* characters in font (256 or 512) */
+ unsigned short charheight; /* scan lines per character (1-32) */
+ char *chardata; /* font data in expanded form */
+};
+
+#define PIO_FONTRESET 0x4B6D /* reset to default font */
+
+#define GIO_CMAP 0x4B70 /* gets colour palette on VGA+ */
+#define PIO_CMAP 0x4B71 /* sets colour palette on VGA+ */
+
+#define KIOCSOUND 0x4B2F /* start sound generation (0 for off) */
+#define KDMKTONE 0x4B30 /* generate tone */
+
+#define KDGETLED 0x4B31 /* return current led state */
+#define KDSETLED 0x4B32 /* set led state [lights, not flags] */
+#define LED_SCR 0x01 /* scroll lock led */
+#define LED_CAP 0x04 /* caps lock led */
+#define LED_NUM 0x02 /* num lock led */
+
+#define KDGKBTYPE 0x4B33 /* get keyboard type */
+#define KB_84 0x01
+#define KB_101 0x02 /* this is what we always answer */
+#define KB_OTHER 0x03
+
+#define KDADDIO 0x4B34 /* add i/o port as valid */
+#define KDDELIO 0x4B35 /* del i/o port as valid */
+#define KDENABIO 0x4B36 /* enable i/o to video board */
+#define KDDISABIO 0x4B37 /* disable i/o to video board */
+
+#define KDSETMODE 0x4B3A /* set text/graphics mode */
+#define KD_TEXT 0x00
+#define KD_GRAPHICS 0x01
+#define KD_TEXT0 0x02 /* obsolete */
+#define KD_TEXT1 0x03 /* obsolete */
+#define KDGETMODE 0x4B3B /* get current mode */
+
+#define KDMAPDISP 0x4B3C /* map display into address space */
+#define KDUNMAPDISP 0x4B3D /* unmap display from address space */
+
+typedef char scrnmap_t;
+#define E_TABSZ 256
+#define GIO_SCRNMAP 0x4B40 /* get screen mapping from kernel */
+#define PIO_SCRNMAP 0x4B41 /* put screen mapping table in kernel */
+#define GIO_UNISCRNMAP 0x4B69 /* get full Unicode screen mapping */
+#define PIO_UNISCRNMAP 0x4B6A /* set full Unicode screen mapping */
+
+#define GIO_UNIMAP 0x4B66 /* get unicode-to-font mapping from kernel */
+struct unipair {
+ unsigned short unicode;
+ unsigned short fontpos;
+};
+struct unimapdesc {
+ unsigned short entry_ct;
+ struct unipair *entries;
+};
+#define PIO_UNIMAP 0x4B67 /* put unicode-to-font mapping in kernel */
+#define PIO_UNIMAPCLR 0x4B68 /* clear table, possibly advise hash algorithm */
+struct unimapinit {
+ unsigned short advised_hashsize; /* 0 if no opinion */
+ unsigned short advised_hashstep; /* 0 if no opinion */
+ unsigned short advised_hashlevel; /* 0 if no opinion */
+};
+
+#define UNI_DIRECT_BASE 0xF000 /* start of Direct Font Region */
+#define UNI_DIRECT_MASK 0x01FF /* Direct Font Region bitmask */
+
+#define K_RAW 0x00
+#define K_XLATE 0x01
+#define K_MEDIUMRAW 0x02
+#define K_UNICODE 0x03
+#define KDGKBMODE 0x4B44 /* gets current keyboard mode */
+#define KDSKBMODE 0x4B45 /* sets current keyboard mode */
+
+#define K_METABIT 0x03
+#define K_ESCPREFIX 0x04
+#define KDGKBMETA 0x4B62 /* gets meta key handling mode */
+#define KDSKBMETA 0x4B63 /* sets meta key handling mode */
+
+#define K_SCROLLLOCK 0x01
+#define K_CAPSLOCK 0x02
+#define K_NUMLOCK 0x04
+#define KDGKBLED 0x4B64 /* get led flags (not lights) */
+#define KDSKBLED 0x4B65 /* set led flags (not lights) */
+
+struct kbentry {
+ unsigned char kb_table;
+ unsigned char kb_index;
+ unsigned short kb_value;
+};
+#define K_NORMTAB 0x00
+#define K_SHIFTTAB 0x01
+#define K_ALTTAB 0x02
+#define K_ALTSHIFTTAB 0x03
+
+#define KDGKBENT 0x4B46 /* gets one entry in translation table */
+#define KDSKBENT 0x4B47 /* sets one entry in translation table */
+
+struct kbsentry {
+ unsigned char kb_func;
+ unsigned char kb_string[512];
+};
+#define KDGKBSENT 0x4B48 /* gets one function key string entry */
+#define KDSKBSENT 0x4B49 /* sets one function key string entry */
+
+struct kbdiacr {
+ unsigned char diacr, base, result;
+};
+struct kbdiacrs {
+ unsigned int kb_cnt; /* number of entries in following array */
+ struct kbdiacr kbdiacr[256]; /* MAX_DIACR from keyboard.h */
+};
+#define KDGKBDIACR 0x4B4A /* read kernel accent table */
+#define KDSKBDIACR 0x4B4B /* write kernel accent table */
+
+struct kbkeycode {
+ unsigned int scancode, keycode;
+};
+#define KDGETKEYCODE 0x4B4C /* read kernel keycode table entry */
+#define KDSETKEYCODE 0x4B4D /* write kernel keycode table entry */
+
+#define KDSIGACCEPT 0x4B4E /* accept kbd generated signals */
+
+struct hwclk_time {
+ unsigned sec; /* 0..59 */
+ unsigned min; /* 0..59 */
+ unsigned hour; /* 0..23 */
+ unsigned day; /* 1..31 */
+ unsigned mon; /* 0..11 */
+ unsigned year; /* 70... */
+ int wday; /* 0..6, 0 is Sunday, -1 means unknown/don't set */
+};
+
+#define KDGHWCLK 0x4B50 /* get hardware clock */
+#define KDSHWCLK 0x4B51 /* set hardware clock */
+
+struct kbd_repeat {
+ int delay; /* in msec; <= 0: don't change */
+ int rate; /* in msec; <= 0: don't change */
+};
+
+#define KDKBDREP 0x4B52 /* set keyboard delay/repeat rate;
+ * actually used values are returned */
+
+#define KDFONTOP 0x4B72 /* font operations */
+
+struct console_font_op {
+ unsigned int op; /* operation code KD_FONT_OP_* */
+ unsigned int flags; /* KD_FONT_FLAG_* */
+ unsigned int width, height; /* font size */
+ unsigned int charcount;
+ unsigned char *data; /* font data with height fixed to 32 */
+};
+
+#define KD_FONT_OP_SET 0 /* Set font */
+#define KD_FONT_OP_GET 1 /* Get font */
+#define KD_FONT_OP_SET_DEFAULT 2 /* Set font to default, data points to name / NULL */
+#define KD_FONT_OP_COPY 3 /* Copy from another console */
+
+#define KD_FONT_FLAG_DONT_RECALC 1 /* Don't recalculate hw charcell size [compat] */
+#ifdef __KERNEL__
+#define KD_FONT_FLAG_OLD 0x80000000 /* Invoked via old interface [compat] */
+#endif
+
+/* note: 0x4B00-0x4B4E all have had a value at some time;
+ don't reuse for the time being */
+/* note: 0x4B60-0x4B6D, 0x4B70-0x4B72 used above */
+
+#endif /* _LINUX_KD_H */
diff --git a/pfinet/linux-src/include/linux/kdev_t.h b/pfinet/linux-src/include/linux/kdev_t.h
new file mode 100644
index 00000000..a06cdb9e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kdev_t.h
@@ -0,0 +1,114 @@
+#ifndef _LINUX_KDEV_T_H
+#define _LINUX_KDEV_T_H
+#ifdef __KERNEL__
+/*
+As a preparation for the introduction of larger device numbers,
+we introduce a type kdev_t to hold them. No information about
+this type is known outside of this include file.
+
+Objects of type kdev_t designate a device. Outside of the kernel
+the corresponding things are objects of type dev_t - usually an
+integral type with the device major and minor in the high and low
+bits, respectively. Conversion is done by
+
+extern kdev_t to_kdev_t(int);
+
+It is up to the various file systems to decide how objects of type
+dev_t are stored on disk.
+The only other point of contact between kernel and outside world
+are the system calls stat and mknod, new versions of which will
+eventually have to be used in libc.
+
+[Unfortunately, the floppy control ioctls fail to hide the internal
+kernel structures, and the fd_device field of a struct floppy_drive_struct
+is user-visible. So, it remains a dev_t for the moment, with some ugly
+conversions in floppy.c.]
+
+Inside the kernel, we aim for a kdev_t type that is a pointer
+to a structure with information about the device (like major,
+minor, size, blocksize, sectorsize, name, read-only flag,
+struct file_operations etc.).
+
+However, for the time being we let kdev_t be almost the same as dev_t:
+
+typedef struct { unsigned short major, minor; } kdev_t;
+
+Admissible operations on an object of type kdev_t:
+- passing it along
+- comparing it for equality with another such object
+- storing it in ROOT_DEV, inode->i_dev, inode->i_rdev, sb->s_dev,
+ bh->b_dev, req->rq_dev, de->dc_dev, tty->device
+- using its bit pattern as argument in a hash function
+- finding its major and minor
+- complaining about it
+
+An object of type kdev_t is created only by the function MKDEV(),
+with the single exception of the constant 0 (no device).
+
+Right now the other information mentioned above is usually found
+in static arrays indexed by major or major,minor.
+
+An obstacle to immediately using
+ typedef struct { ... (* lots of information *) } *kdev_t
+is the case of mknod used to create a block device that the
+kernel doesn't know about at present (but first learns about
+when some module is inserted).
+
+aeb - 950811
+*/
+
+/* Since MINOR(dev) is used as index in static arrays,
+ the kernel is not quite ready yet for larger minors.
+ However, everything runs fine with an arbitrary kdev_t type. */
+
+#define MINORBITS 8
+#define MINORMASK ((1U << MINORBITS) - 1)
+
+typedef unsigned short kdev_t;
+
+#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
+#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
+#define HASHDEV(dev) ((unsigned int) (dev))
+#define NODEV 0
+#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
+#define B_FREE 0xffff /* yuk */
+
+extern char * kdevname(kdev_t); /* note: returns pointer to static data! */
+
+/*
+As long as device numbers in the outside world have 16 bits only,
+we use these conversions.
+*/
+
+static inline unsigned int kdev_t_to_nr(kdev_t dev) {
+ return (MAJOR(dev)<<8) | MINOR(dev);
+}
+
+static inline kdev_t to_kdev_t(int dev)
+{
+ int major, minor;
+#if 0
+ major = (dev >> 16);
+ if (!major) {
+ major = (dev >> 8);
+ minor = (dev & 0xff);
+ } else
+ minor = (dev & 0xffff);
+#else
+ major = (dev >> 8);
+ minor = (dev & 0xff);
+#endif
+ return MKDEV(major, minor);
+}
+
+#else /* __KERNEL__ */
+
+/*
+Some programs want their definitions of MAJOR and MINOR and MKDEV
+from the kernel sources. These must be the externally visible ones.
+*/
+#define MAJOR(dev) ((dev)>>8)
+#define MINOR(dev) ((dev) & 0xff)
+#define MKDEV(ma,mi) ((ma)<<8 | (mi))
+#endif /* __KERNEL__ */
+#endif
diff --git a/pfinet/linux-src/include/linux/kernel.h b/pfinet/linux-src/include/linux/kernel.h
new file mode 100644
index 00000000..73a0a689
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kernel.h
@@ -0,0 +1,96 @@
+#ifndef _LINUX_KERNEL_H
+#define _LINUX_KERNEL_H
+
+/*
+ * 'kernel.h' contains some often-used function prototypes etc
+ */
+
+#ifdef __KERNEL__
+
+#include <stdarg.h>
+#include <linux/linkage.h>
+
+/* Optimization barrier */
+/* The "volatile" is due to gcc bugs */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+#define INT_MAX ((int)(~0U>>1))
+#define UINT_MAX (~0U)
+#define LONG_MAX ((long)(~0UL>>1))
+#define ULONG_MAX (~0UL)
+
+#define STACK_MAGIC 0xdeadbeef
+
+#define KERN_EMERG "<0>" /* system is unusable */
+#define KERN_ALERT "<1>" /* action must be taken immediately */
+#define KERN_CRIT "<2>" /* critical conditions */
+#define KERN_ERR "<3>" /* error conditions */
+#define KERN_WARNING "<4>" /* warning conditions */
+#define KERN_NOTICE "<5>" /* normal but significant condition */
+#define KERN_INFO "<6>" /* informational */
+#define KERN_DEBUG "<7>" /* debug-level messages */
+
+# define NORET_TYPE /**/
+# define ATTRIB_NORET __attribute__((noreturn))
+# define NORET_AND noreturn,
+
+#ifdef __i386__
+#define FASTCALL(x) x __attribute__((regparm(3)))
+#else
+#define FASTCALL(x) x
+#endif
+
+extern void math_error(void);
+extern struct notifier_block *panic_notifier_list;
+NORET_TYPE void panic(const char * fmt, ...)
+ __attribute__ ((NORET_AND format (printf, 1, 2)));
+NORET_TYPE void do_exit(long error_code)
+ ATTRIB_NORET;
+extern unsigned long simple_strtoul(const char *,char **,unsigned int);
+extern long simple_strtol(const char *,char **,unsigned int);
+extern int sprintf(char * buf, const char * fmt, ...);
+extern int vsprintf(char *buf, const char *, va_list);
+
+extern int session_of_pgrp(int pgrp);
+
+asmlinkage int printk(const char * fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+#if DEBUG
+#define pr_debug(fmt,arg...) \
+ printk(KERN_DEBUG fmt,##arg)
+#else
+#define pr_debug(fmt,arg...) \
+ do { } while (0)
+#endif
+
+#define pr_info(fmt,arg...) \
+ printk(KERN_INFO fmt,##arg)
+
+/*
+ * Display an IP address in readable format.
+ */
+
+#define NIPQUAD(addr) \
+ ((unsigned char *)&addr)[0], \
+ ((unsigned char *)&addr)[1], \
+ ((unsigned char *)&addr)[2], \
+ ((unsigned char *)&addr)[3]
+
+#endif /* __KERNEL__ */
+
+#define SI_LOAD_SHIFT 16
+struct sysinfo {
+ long uptime; /* Seconds since boot */
+ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
+ unsigned long totalram; /* Total usable main memory size */
+ unsigned long freeram; /* Available memory size */
+ unsigned long sharedram; /* Amount of shared memory */
+ unsigned long bufferram; /* Memory used by buffers */
+ unsigned long totalswap; /* Total swap space size */
+ unsigned long freeswap; /* swap space still available */
+ unsigned short procs; /* Number of current processes */
+ char _f[22]; /* Pads structure to 64 bytes */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/kernel_stat.h b/pfinet/linux-src/include/linux/kernel_stat.h
new file mode 100644
index 00000000..cd584c1a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kernel_stat.h
@@ -0,0 +1,50 @@
+#ifndef _LINUX_KERNEL_STAT_H
+#define _LINUX_KERNEL_STAT_H
+
+#include <asm/irq.h>
+#include <linux/smp.h>
+#include <linux/tasks.h>
+
+/*
+ * 'kernel_stat.h' contains the definitions needed for doing
+ * some kernel statistics (CPU usage, context switches ...),
+ * used by rstatd/perfmeter
+ */
+
+#define DK_NDRIVE 4
+
+struct kernel_stat {
+ unsigned int cpu_user, cpu_nice, cpu_system;
+ unsigned int per_cpu_user[NR_CPUS],
+ per_cpu_nice[NR_CPUS],
+ per_cpu_system[NR_CPUS];
+ unsigned int dk_drive[DK_NDRIVE];
+ unsigned int dk_drive_rio[DK_NDRIVE];
+ unsigned int dk_drive_wio[DK_NDRIVE];
+ unsigned int dk_drive_rblk[DK_NDRIVE];
+ unsigned int dk_drive_wblk[DK_NDRIVE];
+ unsigned int pgpgin, pgpgout;
+ unsigned int pswpin, pswpout;
+ unsigned int irqs[NR_CPUS][NR_IRQS];
+ unsigned int ipackets, opackets;
+ unsigned int ierrors, oerrors;
+ unsigned int collisions;
+ unsigned int context_swtch;
+};
+
+extern struct kernel_stat kstat;
+
+/*
+ * Number of interrupts per specific IRQ source, since bootup
+ */
+extern inline int kstat_irqs (int irq)
+{
+ int i, sum=0;
+
+ for (i = 0 ; i < smp_num_cpus ; i++)
+ sum += kstat.irqs[cpu_logical_map(i)][irq];
+
+ return sum;
+}
+
+#endif /* _LINUX_KERNEL_STAT_H */
diff --git a/pfinet/linux-src/include/linux/kernelcapi.h b/pfinet/linux-src/include/linux/kernelcapi.h
new file mode 100644
index 00000000..7b212be0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kernelcapi.h
@@ -0,0 +1,136 @@
+/*
+ * $Id: kernelcapi.h,v 1.3 1999/07/01 15:26:56 calle Exp $
+ *
+ * Kernel CAPI 2.0 Interface for Linux
+ *
+ * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: kernelcapi.h,v $
+ * Revision 1.3 1999/07/01 15:26:56 calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ * - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ * - write a CAPI-2.0 for the passive cards
+ * - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ * make menuconfig, in the past all supported cards where included
+ * at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ * using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.2 1999/06/21 15:24:26 calle
+ * extend information in /proc.
+ *
+ * Revision 1.1 1997/03/04 21:27:33 calle
+ * First version in isdn4linux
+ *
+ * Revision 2.2 1997/02/12 09:31:39 calle
+ * new version
+ *
+ * Revision 1.1 1997/01/31 10:32:20 calle
+ * Initial revision
+ *
+ *
+ */
+#ifndef __KERNELCAPI_H__
+#define __KERNELCAPI_H__
+
+#define CAPI_MAXAPPL 20 /*
+ * maximum number of applications
+ */
+#define CAPI_MAXCONTR 10 /*
+ * maximum number of controller
+ */
+#define CAPI_MAXDATAWINDOW 8
+
+
+typedef struct kcapi_flagdef {
+ int contr;
+ int flag;
+} kcapi_flagdef;
+
+/* new ioctls >= 10 */
+#define KCAPI_CMD_TRACE 10
+
+/*
+ * flag > 2 => trace also data
+ * flag & 1 => show trace
+ */
+#define KCAPI_TRACE_OFF 0
+#define KCAPI_TRACE_SHORT_NO_DATA 1
+#define KCAPI_TRACE_FULL_NO_DATA 2
+#define KCAPI_TRACE_SHORT 3
+#define KCAPI_TRACE_FULL 4
+
+
+#ifdef __KERNEL__
+
+struct capi_interface {
+ int (*capi_installed) (void);
+
+ __u16(*capi_register) (capi_register_params * rparam, __u16 * applidp);
+ __u16(*capi_release) (__u16 applid);
+ __u16(*capi_put_message) (__u16 applid, struct sk_buff * msg);
+ __u16(*capi_get_message) (__u16 applid, struct sk_buff ** msgp);
+ __u16(*capi_set_signal) (__u16 applid,
+ void (*signal) (__u16 applid, __u32 param),
+ __u32 param);
+ __u16(*capi_get_manufacturer) (__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN]);
+ __u16(*capi_get_version) (__u16 contr, struct capi_version * verp);
+ __u16(*capi_get_serial) (__u16 contr, __u8 serial[CAPI_SERIAL_LEN]);
+ __u16(*capi_get_profile) (__u16 contr, struct capi_profile * profp);
+
+ /*
+ * to init controllers, data is always in user memory
+ */
+ int (*capi_manufacturer) (unsigned int cmd, void *data);
+
+};
+
+#define KCI_CONTRUP 0
+#define KCI_CONTRDOWN 1
+
+struct capi_interface_user {
+ char name[20];
+ void (*callback) (unsigned int cmd, __u16 contr, void *data);
+ /* internal */
+ struct capi_interface_user *next;
+};
+
+struct capi_interface *attach_capi_interface(struct capi_interface_user *);
+int detach_capi_interface(struct capi_interface_user *);
+
+
+#define CAPI_NOERROR 0x0000
+
+#define CAPI_TOOMANYAPPLS 0x1001
+#define CAPI_LOGBLKSIZETOSMALL 0x1002
+#define CAPI_BUFFEXECEEDS64K 0x1003
+#define CAPI_MSGBUFSIZETOOSMALL 0x1004
+#define CAPI_ANZLOGCONNNOTSUPPORTED 0x1005
+#define CAPI_REGRESERVED 0x1006
+#define CAPI_REGBUSY 0x1007
+#define CAPI_REGOSRESOURCEERR 0x1008
+#define CAPI_REGNOTINSTALLED 0x1009
+#define CAPI_REGCTRLERNOTSUPPORTEXTEQUIP 0x100a
+#define CAPI_REGCTRLERONLYSUPPORTEXTEQUIP 0x100b
+
+#define CAPI_ILLAPPNR 0x1101
+#define CAPI_ILLCMDORSUBCMDORMSGTOSMALL 0x1102
+#define CAPI_SENDQUEUEFULL 0x1103
+#define CAPI_RECEIVEQUEUEEMPTY 0x1104
+#define CAPI_RECEIVEOVERFLOW 0x1105
+#define CAPI_UNKNOWNNOTPAR 0x1106
+#define CAPI_MSGBUSY 0x1107
+#define CAPI_MSGOSRESOURCEERR 0x1108
+#define CAPI_MSGNOTINSTALLED 0x1109
+#define CAPI_MSGCTRLERNOTSUPPORTEXTEQUIP 0x110a
+#define CAPI_MSGCTRLERONLYSUPPORTEXTEQUIP 0x110b
+
+#endif /* __KERNEL__ */
+
+#endif /* __KERNELCAPI_H__ */
diff --git a/pfinet/linux-src/include/linux/keyboard.h b/pfinet/linux-src/include/linux/keyboard.h
new file mode 100644
index 00000000..6829c653
--- /dev/null
+++ b/pfinet/linux-src/include/linux/keyboard.h
@@ -0,0 +1,430 @@
+#ifndef __LINUX_KEYBOARD_H
+#define __LINUX_KEYBOARD_H
+
+#define KG_SHIFT 0
+#define KG_CTRL 2
+#define KG_ALT 3
+#define KG_ALTGR 1
+#define KG_SHIFTL 4
+#define KG_SHIFTR 5
+#define KG_CTRLL 6
+#define KG_CTRLR 7
+#define KG_CAPSSHIFT 8
+
+#define NR_SHIFT 9
+
+#define NR_KEYS 128
+#define MAX_NR_KEYMAPS 256
+/* This means 64Kb if all keymaps are allocated. Only the superuser
+ may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
+#define MAX_NR_OF_USER_KEYMAPS 256 /* should be at least 7 */
+
+#ifdef __KERNEL__
+extern const int NR_TYPES;
+extern const int max_vals[];
+extern unsigned short *key_maps[MAX_NR_KEYMAPS];
+extern unsigned short plain_map[NR_KEYS];
+extern struct wait_queue * keypress_wait;
+extern unsigned char keyboard_type;
+#endif
+
+#define MAX_NR_FUNC 256 /* max nr of strings assigned to keys */
+
+#define KT_LATIN 0 /* we depend on this being zero */
+#define KT_LETTER 11 /* symbol that can be acted upon by CapsLock */
+#define KT_FN 1
+#define KT_SPEC 2
+#define KT_PAD 3
+#define KT_DEAD 4
+#define KT_CONS 5
+#define KT_CUR 6
+#define KT_SHIFT 7
+#define KT_META 8
+#define KT_ASCII 9
+#define KT_LOCK 10
+#define KT_SLOCK 12
+
+#define K(t,v) (((t)<<8)|(v))
+#define KTYP(x) ((x) >> 8)
+#define KVAL(x) ((x) & 0xff)
+
+#define K_F1 K(KT_FN,0)
+#define K_F2 K(KT_FN,1)
+#define K_F3 K(KT_FN,2)
+#define K_F4 K(KT_FN,3)
+#define K_F5 K(KT_FN,4)
+#define K_F6 K(KT_FN,5)
+#define K_F7 K(KT_FN,6)
+#define K_F8 K(KT_FN,7)
+#define K_F9 K(KT_FN,8)
+#define K_F10 K(KT_FN,9)
+#define K_F11 K(KT_FN,10)
+#define K_F12 K(KT_FN,11)
+#define K_F13 K(KT_FN,12)
+#define K_F14 K(KT_FN,13)
+#define K_F15 K(KT_FN,14)
+#define K_F16 K(KT_FN,15)
+#define K_F17 K(KT_FN,16)
+#define K_F18 K(KT_FN,17)
+#define K_F19 K(KT_FN,18)
+#define K_F20 K(KT_FN,19)
+#define K_FIND K(KT_FN,20)
+#define K_INSERT K(KT_FN,21)
+#define K_REMOVE K(KT_FN,22)
+#define K_SELECT K(KT_FN,23)
+#define K_PGUP K(KT_FN,24) /* PGUP is a synonym for PRIOR */
+#define K_PGDN K(KT_FN,25) /* PGDN is a synonym for NEXT */
+#define K_MACRO K(KT_FN,26)
+#define K_HELP K(KT_FN,27)
+#define K_DO K(KT_FN,28)
+#define K_PAUSE K(KT_FN,29)
+#define K_F21 K(KT_FN,30)
+#define K_F22 K(KT_FN,31)
+#define K_F23 K(KT_FN,32)
+#define K_F24 K(KT_FN,33)
+#define K_F25 K(KT_FN,34)
+#define K_F26 K(KT_FN,35)
+#define K_F27 K(KT_FN,36)
+#define K_F28 K(KT_FN,37)
+#define K_F29 K(KT_FN,38)
+#define K_F30 K(KT_FN,39)
+#define K_F31 K(KT_FN,40)
+#define K_F32 K(KT_FN,41)
+#define K_F33 K(KT_FN,42)
+#define K_F34 K(KT_FN,43)
+#define K_F35 K(KT_FN,44)
+#define K_F36 K(KT_FN,45)
+#define K_F37 K(KT_FN,46)
+#define K_F38 K(KT_FN,47)
+#define K_F39 K(KT_FN,48)
+#define K_F40 K(KT_FN,49)
+#define K_F41 K(KT_FN,50)
+#define K_F42 K(KT_FN,51)
+#define K_F43 K(KT_FN,52)
+#define K_F44 K(KT_FN,53)
+#define K_F45 K(KT_FN,54)
+#define K_F46 K(KT_FN,55)
+#define K_F47 K(KT_FN,56)
+#define K_F48 K(KT_FN,57)
+#define K_F49 K(KT_FN,58)
+#define K_F50 K(KT_FN,59)
+#define K_F51 K(KT_FN,60)
+#define K_F52 K(KT_FN,61)
+#define K_F53 K(KT_FN,62)
+#define K_F54 K(KT_FN,63)
+#define K_F55 K(KT_FN,64)
+#define K_F56 K(KT_FN,65)
+#define K_F57 K(KT_FN,66)
+#define K_F58 K(KT_FN,67)
+#define K_F59 K(KT_FN,68)
+#define K_F60 K(KT_FN,69)
+#define K_F61 K(KT_FN,70)
+#define K_F62 K(KT_FN,71)
+#define K_F63 K(KT_FN,72)
+#define K_F64 K(KT_FN,73)
+#define K_F65 K(KT_FN,74)
+#define K_F66 K(KT_FN,75)
+#define K_F67 K(KT_FN,76)
+#define K_F68 K(KT_FN,77)
+#define K_F69 K(KT_FN,78)
+#define K_F70 K(KT_FN,79)
+#define K_F71 K(KT_FN,80)
+#define K_F72 K(KT_FN,81)
+#define K_F73 K(KT_FN,82)
+#define K_F74 K(KT_FN,83)
+#define K_F75 K(KT_FN,84)
+#define K_F76 K(KT_FN,85)
+#define K_F77 K(KT_FN,86)
+#define K_F78 K(KT_FN,87)
+#define K_F79 K(KT_FN,88)
+#define K_F80 K(KT_FN,89)
+#define K_F81 K(KT_FN,90)
+#define K_F82 K(KT_FN,91)
+#define K_F83 K(KT_FN,92)
+#define K_F84 K(KT_FN,93)
+#define K_F85 K(KT_FN,94)
+#define K_F86 K(KT_FN,95)
+#define K_F87 K(KT_FN,96)
+#define K_F88 K(KT_FN,97)
+#define K_F89 K(KT_FN,98)
+#define K_F90 K(KT_FN,99)
+#define K_F91 K(KT_FN,100)
+#define K_F92 K(KT_FN,101)
+#define K_F93 K(KT_FN,102)
+#define K_F94 K(KT_FN,103)
+#define K_F95 K(KT_FN,104)
+#define K_F96 K(KT_FN,105)
+#define K_F97 K(KT_FN,106)
+#define K_F98 K(KT_FN,107)
+#define K_F99 K(KT_FN,108)
+#define K_F100 K(KT_FN,109)
+#define K_F101 K(KT_FN,110)
+#define K_F102 K(KT_FN,111)
+#define K_F103 K(KT_FN,112)
+#define K_F104 K(KT_FN,113)
+#define K_F105 K(KT_FN,114)
+#define K_F106 K(KT_FN,115)
+#define K_F107 K(KT_FN,116)
+#define K_F108 K(KT_FN,117)
+#define K_F109 K(KT_FN,118)
+#define K_F110 K(KT_FN,119)
+#define K_F111 K(KT_FN,120)
+#define K_F112 K(KT_FN,121)
+#define K_F113 K(KT_FN,122)
+#define K_F114 K(KT_FN,123)
+#define K_F115 K(KT_FN,124)
+#define K_F116 K(KT_FN,125)
+#define K_F117 K(KT_FN,126)
+#define K_F118 K(KT_FN,127)
+#define K_F119 K(KT_FN,128)
+#define K_F120 K(KT_FN,129)
+#define K_F121 K(KT_FN,130)
+#define K_F122 K(KT_FN,131)
+#define K_F123 K(KT_FN,132)
+#define K_F124 K(KT_FN,133)
+#define K_F125 K(KT_FN,134)
+#define K_F126 K(KT_FN,135)
+#define K_F127 K(KT_FN,136)
+#define K_F128 K(KT_FN,137)
+#define K_F129 K(KT_FN,138)
+#define K_F130 K(KT_FN,139)
+#define K_F131 K(KT_FN,140)
+#define K_F132 K(KT_FN,141)
+#define K_F133 K(KT_FN,142)
+#define K_F134 K(KT_FN,143)
+#define K_F135 K(KT_FN,144)
+#define K_F136 K(KT_FN,145)
+#define K_F137 K(KT_FN,146)
+#define K_F138 K(KT_FN,147)
+#define K_F139 K(KT_FN,148)
+#define K_F140 K(KT_FN,149)
+#define K_F141 K(KT_FN,150)
+#define K_F142 K(KT_FN,151)
+#define K_F143 K(KT_FN,152)
+#define K_F144 K(KT_FN,153)
+#define K_F145 K(KT_FN,154)
+#define K_F146 K(KT_FN,155)
+#define K_F147 K(KT_FN,156)
+#define K_F148 K(KT_FN,157)
+#define K_F149 K(KT_FN,158)
+#define K_F150 K(KT_FN,159)
+#define K_F151 K(KT_FN,160)
+#define K_F152 K(KT_FN,161)
+#define K_F153 K(KT_FN,162)
+#define K_F154 K(KT_FN,163)
+#define K_F155 K(KT_FN,164)
+#define K_F156 K(KT_FN,165)
+#define K_F157 K(KT_FN,166)
+#define K_F158 K(KT_FN,167)
+#define K_F159 K(KT_FN,168)
+#define K_F160 K(KT_FN,169)
+#define K_F161 K(KT_FN,170)
+#define K_F162 K(KT_FN,171)
+#define K_F163 K(KT_FN,172)
+#define K_F164 K(KT_FN,173)
+#define K_F165 K(KT_FN,174)
+#define K_F166 K(KT_FN,175)
+#define K_F167 K(KT_FN,176)
+#define K_F168 K(KT_FN,177)
+#define K_F169 K(KT_FN,178)
+#define K_F170 K(KT_FN,179)
+#define K_F171 K(KT_FN,180)
+#define K_F172 K(KT_FN,181)
+#define K_F173 K(KT_FN,182)
+#define K_F174 K(KT_FN,183)
+#define K_F175 K(KT_FN,184)
+#define K_F176 K(KT_FN,185)
+#define K_F177 K(KT_FN,186)
+#define K_F178 K(KT_FN,187)
+#define K_F179 K(KT_FN,188)
+#define K_F180 K(KT_FN,189)
+#define K_F181 K(KT_FN,190)
+#define K_F182 K(KT_FN,191)
+#define K_F183 K(KT_FN,192)
+#define K_F184 K(KT_FN,193)
+#define K_F185 K(KT_FN,194)
+#define K_F186 K(KT_FN,195)
+#define K_F187 K(KT_FN,196)
+#define K_F188 K(KT_FN,197)
+#define K_F189 K(KT_FN,198)
+#define K_F190 K(KT_FN,199)
+#define K_F191 K(KT_FN,200)
+#define K_F192 K(KT_FN,201)
+#define K_F193 K(KT_FN,202)
+#define K_F194 K(KT_FN,203)
+#define K_F195 K(KT_FN,204)
+#define K_F196 K(KT_FN,205)
+#define K_F197 K(KT_FN,206)
+#define K_F198 K(KT_FN,207)
+#define K_F199 K(KT_FN,208)
+#define K_F200 K(KT_FN,209)
+#define K_F201 K(KT_FN,210)
+#define K_F202 K(KT_FN,211)
+#define K_F203 K(KT_FN,212)
+#define K_F204 K(KT_FN,213)
+#define K_F205 K(KT_FN,214)
+#define K_F206 K(KT_FN,215)
+#define K_F207 K(KT_FN,216)
+#define K_F208 K(KT_FN,217)
+#define K_F209 K(KT_FN,218)
+#define K_F210 K(KT_FN,219)
+#define K_F211 K(KT_FN,220)
+#define K_F212 K(KT_FN,221)
+#define K_F213 K(KT_FN,222)
+#define K_F214 K(KT_FN,223)
+#define K_F215 K(KT_FN,224)
+#define K_F216 K(KT_FN,225)
+#define K_F217 K(KT_FN,226)
+#define K_F218 K(KT_FN,227)
+#define K_F219 K(KT_FN,228)
+#define K_F220 K(KT_FN,229)
+#define K_F221 K(KT_FN,230)
+#define K_F222 K(KT_FN,231)
+#define K_F223 K(KT_FN,232)
+#define K_F224 K(KT_FN,233)
+#define K_F225 K(KT_FN,234)
+#define K_F226 K(KT_FN,235)
+#define K_F227 K(KT_FN,236)
+#define K_F228 K(KT_FN,237)
+#define K_F229 K(KT_FN,238)
+#define K_F230 K(KT_FN,239)
+#define K_F231 K(KT_FN,240)
+#define K_F232 K(KT_FN,241)
+#define K_F233 K(KT_FN,242)
+#define K_F234 K(KT_FN,243)
+#define K_F235 K(KT_FN,244)
+#define K_F236 K(KT_FN,245)
+#define K_F237 K(KT_FN,246)
+#define K_F238 K(KT_FN,247)
+#define K_F239 K(KT_FN,248)
+#define K_F240 K(KT_FN,249)
+#define K_F241 K(KT_FN,250)
+#define K_F242 K(KT_FN,251)
+#define K_F243 K(KT_FN,252)
+#define K_F244 K(KT_FN,253)
+#define K_F245 K(KT_FN,254)
+#define K_UNDO K(KT_FN,255)
+
+
+#define K_HOLE K(KT_SPEC,0)
+#define K_ENTER K(KT_SPEC,1)
+#define K_SH_REGS K(KT_SPEC,2)
+#define K_SH_MEM K(KT_SPEC,3)
+#define K_SH_STAT K(KT_SPEC,4)
+#define K_BREAK K(KT_SPEC,5)
+#define K_CONS K(KT_SPEC,6)
+#define K_CAPS K(KT_SPEC,7)
+#define K_NUM K(KT_SPEC,8)
+#define K_HOLD K(KT_SPEC,9)
+#define K_SCROLLFORW K(KT_SPEC,10)
+#define K_SCROLLBACK K(KT_SPEC,11)
+#define K_BOOT K(KT_SPEC,12)
+#define K_CAPSON K(KT_SPEC,13)
+#define K_COMPOSE K(KT_SPEC,14)
+#define K_SAK K(KT_SPEC,15)
+#define K_DECRCONSOLE K(KT_SPEC,16)
+#define K_INCRCONSOLE K(KT_SPEC,17)
+#define K_SPAWNCONSOLE K(KT_SPEC,18)
+#define K_BARENUMLOCK K(KT_SPEC,19)
+
+#define K_ALLOCATED K(KT_SPEC,126) /* dynamically allocated keymap */
+#define K_NOSUCHMAP K(KT_SPEC,127) /* returned by KDGKBENT */
+
+#define K_P0 K(KT_PAD,0)
+#define K_P1 K(KT_PAD,1)
+#define K_P2 K(KT_PAD,2)
+#define K_P3 K(KT_PAD,3)
+#define K_P4 K(KT_PAD,4)
+#define K_P5 K(KT_PAD,5)
+#define K_P6 K(KT_PAD,6)
+#define K_P7 K(KT_PAD,7)
+#define K_P8 K(KT_PAD,8)
+#define K_P9 K(KT_PAD,9)
+#define K_PPLUS K(KT_PAD,10) /* key-pad plus */
+#define K_PMINUS K(KT_PAD,11) /* key-pad minus */
+#define K_PSTAR K(KT_PAD,12) /* key-pad asterisk (star) */
+#define K_PSLASH K(KT_PAD,13) /* key-pad slash */
+#define K_PENTER K(KT_PAD,14) /* key-pad enter */
+#define K_PCOMMA K(KT_PAD,15) /* key-pad comma: kludge... */
+#define K_PDOT K(KT_PAD,16) /* key-pad dot (period): kludge... */
+#define K_PPLUSMINUS K(KT_PAD,17) /* key-pad plus/minus */
+#define K_PPARENL K(KT_PAD,18) /* key-pad left parenthesis */
+#define K_PPARENR K(KT_PAD,19) /* key-pad right parenthesis */
+
+#define NR_PAD 20
+
+#define K_DGRAVE K(KT_DEAD,0)
+#define K_DACUTE K(KT_DEAD,1)
+#define K_DCIRCM K(KT_DEAD,2)
+#define K_DTILDE K(KT_DEAD,3)
+#define K_DDIERE K(KT_DEAD,4)
+#define K_DCEDIL K(KT_DEAD,5)
+
+#define NR_DEAD 6
+
+#define K_DOWN K(KT_CUR,0)
+#define K_LEFT K(KT_CUR,1)
+#define K_RIGHT K(KT_CUR,2)
+#define K_UP K(KT_CUR,3)
+
+#define K_SHIFT K(KT_SHIFT,KG_SHIFT)
+#define K_CTRL K(KT_SHIFT,KG_CTRL)
+#define K_ALT K(KT_SHIFT,KG_ALT)
+#define K_ALTGR K(KT_SHIFT,KG_ALTGR)
+#define K_SHIFTL K(KT_SHIFT,KG_SHIFTL)
+#define K_SHIFTR K(KT_SHIFT,KG_SHIFTR)
+#define K_CTRLL K(KT_SHIFT,KG_CTRLL)
+#define K_CTRLR K(KT_SHIFT,KG_CTRLR)
+#define K_CAPSSHIFT K(KT_SHIFT,KG_CAPSSHIFT)
+
+#define K_ASC0 K(KT_ASCII,0)
+#define K_ASC1 K(KT_ASCII,1)
+#define K_ASC2 K(KT_ASCII,2)
+#define K_ASC3 K(KT_ASCII,3)
+#define K_ASC4 K(KT_ASCII,4)
+#define K_ASC5 K(KT_ASCII,5)
+#define K_ASC6 K(KT_ASCII,6)
+#define K_ASC7 K(KT_ASCII,7)
+#define K_ASC8 K(KT_ASCII,8)
+#define K_ASC9 K(KT_ASCII,9)
+#define K_HEX0 K(KT_ASCII,10)
+#define K_HEX1 K(KT_ASCII,11)
+#define K_HEX2 K(KT_ASCII,12)
+#define K_HEX3 K(KT_ASCII,13)
+#define K_HEX4 K(KT_ASCII,14)
+#define K_HEX5 K(KT_ASCII,15)
+#define K_HEX6 K(KT_ASCII,16)
+#define K_HEX7 K(KT_ASCII,17)
+#define K_HEX8 K(KT_ASCII,18)
+#define K_HEX9 K(KT_ASCII,19)
+#define K_HEXa K(KT_ASCII,20)
+#define K_HEXb K(KT_ASCII,21)
+#define K_HEXc K(KT_ASCII,22)
+#define K_HEXd K(KT_ASCII,23)
+#define K_HEXe K(KT_ASCII,24)
+#define K_HEXf K(KT_ASCII,25)
+
+#define NR_ASCII 26
+
+#define K_SHIFTLOCK K(KT_LOCK,KG_SHIFT)
+#define K_CTRLLOCK K(KT_LOCK,KG_CTRL)
+#define K_ALTLOCK K(KT_LOCK,KG_ALT)
+#define K_ALTGRLOCK K(KT_LOCK,KG_ALTGR)
+#define K_SHIFTLLOCK K(KT_LOCK,KG_SHIFTL)
+#define K_SHIFTRLOCK K(KT_LOCK,KG_SHIFTR)
+#define K_CTRLLLOCK K(KT_LOCK,KG_CTRLL)
+#define K_CTRLRLOCK K(KT_LOCK,KG_CTRLR)
+
+#define K_SHIFT_SLOCK K(KT_SLOCK,KG_SHIFT)
+#define K_CTRL_SLOCK K(KT_SLOCK,KG_CTRL)
+#define K_ALT_SLOCK K(KT_SLOCK,KG_ALT)
+#define K_ALTGR_SLOCK K(KT_SLOCK,KG_ALTGR)
+#define K_SHIFTL_SLOCK K(KT_SLOCK,KG_SHIFTL)
+#define K_SHIFTR_SLOCK K(KT_SLOCK,KG_SHIFTR)
+#define K_CTRLL_SLOCK K(KT_SLOCK,KG_CTRLL)
+#define K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR)
+
+#define NR_LOCK 8
+
+#define MAX_DIACR 256
+#endif
diff --git a/pfinet/linux-src/include/linux/kmod.h b/pfinet/linux-src/include/linux/kmod.h
new file mode 100644
index 00000000..7392910d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/kmod.h
@@ -0,0 +1,12 @@
+/*
+ kmod header
+*/
+
+#include <linux/config.h>
+
+#ifdef CONFIG_KMOD
+extern int request_module(const char * name);
+#else
+#define request_module(x) do {} while(0)
+#endif
+
diff --git a/pfinet/linux-src/include/linux/lapb.h b/pfinet/linux-src/include/linux/lapb.h
new file mode 100644
index 00000000..bf1825a6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/lapb.h
@@ -0,0 +1,56 @@
+/*
+ * These are the public elements of the Linux LAPB module.
+ */
+
+#ifndef LAPB_KERNEL_H
+#define LAPB_KERNEL_H
+
+#define LAPB_OK 0
+#define LAPB_BADTOKEN 1
+#define LAPB_INVALUE 2
+#define LAPB_CONNECTED 3
+#define LAPB_NOTCONNECTED 4
+#define LAPB_REFUSED 5
+#define LAPB_TIMEDOUT 6
+#define LAPB_NOMEM 7
+
+#define LAPB_STANDARD 0x00
+#define LAPB_EXTENDED 0x01
+
+#define LAPB_SLP 0x00
+#define LAPB_MLP 0x02
+
+#define LAPB_DTE 0x00
+#define LAPB_DCE 0x04
+
+struct lapb_register_struct {
+ void (*connect_confirmation)(void *token, int reason);
+ void (*connect_indication)(void *token, int reason);
+ void (*disconnect_confirmation)(void *token, int reason);
+ void (*disconnect_indication)(void *token, int reason);
+ void (*data_indication)(void *token, struct sk_buff *skb);
+ void (*data_transmit)(void *token, struct sk_buff *skb);
+};
+
+struct lapb_parms_struct {
+ unsigned int t1;
+ unsigned int t1timer;
+ unsigned int t2;
+ unsigned int t2timer;
+ unsigned int n2;
+ unsigned int n2count;
+ unsigned int window;
+ unsigned int state;
+ unsigned int mode;
+};
+
+extern int lapb_register(void *token, struct lapb_register_struct *callbacks);
+extern int lapb_unregister(void *token);
+extern int lapb_getparms(void *token, struct lapb_parms_struct *parms);
+extern int lapb_setparms(void *token, struct lapb_parms_struct *parms);
+extern int lapb_connect_request(void *token);
+extern int lapb_disconnect_request(void *token);
+extern int lapb_data_request(void *token, struct sk_buff *skb);
+extern int lapb_data_received(void *token, struct sk_buff *skb);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/limits.h b/pfinet/linux-src/include/linux/limits.h
new file mode 100644
index 00000000..5848688e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/limits.h
@@ -0,0 +1,19 @@
+#ifndef _LINUX_LIMITS_H
+#define _LINUX_LIMITS_H
+
+#define NR_OPEN 1024
+
+#define NGROUPS_MAX 32 /* supplemental group IDs are available */
+#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
+#define CHILD_MAX 999 /* no limit :-) */
+#define OPEN_MAX 256 /* # open files a process may have */
+#define LINK_MAX 127 /* # links a file may have */
+#define MAX_CANON 255 /* size of the canonical input queue */
+#define MAX_INPUT 255 /* size of the type-ahead buffer */
+#define NAME_MAX 255 /* # chars in a file name */
+#define PATH_MAX 4095 /* # chars in a path name */
+#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
+
+#define RTSIG_MAX 32
+
+#endif
diff --git a/pfinet/linux-src/include/linux/linkage.h b/pfinet/linux-src/include/linux/linkage.h
new file mode 100644
index 00000000..190202f0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/linkage.h
@@ -0,0 +1,54 @@
+#ifndef _LINUX_LINKAGE_H
+#define _LINUX_LINKAGE_H
+
+#ifdef __cplusplus
+#define CPP_ASMLINKAGE extern "C"
+#else
+#define CPP_ASMLINKAGE
+#endif
+
+#if defined __i386__ && (__GNUC__ > 2 || __GNUC_MINOR__ > 7)
+#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
+#else
+#define asmlinkage CPP_ASMLINKAGE
+#endif
+
+#define SYMBOL_NAME_STR(X) #X
+#define SYMBOL_NAME(X) X
+#ifdef __STDC__
+#define SYMBOL_NAME_LABEL(X) X##:
+#else
+#define SYMBOL_NAME_LABEL(X) X/**/:
+#endif
+
+#ifdef __arm__
+#define __ALIGN .align 0
+#define __ALIGN_STR ".align 0"
+#else
+#ifdef __mc68000__
+#define __ALIGN .align 4
+#define __ALIGN_STR ".align 4"
+#else
+#if !defined(__i486__) && !defined(__i586__)
+#define __ALIGN .align 4,0x90
+#define __ALIGN_STR ".align 4,0x90"
+#else /* __i486__/__i586__ */
+#define __ALIGN .align 16,0x90
+#define __ALIGN_STR ".align 16,0x90"
+#endif /* __i486__/__i586__ */
+#endif /* __mc68000__ */
+#endif /* __arm__ */
+
+#ifdef __ASSEMBLY__
+
+#define ALIGN __ALIGN
+#define ALIGN_STR __ALIGN_STR
+
+#define ENTRY(name) \
+ .globl SYMBOL_NAME(name); \
+ ALIGN; \
+ SYMBOL_NAME_LABEL(name)
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/linux_logo.h b/pfinet/linux-src/include/linux/linux_logo.h
new file mode 100644
index 00000000..9aa712eb
--- /dev/null
+++ b/pfinet/linux-src/include/linux/linux_logo.h
@@ -0,0 +1,1445 @@
+/* $Id: linux_logo.h,v 1.5 1998/07/30 16:30:58 jj Exp $
+ * include/linux/linux_logo.h: This is a linux logo
+ * to be displayed on boot.
+ *
+ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from 0x20
+ * (i.e. RGB(linux_logo_red[0],
+ * linux_logo_green[0],
+ * linux_logo_blue[0]) is color 0x20)
+ * BW image has to be 80x80 as well, with MS bit
+ * on the left
+ * Serial_console ascii image can be any size,
+ * but should contain %s to display the version
+ */
+
+#if LINUX_LOGO_COLORS == 214
+
+unsigned char linux_logo_red[] __initdata = {
+ 0x02, 0x9E, 0xE9, 0xC4, 0x50, 0xC9, 0xC4, 0xE9,
+ 0x65, 0xE3, 0xC2, 0x25, 0xA4, 0xEC, 0x90, 0xA6,
+ 0xC4, 0x6A, 0xD1, 0xF3, 0x12, 0xED, 0xA0, 0xC2,
+ 0xB8, 0xD5, 0xDB, 0xD2, 0x3E, 0x16, 0xEB, 0x54,
+ 0xA9, 0xCD, 0xF5, 0x0A, 0xBA, 0xB3, 0xDC, 0x74,
+ 0xCE, 0xF6, 0xD3, 0xC5, 0xEA, 0xB8, 0xED, 0x5E,
+ 0xE5, 0x26, 0xF4, 0xA9, 0x82, 0x94, 0xE6, 0x38,
+ 0xF2, 0x0F, 0x7F, 0x49, 0xE5, 0xF4, 0xD3, 0xC3,
+ 0xC2, 0x1E, 0xD5, 0xC6, 0xA4, 0xFA, 0x0A, 0xBA,
+ 0xD4, 0xEB, 0xEA, 0xEC, 0xA8, 0xBC, 0xB4, 0xDC,
+ 0x84, 0xE4, 0xCE, 0xEC, 0x92, 0xCD, 0xDC, 0x8B,
+ 0xCC, 0x1E, 0xF6, 0xB2, 0x60, 0x2A, 0x96, 0x52,
+ 0x0F, 0xBD, 0xFA, 0xCC, 0xB8, 0x7A, 0x4C, 0xD2,
+ 0x06, 0xEF, 0x44, 0x64, 0xF4, 0xBA, 0xCE, 0xE6,
+ 0x8A, 0x6F, 0x3C, 0x70, 0x7C, 0x9C, 0xBA, 0xDF,
+ 0x2C, 0x4D, 0x3B, 0xCA, 0xDE, 0xCE, 0xEE, 0x46,
+ 0x6A, 0xAC, 0x96, 0xE5, 0x96, 0x7A, 0xBA, 0xB6,
+ 0xE2, 0x7E, 0xAA, 0xC5, 0x96, 0x9E, 0xC2, 0xAA,
+ 0xDA, 0x35, 0xB6, 0x82, 0x88, 0xBE, 0xC2, 0x9E,
+ 0xB4, 0xD5, 0xDA, 0x9C, 0xA0, 0xD0, 0xA8, 0xC7,
+ 0x72, 0xF2, 0xDB, 0x76, 0xDC, 0xBE, 0xAA, 0xF4,
+ 0x87, 0x2F, 0x53, 0x8E, 0x36, 0xCE, 0xE6, 0xCA,
+ 0xCB, 0xE4, 0xD6, 0xAA, 0x42, 0x5D, 0xB4, 0x59,
+ 0x1C, 0xC8, 0x96, 0x6C, 0xDA, 0xCE, 0xE6, 0xCB,
+ 0x96, 0x16, 0xFA, 0xBE, 0xAE, 0xFE, 0x6E, 0xD6,
+ 0xCE, 0xB6, 0xE5, 0xED, 0xDB, 0xDC, 0xF4, 0x72,
+ 0x1F, 0xAE, 0xE6, 0xC2, 0xCA, 0xC4
+};
+
+unsigned char linux_logo_green[] __initdata = {
+ 0x02, 0x88, 0xC4, 0x85, 0x44, 0xA2, 0xA8, 0xE5,
+ 0x65, 0xA6, 0xC2, 0x24, 0xA4, 0xB4, 0x62, 0x86,
+ 0x94, 0x44, 0xD2, 0xB6, 0x12, 0xD4, 0x73, 0x96,
+ 0x92, 0x95, 0xB2, 0xC2, 0x36, 0x0E, 0xBC, 0x54,
+ 0x75, 0xA5, 0xF5, 0x0A, 0xB2, 0x83, 0xC2, 0x74,
+ 0x9B, 0xBD, 0xA2, 0xCA, 0xDA, 0x8C, 0xCB, 0x42,
+ 0xAC, 0x12, 0xDA, 0x7B, 0x54, 0x94, 0xD2, 0x24,
+ 0xBE, 0x06, 0x65, 0x33, 0xBB, 0xBC, 0xAB, 0x8C,
+ 0x92, 0x1E, 0x9B, 0xB6, 0x6E, 0xFB, 0x04, 0xA2,
+ 0xC8, 0xBD, 0xAD, 0xEC, 0x92, 0xBC, 0x7B, 0x9D,
+ 0x84, 0xC4, 0xC4, 0xB4, 0x6C, 0x93, 0xA3, 0x5E,
+ 0x8D, 0x13, 0xD6, 0x82, 0x4C, 0x2A, 0x7A, 0x5A,
+ 0x0D, 0x82, 0xBB, 0xCC, 0x8B, 0x6A, 0x3C, 0xBE,
+ 0x06, 0xC4, 0x44, 0x45, 0xDB, 0x96, 0xB6, 0xDE,
+ 0x8A, 0x4D, 0x3C, 0x5A, 0x7C, 0x9C, 0xAA, 0xCB,
+ 0x1C, 0x4D, 0x2E, 0xB2, 0xBE, 0xAA, 0xDE, 0x3E,
+ 0x6A, 0xAC, 0x82, 0xE5, 0x72, 0x62, 0x92, 0x9E,
+ 0xCA, 0x4A, 0x8E, 0xBE, 0x86, 0x6B, 0xAA, 0x9A,
+ 0xBE, 0x34, 0xAB, 0x76, 0x6E, 0x9A, 0x9E, 0x62,
+ 0x76, 0xCE, 0xD3, 0x92, 0x7C, 0xB8, 0x7E, 0xC6,
+ 0x5E, 0xE2, 0xC3, 0x54, 0xAA, 0x9E, 0x8A, 0xCA,
+ 0x63, 0x2D, 0x3B, 0x8E, 0x1A, 0x9E, 0xC2, 0xA6,
+ 0xCB, 0xDC, 0xD6, 0x8E, 0x26, 0x5C, 0xB4, 0x45,
+ 0x1C, 0xB8, 0x6E, 0x4C, 0xBC, 0xAE, 0xD6, 0x92,
+ 0x63, 0x16, 0xF6, 0x8C, 0x7A, 0xFE, 0x6E, 0xBA,
+ 0xC6, 0x86, 0xAA, 0xAE, 0xDB, 0xA4, 0xD4, 0x56,
+ 0x0E, 0x6E, 0xB6, 0xB2, 0xBE, 0xBE
+};
+
+unsigned char linux_logo_blue[] __initdata = {
+ 0x04, 0x28, 0x10, 0x0B, 0x14, 0x14, 0x74, 0xC7,
+ 0x64, 0x0E, 0xC3, 0x24, 0xA4, 0x0C, 0x10, 0x20,
+ 0x0D, 0x04, 0xD1, 0x0D, 0x13, 0x22, 0x0A, 0x40,
+ 0x14, 0x0C, 0x11, 0x94, 0x0C, 0x08, 0x0B, 0x56,
+ 0x09, 0x47, 0xF4, 0x0B, 0x9C, 0x07, 0x54, 0x74,
+ 0x0F, 0x0C, 0x0F, 0xC7, 0x6C, 0x14, 0x14, 0x11,
+ 0x0B, 0x04, 0x12, 0x0C, 0x05, 0x94, 0x94, 0x0A,
+ 0x34, 0x09, 0x14, 0x08, 0x2F, 0x15, 0x19, 0x11,
+ 0x28, 0x0C, 0x0B, 0x94, 0x08, 0xFA, 0x08, 0x7C,
+ 0xBC, 0x15, 0x0A, 0xEC, 0x64, 0xBB, 0x0A, 0x0C,
+ 0x84, 0x2C, 0xA0, 0x15, 0x10, 0x0D, 0x0B, 0x0E,
+ 0x0A, 0x07, 0x10, 0x3C, 0x24, 0x2C, 0x28, 0x5C,
+ 0x0A, 0x0D, 0x0A, 0xC1, 0x22, 0x4C, 0x10, 0x94,
+ 0x04, 0x0F, 0x45, 0x08, 0x31, 0x54, 0x3C, 0xBC,
+ 0x8C, 0x09, 0x3C, 0x18, 0x7C, 0x9C, 0x7C, 0x91,
+ 0x0C, 0x4D, 0x17, 0x74, 0x0C, 0x48, 0x9C, 0x3C,
+ 0x6A, 0xAC, 0x5C, 0xE3, 0x29, 0x3C, 0x2C, 0x7C,
+ 0x6C, 0x04, 0x14, 0xA9, 0x74, 0x07, 0x2C, 0x74,
+ 0x4C, 0x34, 0x97, 0x5C, 0x38, 0x0C, 0x5C, 0x04,
+ 0x0C, 0xBA, 0xBC, 0x78, 0x18, 0x88, 0x24, 0xC2,
+ 0x3C, 0xB4, 0x87, 0x0C, 0x14, 0x4C, 0x3C, 0x10,
+ 0x17, 0x2C, 0x0A, 0x8C, 0x04, 0x1C, 0x44, 0x2C,
+ 0xCD, 0xD8, 0xD4, 0x34, 0x0C, 0x5B, 0xB4, 0x1E,
+ 0x1D, 0xAC, 0x24, 0x18, 0x20, 0x5C, 0xB4, 0x1C,
+ 0x09, 0x14, 0xFC, 0x0C, 0x10, 0xFC, 0x6C, 0x7C,
+ 0xB4, 0x1C, 0x15, 0x17, 0xDB, 0x18, 0x21, 0x24,
+ 0x04, 0x04, 0x44, 0x8C, 0x8C, 0xB7
+};
+
+unsigned char linux_logo[] __initdata = {
+ 0xBF, 0x95, 0x90, 0xCB, 0x95, 0xA1, 0x2C, 0x2C,
+ 0x95, 0x55, 0xCB, 0x90, 0xCB, 0x95, 0x2C, 0x95,
+ 0xCB, 0x47, 0x94, 0x95, 0xA1, 0xD6, 0xD6, 0x2C,
+ 0x90, 0x47, 0x70, 0x2C, 0x6D, 0x2A, 0x6D, 0xD6,
+ 0xA1, 0x2C, 0x55, 0x95, 0x2C, 0x2C, 0x55, 0x55,
+ 0x95, 0xA1, 0xA1, 0xA1, 0x6D, 0xBF, 0x2A, 0x2A,
+ 0xBF, 0x83, 0xBF, 0x95, 0x90, 0xCB, 0x95, 0xA1,
+ 0x2C, 0x2C, 0x95, 0x55, 0xCB, 0x90, 0xCB, 0x95,
+ 0x2C, 0x95, 0xCB, 0x47, 0x94, 0x95, 0xA1, 0xD6,
+ 0xD6, 0x2C, 0x90, 0x47, 0x70, 0x2C, 0x6D, 0x2A,
+ 0x95, 0x47, 0x47, 0x90, 0x2C, 0x2C, 0x2C, 0x95,
+ 0x55, 0x55, 0xCB, 0x90, 0xCB, 0x55, 0x55, 0xCB,
+ 0x47, 0xE6, 0x70, 0x95, 0xD6, 0xD6, 0xA1, 0x2C,
+ 0x55, 0x55, 0x95, 0xD6, 0x6D, 0xD6, 0xA1, 0x2C,
+ 0x2C, 0x95, 0x55, 0x95, 0x95, 0x95, 0x2C, 0x2C,
+ 0xA1, 0xA1, 0x2C, 0x2C, 0xA1, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD6, 0x95, 0x47, 0x47, 0x90, 0x2C, 0x2C,
+ 0x2C, 0x95, 0x55, 0x55, 0xCB, 0x90, 0xCB, 0x55,
+ 0x55, 0xCB, 0x47, 0xE6, 0x70, 0x95, 0xD6, 0xD6,
+ 0xA1, 0x2C, 0x55, 0x55, 0x95, 0xD6, 0x6D, 0xD6,
+ 0x90, 0x47, 0x47, 0x70, 0x2C, 0xA1, 0x2C, 0x95,
+ 0x55, 0x55, 0x90, 0xCB, 0x55, 0x55, 0x55, 0x70,
+ 0x94, 0x70, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C,
+ 0x95, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C,
+ 0x95, 0x55, 0xCB, 0x95, 0xD6, 0xA1, 0x2C, 0x95,
+ 0xA1, 0xD6, 0xD6, 0xA1, 0xA1, 0xD6, 0xA1, 0xA1,
+ 0xA1, 0x2C, 0x90, 0x47, 0x47, 0x70, 0x2C, 0xA1,
+ 0x2C, 0x95, 0x55, 0x55, 0x90, 0xCB, 0x55, 0x55,
+ 0x55, 0x70, 0x94, 0x70, 0x95, 0xA1, 0xD6, 0xD6,
+ 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0xD6, 0xD6, 0xA1,
+ 0x94, 0xA0, 0x47, 0x55, 0x2C, 0xD6, 0xA1, 0x95,
+ 0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0xCB, 0xCB,
+ 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C,
+ 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x95,
+ 0x55, 0x55, 0x2C, 0x3F, 0x80, 0x20, 0x88, 0x88,
+ 0x88, 0x20, 0x88, 0xB1, 0x2C, 0xA1, 0x2C, 0x2C,
+ 0x95, 0xCB, 0x94, 0xA0, 0x47, 0x55, 0x2C, 0xD6,
+ 0xA1, 0x95, 0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55,
+ 0xCB, 0xCB, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6,
+ 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C,
+ 0x55, 0x55, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x95, 0x2C, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x95,
+ 0x55, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x2C, 0x94, 0x80, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x88, 0x92, 0xA1, 0x95,
+ 0x55, 0x90, 0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6,
+ 0xA1, 0x2C, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x95, 0x2C, 0xD6, 0xD6, 0xD6, 0xA1,
+ 0x2C, 0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95,
+ 0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0x95,
+ 0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55, 0x2C, 0x2C,
+ 0xA1, 0xD6, 0xA1, 0xA1, 0x2C, 0x2C, 0x95, 0x55,
+ 0x55, 0x55, 0x95, 0x95, 0x2C, 0x95, 0x95, 0xD6,
+ 0xB1, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x80, 0x34, 0x88, 0x43, 0x47,
+ 0x95, 0xCB, 0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6,
+ 0xA1, 0x95, 0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55,
+ 0x2C, 0x2C, 0xA1, 0xD6, 0xA1, 0xA1, 0xA1, 0x2C,
+ 0x55, 0x55, 0x55, 0x55, 0x2C, 0x95, 0x2C, 0x2C,
+ 0x55, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x55,
+ 0x90, 0x70, 0x90, 0x55, 0x95, 0x95, 0xA1, 0xA1,
+ 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x95, 0x95,
+ 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xD5,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x88, 0x7D, 0x3F, 0xB1, 0x80, 0x20,
+ 0x99, 0x2C, 0x55, 0x55, 0x95, 0x2C, 0xA1, 0xA1,
+ 0x2C, 0x55, 0x90, 0x70, 0x90, 0x55, 0x95, 0x95,
+ 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C,
+ 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1, 0x95, 0xCB,
+ 0x70, 0x94, 0x90, 0x55, 0x95, 0xA1, 0xA1, 0xA1,
+ 0x2C, 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0xA1, 0x88,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0xB1, 0x47, 0xD5, 0x7D, 0x43,
+ 0x20, 0x70, 0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1,
+ 0x95, 0xCB, 0x70, 0x94, 0x90, 0x55, 0x95, 0xA1,
+ 0xA1, 0xA1, 0x2C, 0x95, 0x2C, 0x2C, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95,
+ 0x95, 0x90, 0x55, 0x2C, 0xD6, 0xD6, 0x2C, 0x90,
+ 0x94, 0x70, 0x55, 0x95, 0x2C, 0xD6, 0xD6, 0xA1,
+ 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x95, 0x55, 0x55,
+ 0xCB, 0xCB, 0xCB, 0x55, 0xCB, 0x55, 0x47, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x88, 0xB1, 0x3F, 0x92, 0x2B, 0x80,
+ 0x20, 0x80, 0xD6, 0x70, 0x55, 0x2C, 0xD6, 0xD6,
+ 0x2C, 0x90, 0x94, 0x70, 0x55, 0x95, 0x2C, 0xD6,
+ 0xD6, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x95,
+ 0x95, 0x55, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x55,
+ 0xD6, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x55, 0x70,
+ 0x94, 0x55, 0x95, 0xA1, 0xA1, 0xA1, 0xA1, 0x95,
+ 0x55, 0x55, 0x55, 0x95, 0x55, 0x55, 0xCB, 0x90,
+ 0x70, 0x90, 0xCB, 0x55, 0x55, 0xA1, 0xD8, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x88, 0xD8, 0xE1, 0x88, 0x20, 0x20,
+ 0x88, 0x88, 0xE6, 0x55, 0x2C, 0xA1, 0xD6, 0xA1,
+ 0x55, 0x70, 0x94, 0x55, 0x95, 0xA1, 0xA1, 0xA1,
+ 0xA1, 0x95, 0x55, 0x55, 0x95, 0x95, 0x55, 0x55,
+ 0x90, 0x90, 0x90, 0x90, 0xCB, 0x55, 0x55, 0x55,
+ 0xD6, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0xCB, 0x70,
+ 0x70, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x55,
+ 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x95, 0x2C, 0x95, 0x2C, 0xD6, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x80, 0xD6, 0xA1, 0xD6, 0xD6, 0xA1,
+ 0xCB, 0x70, 0x70, 0x95, 0x2C, 0xA1, 0xA1, 0x2C,
+ 0x2C, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0xD6, 0xA1, 0xA1, 0xA1, 0xA1, 0x55, 0x70, 0x94,
+ 0xCB, 0x95, 0xA1, 0xA1, 0x2C, 0x95, 0xCB, 0x55,
+ 0x90, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x95, 0xA1,
+ 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x95, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x88, 0x95, 0xA1, 0xA1, 0xA1, 0x55,
+ 0x70, 0x94, 0xCB, 0x95, 0xA1, 0xA1, 0x2C, 0x95,
+ 0xCB, 0xCB, 0x90, 0xCB, 0x55, 0x55, 0x55, 0x55,
+ 0x95, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+ 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0xCB, 0x70, 0x70,
+ 0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x70, 0x90, 0xCB,
+ 0xCB, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x2C, 0xD6,
+ 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x70, 0x20, 0x20,
+ 0x88, 0x43, 0xD8, 0x43, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x88, 0x88, 0x43, 0x2B, 0xD8, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x3F, 0x2C, 0x95, 0x95, 0xCB,
+ 0x70, 0x70, 0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x90,
+ 0x90, 0xCB, 0x55, 0xCB, 0x55, 0xCB, 0x55, 0x95,
+ 0x2C, 0xD6, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C,
+ 0xA1, 0x95, 0x95, 0x55, 0xCB, 0x70, 0x90, 0x55,
+ 0x2C, 0x2C, 0x2C, 0x55, 0x70, 0x70, 0x55, 0x95,
+ 0x95, 0xCB, 0x90, 0x90, 0x90, 0x95, 0x2C, 0xA1,
+ 0xD6, 0xD6, 0x2C, 0x2C, 0x95, 0x70, 0x20, 0x20,
+ 0x80, 0x2B, 0x34, 0x2B, 0x88, 0x20, 0x20, 0x20,
+ 0x88, 0xB1, 0x28, 0x28, 0x2B, 0x7D, 0x80, 0x20,
+ 0x20, 0x20, 0x20, 0x92, 0x95, 0x55, 0xCB, 0x70,
+ 0x90, 0x55, 0x2C, 0x2C, 0x2C, 0x55, 0x70, 0x70,
+ 0x55, 0x95, 0x55, 0x55, 0x90, 0x90, 0x90, 0x55,
+ 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x95,
+ 0xA1, 0x95, 0x55, 0xCB, 0x90, 0x70, 0xCB, 0x95,
+ 0xA1, 0x95, 0x95, 0xCB, 0x90, 0xCB, 0x95, 0x2C,
+ 0x95, 0x70, 0x70, 0x90, 0x55, 0x2C, 0xA1, 0xA1,
+ 0x2C, 0x2C, 0x55, 0xCB, 0x55, 0x90, 0x20, 0x34,
+ 0x90, 0x6D, 0x70, 0xD8, 0x43, 0x20, 0x20, 0x88,
+ 0x3F, 0x55, 0xA1, 0x2A, 0xD6, 0x7D, 0x43, 0x20,
+ 0x20, 0x20, 0x88, 0x7D, 0x55, 0xCB, 0x90, 0x70,
+ 0xCB, 0x95, 0xA1, 0x95, 0x95, 0xCB, 0x70, 0xCB,
+ 0x95, 0xA1, 0x95, 0x70, 0x70, 0xCB, 0x55, 0x2C,
+ 0xA1, 0xA1, 0xA1, 0x95, 0x55, 0x55, 0x55, 0x95,
+ 0x2C, 0x55, 0x90, 0x70, 0x94, 0x90, 0x95, 0x2C,
+ 0x2C, 0x95, 0xCB, 0x90, 0x55, 0x95, 0xA1, 0xA1,
+ 0x95, 0x90, 0x90, 0x95, 0xA1, 0xD6, 0xD6, 0x6D,
+ 0xA1, 0x95, 0x55, 0xCB, 0x55, 0xCB, 0x20, 0x99,
+ 0xBF, 0xA3, 0xA3, 0x90, 0x20, 0x20, 0x20, 0x92,
+ 0x83, 0x6B, 0x6B, 0x6B, 0xA3, 0x70, 0x88, 0x20,
+ 0x20, 0x20, 0x20, 0x2B, 0x90, 0x70, 0x94, 0x90,
+ 0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x90, 0x55, 0x95,
+ 0xA1, 0x2C, 0x55, 0x90, 0x90, 0x95, 0xA1, 0xD6,
+ 0xD6, 0x6D, 0xA1, 0x95, 0x55, 0xCB, 0x55, 0x55,
+ 0x2C, 0x55, 0x70, 0x70, 0x94, 0x90, 0x95, 0x2C,
+ 0x2C, 0x55, 0xCB, 0xCB, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x55, 0x55, 0x95, 0xA1, 0x6D, 0xBF, 0x6D, 0xD6,
+ 0x95, 0x55, 0x90, 0xCB, 0x55, 0x95, 0x88, 0x95,
+ 0x2C, 0x3F, 0x6D, 0x6B, 0x34, 0x20, 0x20, 0x47,
+ 0x65, 0xD6, 0xE1, 0x3F, 0x2A, 0x6B, 0x2B, 0x20,
+ 0x20, 0x20, 0x20, 0x43, 0x70, 0x70, 0x94, 0x90,
+ 0x95, 0x2C, 0x2C, 0x55, 0x55, 0x55, 0x95, 0x2C,
+ 0xA1, 0x2C, 0x55, 0xCB, 0x95, 0xA1, 0x6D, 0xBF,
+ 0x6D, 0xD6, 0x2C, 0x55, 0x90, 0xCB, 0x95, 0x95,
+ 0x95, 0x55, 0x70, 0x94, 0x70, 0x55, 0x2C, 0xA1,
+ 0x2C, 0x55, 0xCB, 0x55, 0x2C, 0x95, 0x2C, 0x95,
+ 0x95, 0x95, 0xA1, 0x6D, 0xBF, 0x2A, 0xD6, 0x95,
+ 0x70, 0x94, 0x94, 0x70, 0x55, 0x55, 0x20, 0xBF,
+ 0xC9, 0xB1, 0x99, 0x42, 0xB1, 0x61, 0x7D, 0x94,
+ 0x65, 0xB1, 0x88, 0x99, 0xD5, 0xE5, 0x7F, 0x20,
+ 0x20, 0x20, 0x20, 0x43, 0x70, 0x94, 0x70, 0x55,
+ 0x2C, 0xA1, 0x2C, 0x55, 0x90, 0x55, 0x2C, 0x95,
+ 0x2C, 0x95, 0x95, 0x2C, 0xA1, 0x6D, 0xBF, 0xBF,
+ 0xD6, 0x55, 0x70, 0x94, 0x94, 0x70, 0xCB, 0x55,
+ 0x55, 0xCB, 0x70, 0x94, 0x70, 0x95, 0xA1, 0xA1,
+ 0x95, 0x55, 0x55, 0x95, 0x2C, 0x95, 0x95, 0x95,
+ 0x95, 0xA1, 0x6D, 0x2A, 0x2A, 0xD6, 0x55, 0x94,
+ 0xE6, 0xE6, 0x47, 0x70, 0x55, 0x95, 0x20, 0x2A,
+ 0xD8, 0x43, 0xC9, 0x83, 0x98, 0x79, 0x34, 0x9F,
+ 0x6B, 0x43, 0x20, 0x88, 0x2B, 0x65, 0xA0, 0x20,
+ 0x20, 0x20, 0x20, 0xE1, 0x70, 0x94, 0x70, 0x95,
+ 0xA1, 0xA1, 0x95, 0x55, 0x55, 0x95, 0x2C, 0x95,
+ 0x95, 0x95, 0x95, 0xA1, 0x6D, 0xBF, 0x2A, 0xD6,
+ 0x55, 0x94, 0xE6, 0xE6, 0x47, 0x70, 0x55, 0x55,
+ 0x94, 0x70, 0x94, 0x47, 0x70, 0x95, 0x2C, 0x2C,
+ 0x95, 0xCB, 0x95, 0x2C, 0x2C, 0xA1, 0x2C, 0x2C,
+ 0xA1, 0xD6, 0x6D, 0x6D, 0xA1, 0xCB, 0x47, 0x28,
+ 0xE6, 0x47, 0x70, 0x55, 0x95, 0xA1, 0x20, 0x2C,
+ 0x7F, 0x88, 0xF0, 0xC6, 0x25, 0x5E, 0xCF, 0x2F,
+ 0xE7, 0x9A, 0x20, 0x88, 0x99, 0x65, 0x3F, 0x20,
+ 0x20, 0x20, 0x20, 0x34, 0x94, 0x47, 0x70, 0x95,
+ 0xA1, 0x2C, 0x55, 0xCB, 0x95, 0x2C, 0x2C, 0xA1,
+ 0x2C, 0x2C, 0xA1, 0xD6, 0x6D, 0x6D, 0xA1, 0xCB,
+ 0x94, 0x28, 0xA0, 0x47, 0x70, 0x55, 0x95, 0x95,
+ 0x47, 0x70, 0x90, 0x94, 0x70, 0x95, 0xA1, 0x2C,
+ 0x55, 0x55, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C,
+ 0xA1, 0x6D, 0x2A, 0xD6, 0x55, 0x47, 0x28, 0x28,
+ 0x47, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0x20, 0x28,
+ 0xEC, 0x86, 0xBE, 0x48, 0x3E, 0x3E, 0x3A, 0x25,
+ 0x4E, 0xAE, 0x93, 0xD7, 0xEC, 0xD1, 0x34, 0x20,
+ 0x20, 0x20, 0x20, 0x43, 0x55, 0x94, 0x70, 0x95,
+ 0xA1, 0xA1, 0x55, 0xCB, 0x2C, 0xA1, 0xA1, 0xA1,
+ 0xA1, 0x2C, 0xA1, 0x6D, 0x6D, 0xD6, 0x55, 0x47,
+ 0x28, 0x28, 0x47, 0x70, 0x55, 0x95, 0x2C, 0x2C,
+ 0x95, 0x95, 0x55, 0x90, 0xCB, 0x2C, 0xA1, 0xA1,
+ 0x55, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0xA1, 0x2C,
+ 0xD6, 0x6D, 0x6D, 0xA1, 0x70, 0x28, 0xD5, 0xE6,
+ 0x70, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0x20, 0xE1,
+ 0x26, 0x84, 0x76, 0x73, 0x9C, 0x22, 0x4E, 0x35,
+ 0x8C, 0x7A, 0x4E, 0xDC, 0x8E, 0x7E, 0x3D, 0x88,
+ 0x20, 0x20, 0x20, 0x88, 0x2C, 0x90, 0x90, 0x95,
+ 0xA1, 0x2C, 0x55, 0x55, 0x2C, 0xD6, 0xD6, 0xD6,
+ 0x2C, 0x2C, 0xD6, 0x2A, 0x6D, 0x2C, 0x70, 0x28,
+ 0xD5, 0xE6, 0x70, 0x55, 0x95, 0xA1, 0x2C, 0xA1,
+ 0xBF, 0xA1, 0x95, 0xCB, 0xCB, 0x2C, 0xA1, 0xA1,
+ 0x95, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C, 0x95,
+ 0xD6, 0x6D, 0xD6, 0x95, 0x94, 0x28, 0xE6, 0x70,
+ 0x55, 0x95, 0xA1, 0xA1, 0xA1, 0xD6, 0x20, 0x57,
+ 0xE4, 0xDF, 0x50, 0x3E, 0x22, 0x4E, 0x35, 0x8C,
+ 0x8C, 0x52, 0x52, 0x7A, 0x4E, 0x58, 0xD7, 0x20,
+ 0x20, 0x20, 0x20, 0x88, 0x2C, 0xCB, 0x55, 0x2C,
+ 0xA1, 0xA1, 0x95, 0x95, 0xA1, 0xD6, 0xD6, 0xA1,
+ 0x2C, 0x95, 0xA1, 0x6D, 0x6D, 0x95, 0x47, 0xA0,
+ 0xE6, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0xA1,
+ 0xD2, 0x95, 0x55, 0x90, 0x55, 0x2C, 0xD6, 0xA1,
+ 0x95, 0x95, 0xA1, 0xD6, 0xD6, 0x2C, 0x95, 0x2C,
+ 0xA1, 0x6D, 0xA1, 0x55, 0x94, 0x47, 0x94, 0xCB,
+ 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6, 0x59, 0xC8,
+ 0xE3, 0x76, 0x2D, 0x3E, 0x22, 0x4E, 0x8C, 0x35,
+ 0x52, 0x52, 0xEE, 0x3A, 0x4D, 0xED, 0x24, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x28, 0xCB, 0x55, 0x2C,
+ 0xD6, 0xA1, 0x95, 0x95, 0xA1, 0xD6, 0xA1, 0x2C,
+ 0x95, 0x2C, 0xD6, 0x6D, 0xA1, 0x55, 0x94, 0xE6,
+ 0x70, 0xCB, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xA1,
+ 0xD0, 0x94, 0x94, 0x90, 0x55, 0x2C, 0xA1, 0xA1,
+ 0x55, 0x95, 0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x2C,
+ 0xA1, 0xD6, 0x2C, 0x70, 0x94, 0x94, 0x94, 0x94,
+ 0x70, 0x55, 0xA1, 0xD6, 0xA1, 0xD6, 0x88, 0x77,
+ 0x38, 0xC4, 0x3E, 0x69, 0x4E, 0x35, 0x8C, 0xEE,
+ 0x35, 0x89, 0x30, 0x30, 0x4A, 0x48, 0x3C, 0x20,
+ 0x20, 0x88, 0x20, 0x20, 0xD8, 0x2C, 0x55, 0x2C,
+ 0xD6, 0xA1, 0x95, 0x95, 0x2C, 0xD6, 0xA1, 0x2C,
+ 0x95, 0x2C, 0xA1, 0xD6, 0x2C, 0x90, 0x94, 0x47,
+ 0x94, 0x94, 0x70, 0x55, 0x2C, 0xD6, 0xA1, 0x95,
+ 0x95, 0x28, 0x47, 0x90, 0x95, 0x2C, 0xA1, 0x2C,
+ 0x95, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C,
+ 0xA1, 0xA1, 0x55, 0x70, 0x94, 0x47, 0x94, 0x94,
+ 0x70, 0x2C, 0xD6, 0xD6, 0x2C, 0xA1, 0x43, 0x98,
+ 0x54, 0x48, 0x3E, 0x22, 0x35, 0xEE, 0xEE, 0x9C,
+ 0x4D, 0x45, 0x75, 0x4A, 0xDF, 0x7B, 0x3D, 0x20,
+ 0xD8, 0x28, 0x2B, 0x88, 0x20, 0x95, 0x95, 0x2C,
+ 0xA1, 0x2C, 0x55, 0x55, 0x2C, 0xA1, 0xD6, 0xA1,
+ 0x2C, 0x95, 0xA1, 0x2C, 0x55, 0x70, 0x94, 0x94,
+ 0x94, 0x94, 0x70, 0x95, 0xD6, 0xD6, 0x2C, 0x95,
+ 0x70, 0x28, 0x47, 0x55, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x95, 0x95, 0x95, 0xA1, 0xA1, 0xA1, 0x95, 0x55,
+ 0x95, 0x95, 0x55, 0x70, 0x70, 0x70, 0x94, 0x70,
+ 0x55, 0xD6, 0x6D, 0xD6, 0x95, 0x2C, 0x20, 0x43,
+ 0xBB, 0xC8, 0x36, 0x30, 0x30, 0x38, 0x45, 0x6E,
+ 0xE3, 0x75, 0x78, 0x37, 0xBD, 0xD9, 0x3F, 0x20,
+ 0x88, 0xD5, 0x70, 0xB1, 0x88, 0xA0, 0x95, 0x2C,
+ 0x2C, 0xA1, 0x95, 0x55, 0x95, 0xA1, 0xA1, 0xA1,
+ 0x2C, 0x55, 0x95, 0x2C, 0x55, 0x70, 0x70, 0x70,
+ 0x94, 0x70, 0x55, 0xD6, 0x6D, 0x6D, 0x95, 0x55,
+ 0x94, 0x47, 0x70, 0x95, 0x2C, 0x2C, 0x2C, 0xA1,
+ 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x55,
+ 0x55, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0x95,
+ 0xA1, 0x6D, 0x4B, 0xD6, 0x55, 0xD6, 0x20, 0xD8,
+ 0xD6, 0x67, 0xDA, 0x4D, 0xED, 0x62, 0x78, 0x78,
+ 0x23, 0x84, 0x67, 0xF5, 0x4B, 0xBF, 0x90, 0x88,
+ 0x88, 0x2B, 0x47, 0x99, 0x20, 0x43, 0xD6, 0x2C,
+ 0x2C, 0xA1, 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1,
+ 0x95, 0x95, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x95, 0xD6, 0x6D, 0xBF, 0xD6, 0x55, 0xCB,
+ 0x55, 0x55, 0x55, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+ 0x2C, 0x2C, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x95,
+ 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+ 0x6D, 0x2A, 0x2A, 0xA1, 0x55, 0x55, 0x20, 0xD8,
+ 0x6D, 0xAB, 0x96, 0x7E, 0x64, 0x53, 0x36, 0x36,
+ 0xC6, 0x63, 0x6D, 0xD0, 0x6B, 0xE5, 0xA3, 0x7D,
+ 0x20, 0x88, 0x80, 0x88, 0x20, 0x20, 0xC9, 0xA1,
+ 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0xA1, 0xA1, 0xA1,
+ 0x95, 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x2C, 0xA1, 0x6D, 0xBF, 0x6D, 0xA1, 0x55, 0x55,
+ 0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0xA1,
+ 0xA1, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x95,
+ 0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xD6,
+ 0x6D, 0x6D, 0xA1, 0x55, 0x2C, 0xD8, 0x20, 0xB1,
+ 0xA3, 0x4B, 0x6D, 0xD9, 0xA7, 0x6C, 0xAF, 0xB2,
+ 0x6D, 0x2A, 0x83, 0x42, 0xE5, 0xE5, 0x65, 0x2C,
+ 0x20, 0x20, 0x88, 0x20, 0x20, 0x20, 0x88, 0x95,
+ 0x2C, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x2C, 0x95, 0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1,
+ 0xD6, 0xD6, 0x6D, 0x6D, 0xA1, 0x55, 0xCB, 0x55,
+ 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x95, 0x2C,
+ 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95,
+ 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xA1,
+ 0xA1, 0x2C, 0x55, 0x55, 0x28, 0x88, 0x43, 0x2A,
+ 0xE5, 0xA3, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+ 0xBF, 0xA3, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0x65,
+ 0xB1, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xD8,
+ 0xD6, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x2C,
+ 0x95, 0x95, 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1,
+ 0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x90, 0x90, 0x55,
+ 0x90, 0xCB, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x2C, 0x2C, 0x95, 0x55, 0x95, 0x95, 0x95, 0x55,
+ 0x55, 0xCB, 0x55, 0x2C, 0x95, 0x95, 0x95, 0x95,
+ 0x55, 0x90, 0x90, 0x90, 0xE1, 0x43, 0x28, 0xE5,
+ 0xE5, 0x65, 0xD0, 0x6D, 0x6D, 0x6D, 0x2A, 0xD2,
+ 0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xD6, 0x20, 0x20, 0x20, 0x20, 0x20, 0x88, 0x88,
+ 0xD5, 0x2C, 0x2C, 0x2C, 0x95, 0x55, 0x95, 0x95,
+ 0x95, 0x55, 0x55, 0xCB, 0x55, 0x95, 0x2C, 0x95,
+ 0x95, 0x95, 0x55, 0x90, 0x70, 0x70, 0x70, 0x90,
+ 0x70, 0x70, 0xCB, 0x55, 0x55, 0x95, 0x95, 0x95,
+ 0x2C, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0xCB,
+ 0x70, 0x70, 0x70, 0xCB, 0x90, 0x90, 0x70, 0x94,
+ 0x94, 0x94, 0x2C, 0x80, 0x20, 0xE1, 0xA3, 0xE5,
+ 0xE5, 0xE5, 0x42, 0xEC, 0xD0, 0x83, 0xA3, 0x65,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0x65, 0x7D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x88, 0x2C, 0x95, 0x95, 0x95, 0x55, 0x55, 0x55,
+ 0x55, 0xCB, 0x70, 0x70, 0x90, 0x90, 0x90, 0x90,
+ 0x70, 0x94, 0x94, 0x94, 0x70, 0x70, 0x70, 0x70,
+ 0x70, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95, 0x95,
+ 0x2C, 0x2C, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x90, 0x70, 0x90, 0x55, 0x55, 0xCB, 0x70, 0x94,
+ 0x94, 0x95, 0xD8, 0x20, 0x88, 0x70, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0xE1, 0x6D, 0x2C, 0x95, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x90, 0x70, 0x70, 0x55, 0x55, 0xCB,
+ 0x70, 0x94, 0x94, 0x94, 0x70, 0x90, 0x70, 0x94,
+ 0x55, 0x2C, 0x2C, 0x2C, 0x95, 0x2C, 0x95, 0x95,
+ 0x2C, 0x2C, 0x2C, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0xCB, 0xCB, 0x95, 0x2C, 0x2C, 0x95, 0x55, 0x90,
+ 0x55, 0x99, 0x20, 0x20, 0xE1, 0xA3, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xD6, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2B, 0x6D, 0x95, 0x95, 0x55, 0x55,
+ 0x55, 0x55, 0xCB, 0x55, 0x95, 0x2C, 0x2C, 0x95,
+ 0x55, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x90, 0x70,
+ 0x2C, 0xD6, 0xD6, 0x2C, 0x2C, 0x95, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95,
+ 0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x95, 0x55, 0x95,
+ 0xE6, 0x88, 0x20, 0x20, 0x3F, 0xA3, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0x42, 0xA3, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x88, 0x2B, 0xD6, 0x95, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x95,
+ 0x55, 0x55, 0x95, 0x95, 0x95, 0x55, 0x55, 0x55,
+ 0xA1, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x2C,
+ 0x2C, 0x2C, 0x95, 0x2C, 0x95, 0x95, 0x55, 0x95,
+ 0x95, 0x2C, 0x2C, 0x2C, 0x95, 0xCB, 0xCB, 0x94,
+ 0x20, 0x20, 0x20, 0x20, 0xE6, 0x83, 0x65, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0x6B, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0x6B, 0xA3, 0xD2,
+ 0xD2, 0x6B, 0xC9, 0x20, 0x20, 0x88, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x88, 0x8A, 0xA1, 0x95, 0x95,
+ 0x95, 0x55, 0x95, 0x2C, 0xA1, 0x2C, 0x95, 0xCB,
+ 0xCB, 0x55, 0x95, 0x95, 0x95, 0x55, 0x55, 0x95,
+ 0x6D, 0x6D, 0x6D, 0xD6, 0xA1, 0x2C, 0x2C, 0x95,
+ 0x2C, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x55, 0x70, 0x70, 0x2C, 0x80,
+ 0x88, 0x20, 0x20, 0x80, 0x94, 0xD6, 0x32, 0x6B,
+ 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xA3, 0xD2, 0xD0, 0xBF, 0x2A,
+ 0x2A, 0xD0, 0x6D, 0x34, 0x20, 0xE1, 0x88, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x88, 0xA1, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x55, 0x70, 0x70,
+ 0x70, 0x90, 0xCB, 0xCB, 0xCB, 0x95, 0x95, 0x2C,
+ 0xD0, 0x6D, 0xD6, 0xD6, 0xA1, 0xA1, 0xA1, 0x2C,
+ 0x2C, 0x2C, 0x2C, 0x95, 0x55, 0x55, 0x55, 0x95,
+ 0x95, 0x2C, 0x95, 0x55, 0xCB, 0xCB, 0x95, 0x88,
+ 0x20, 0x20, 0x88, 0xD8, 0x2C, 0xD1, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x65, 0x65, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0xEC,
+ 0xBF, 0x2A, 0xEC, 0x95, 0x20, 0x34, 0x2B, 0xE1,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x99, 0x95, 0x55,
+ 0x55, 0x55, 0x95, 0x95, 0x95, 0x55, 0xCB, 0xCB,
+ 0x55, 0x55, 0xCB, 0xCB, 0xCB, 0x55, 0x95, 0x95,
+ 0x32, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C,
+ 0xA1, 0x95, 0x95, 0x95, 0x55, 0xCB, 0xCB, 0x55,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x55, 0x99, 0x20,
+ 0xE1, 0xE1, 0x43, 0x47, 0x6B, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0x42, 0xEC, 0xBF, 0xA3, 0x8A, 0x20, 0x88, 0xD8,
+ 0x2B, 0x20, 0x20, 0x20, 0x88, 0x88, 0x2C, 0xCB,
+ 0xCB, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x55, 0x95,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x95, 0x55, 0x95,
+ 0x6D, 0x55, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x95,
+ 0x2C, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0xA1, 0x34, 0x20,
+ 0xC9, 0x20, 0xE1, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xA3, 0x83, 0x6D, 0x20, 0x88, 0x88,
+ 0x2B, 0x34, 0x20, 0x20, 0x20, 0x88, 0xD5, 0x55,
+ 0x55, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x55, 0x55, 0x95, 0x95,
+ 0x2C, 0x55, 0xCB, 0x55, 0xCB, 0x55, 0x55, 0x95,
+ 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0x2C, 0x95, 0x95, 0x55, 0x95, 0x2C, 0x20, 0xD8,
+ 0xE1, 0x20, 0x70, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x65, 0xA3, 0x92, 0x43, 0x7D,
+ 0xD8, 0xC9, 0x88, 0x20, 0x20, 0x20, 0x43, 0xD6,
+ 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x55, 0x95, 0x2C,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95, 0x2C,
+ 0xA1, 0x55, 0x55, 0x55, 0x55, 0x95, 0x95, 0x55,
+ 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0xA1, 0x2C,
+ 0xA1, 0x2C, 0x2C, 0x95, 0x2C, 0x99, 0x88, 0xB1,
+ 0x20, 0xD8, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x34, 0x8A,
+ 0xC9, 0x34, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x90,
+ 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x95, 0x95, 0x2C,
+ 0x2C, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+ 0xD6, 0x2C, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x55, 0xCB, 0x55, 0x2C, 0x2C, 0xA1, 0x2C, 0xA1,
+ 0xA1, 0xA1, 0x2C, 0x2C, 0x6D, 0x43, 0xD8, 0x80,
+ 0x88, 0xCB, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x32, 0x80, 0xE1,
+ 0x80, 0x20, 0xB1, 0x20, 0x20, 0x20, 0x20, 0xC9,
+ 0xD6, 0xA1, 0xA1, 0xA1, 0x2C, 0xA1, 0x2C, 0x2C,
+ 0x2C, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95, 0x55,
+ 0xD6, 0x95, 0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x2C,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95, 0x2C,
+ 0x2C, 0x2C, 0x2C, 0x95, 0xCB, 0x20, 0xC9, 0x20,
+ 0xE1, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xD8, 0x20,
+ 0x20, 0x20, 0x2B, 0x43, 0x20, 0x20, 0x20, 0x88,
+ 0xD6, 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x55,
+ 0x95, 0x55, 0x55, 0xCB, 0x55, 0xCB, 0xCB, 0x55,
+ 0x2C, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0x95,
+ 0x55, 0x95, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x55, 0xCB, 0x70, 0xCB, 0xC9, 0x80, 0x2B, 0x20,
+ 0xA0, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x92, 0x20,
+ 0x20, 0x20, 0xE1, 0xD8, 0x20, 0x20, 0x20, 0x20,
+ 0x95, 0x95, 0x55, 0xCB, 0x90, 0x90, 0x70, 0x90,
+ 0x90, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x55, 0x95,
+ 0x95, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x95, 0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x55,
+ 0x90, 0x47, 0xA0, 0x55, 0x20, 0x2B, 0x43, 0x88,
+ 0x6D, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x28, 0x20,
+ 0x20, 0x20, 0xE1, 0xE1, 0x20, 0x20, 0x20, 0x20,
+ 0x28, 0x55, 0x90, 0x47, 0xA0, 0x47, 0x94, 0x70,
+ 0x55, 0x95, 0x95, 0x55, 0xCB, 0x55, 0x55, 0x2C,
+ 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x55,
+ 0x94, 0xE6, 0x70, 0x2B, 0x88, 0x2B, 0x88, 0xE1,
+ 0x65, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x47, 0x20,
+ 0x20, 0x20, 0xE1, 0x34, 0x20, 0x20, 0x20, 0x20,
+ 0xB1, 0x95, 0x94, 0xE6, 0xA0, 0x47, 0x70, 0x55,
+ 0x2C, 0xA1, 0x2C, 0x55, 0x90, 0xCB, 0x2C, 0xD6,
+ 0x6D, 0xA1, 0x2C, 0x95, 0x95, 0xA1, 0x2C, 0xA1,
+ 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x55,
+ 0x70, 0xE6, 0x70, 0x20, 0x20, 0x7D, 0x20, 0x8A,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x65, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x94, 0x20,
+ 0x20, 0x20, 0xD8, 0x88, 0x20, 0x20, 0x20, 0x20,
+ 0xD8, 0x2C, 0x94, 0x47, 0x47, 0x90, 0x95, 0x95,
+ 0xA1, 0x6D, 0xA1, 0x90, 0x94, 0x55, 0x2C, 0xD6,
+ 0xD0, 0xA1, 0x95, 0x95, 0x2C, 0x2C, 0xA1, 0x2C,
+ 0x95, 0x95, 0x55, 0x55, 0x55, 0x95, 0x2C, 0x2C,
+ 0xCB, 0x95, 0xD8, 0x20, 0x20, 0xB1, 0x88, 0x28,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE2, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20,
+ 0x20, 0x20, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x88, 0xD6, 0x55, 0x47, 0x94, 0x55, 0x2C, 0xA1,
+ 0xA1, 0xD6, 0x95, 0x94, 0x94, 0x55, 0xD6, 0x6D,
+ 0xBF, 0x95, 0x90, 0xCB, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0x55, 0x95, 0xCB, 0x90, 0x90, 0x95, 0x2C, 0x95,
+ 0x90, 0x70, 0x20, 0x20, 0x34, 0x8A, 0x20, 0x94,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20,
+ 0x20, 0x88, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x88, 0xD6, 0xCB, 0x47, 0x94, 0x55, 0xA1, 0xD6,
+ 0xD6, 0x2C, 0xCB, 0x47, 0x70, 0xA1, 0x6D, 0x2A,
+ 0x95, 0x47, 0x47, 0x70, 0x95, 0xA1, 0x2C, 0x95,
+ 0x55, 0x55, 0x90, 0x90, 0x55, 0x55, 0x55, 0x90,
+ 0x47, 0xD5, 0x20, 0x20, 0x80, 0xD5, 0x43, 0xCB,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20,
+ 0x20, 0x80, 0x34, 0x20, 0x20, 0x20, 0x88, 0x20,
+ 0x20, 0x2C, 0x47, 0xE6, 0x70, 0x2C, 0xD6, 0xD6,
+ 0xA1, 0x2C, 0x55, 0xCB, 0x95, 0xA1, 0x6D, 0xD6,
+ 0x90, 0x47, 0x47, 0x90, 0x2C, 0xA1, 0x2C, 0x95,
+ 0x55, 0x55, 0x90, 0x90, 0x55, 0x55, 0x55, 0x70,
+ 0x94, 0x8A, 0x20, 0x88, 0x88, 0xE1, 0xD8, 0x95,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE2, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x47, 0x20,
+ 0x43, 0x7D, 0x43, 0x80, 0x88, 0x20, 0x20, 0x20,
+ 0x88, 0xCB, 0x94, 0x70, 0x55, 0xA1, 0xD6, 0xD6,
+ 0xA1, 0x2C, 0x2C, 0x95, 0xA1, 0xA1, 0xD6, 0xA1,
+ 0x94, 0xE6, 0x47, 0x55, 0x2C, 0xD6, 0xA1, 0x95,
+ 0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0xCB, 0xCB,
+ 0x55, 0xA0, 0x43, 0x86, 0x86, 0x43, 0xD8, 0xCB,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x3F, 0x80,
+ 0xD8, 0x80, 0x88, 0x34, 0xD8, 0x2B, 0xD8, 0x20,
+ 0x99, 0x90, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6,
+ 0xA1, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C,
+ 0x55, 0x55, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x95, 0x44, 0xBC, 0x3E, 0x5D, 0xD3, 0x79, 0x92,
+ 0xA3, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x65, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0x9A, 0x34,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x99, 0xE1,
+ 0x70, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xD6, 0xA1,
+ 0x2C, 0x95, 0x55, 0x55, 0x95, 0x95, 0x95, 0x95,
+ 0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0x95,
+ 0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55, 0x2C, 0x2C,
+ 0x32, 0x9D, 0xEB, 0x5D, 0x69, 0x49, 0x84, 0xF0,
+ 0xB1, 0xEC, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xC1, 0x4E, 0x21, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0xC9, 0xD8,
+ 0xBB, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C,
+ 0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C,
+ 0x55, 0xCB, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x55,
+ 0x90, 0x70, 0x90, 0x55, 0x95, 0x95, 0x6D, 0xD0,
+ 0xC2, 0x48, 0x6A, 0x49, 0x69, 0x82, 0x5D, 0x2F,
+ 0x59, 0x7D, 0xBF, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xEA, 0xC7, 0x7E, 0x66,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x43, 0x5A,
+ 0x46, 0x27, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x95,
+ 0x95, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1, 0x95, 0x55,
+ 0x94, 0x94, 0x2C, 0x2A, 0x72, 0x3B, 0x56, 0xDD,
+ 0xDF, 0x29, 0x5D, 0x49, 0x89, 0x5D, 0x3E, 0x69,
+ 0x93, 0x66, 0x34, 0xA1, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x65, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xEA, 0x3E, 0x5A, 0x66,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x5B, 0x73,
+ 0x89, 0x4C, 0xBF, 0x2C, 0x95, 0x2C, 0x2C, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x2C, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0x2C, 0xCB,
+ 0x70, 0x55, 0xE7, 0x60, 0x4A, 0x48, 0xCD, 0x4A,
+ 0x29, 0x73, 0x5D, 0x82, 0x49, 0x49, 0x49, 0x49,
+ 0x3A, 0x57, 0x88, 0x88, 0x70, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0x42, 0x73, 0x50, 0xBE, 0x79,
+ 0x20, 0x20, 0x20, 0x20, 0x66, 0xCC, 0x37, 0x9C,
+ 0x3E, 0xCE, 0xBF, 0x95, 0x95, 0x95, 0x2C, 0x95,
+ 0x95, 0x55, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0x55,
+ 0xA1, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x55, 0x94,
+ 0x94, 0xE8, 0x60, 0xC4, 0x3E, 0x2D, 0x2D, 0x2D,
+ 0x33, 0x5D, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x89, 0xAA, 0x59, 0x20, 0x20, 0x28, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xEC, 0x4A, 0x2D, 0x50, 0x78, 0x2E,
+ 0x57, 0x51, 0xF0, 0x57, 0x31, 0x4D, 0x50, 0x2D,
+ 0x5D, 0xF2, 0xA1, 0x2C, 0x95, 0x95, 0x55, 0x55,
+ 0x90, 0x90, 0x70, 0x90, 0xCB, 0x55, 0x55, 0x55,
+ 0x6D, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0x55, 0x94,
+ 0x70, 0xB9, 0x75, 0x50, 0x3E, 0x49, 0x49, 0x49,
+ 0x5D, 0x82, 0x49, 0x49, 0x82, 0x49, 0x49, 0x49,
+ 0x89, 0x69, 0x4F, 0x20, 0x20, 0x20, 0x8A, 0x42,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0x83, 0x4A, 0x3A, 0x50, 0x62, 0x23,
+ 0x81, 0xB8, 0xB8, 0xE9, 0x5F, 0x29, 0x33, 0x5D,
+ 0x5D, 0x73, 0xE8, 0xCB, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0xD6, 0xA1, 0xA1, 0xA1, 0xA1, 0x55, 0x70, 0x70,
+ 0xCB, 0x68, 0x75, 0x50, 0x82, 0x49, 0x49, 0x49,
+ 0x5D, 0x49, 0x49, 0x5D, 0x49, 0x49, 0x5D, 0x82,
+ 0x69, 0x5D, 0x25, 0xF0, 0x20, 0x20, 0x20, 0xE1,
+ 0x2A, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0x4B, 0xF4, 0xDF, 0x50, 0x73, 0x76, 0x48,
+ 0x75, 0xDF, 0x75, 0x62, 0xC4, 0x33, 0x82, 0x49,
+ 0x5D, 0x5D, 0xA8, 0xF5, 0x55, 0x55, 0x55, 0x55,
+ 0x2C, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+ 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0xCB, 0x70, 0x70,
+ 0x95, 0x83, 0x5F, 0xEA, 0x2D, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x5D, 0x49, 0x22, 0x5A, 0x79, 0x20, 0x20, 0x20,
+ 0x80, 0xD2, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0x65, 0xD0, 0x63, 0x5F, 0x29, 0x2D, 0x2D, 0xEA,
+ 0x29, 0x29, 0x76, 0x50, 0x2D, 0x82, 0x49, 0x49,
+ 0x3E, 0x49, 0x5C, 0xB0, 0xBA, 0x95, 0x55, 0x55,
+ 0x2C, 0xA1, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C,
+ 0xA1, 0x95, 0x95, 0x55, 0xCB, 0x70, 0x70, 0x55,
+ 0x2C, 0x83, 0x60, 0x76, 0x5D, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x5D, 0x89, 0xDC, 0x8B, 0x20, 0x20, 0x20,
+ 0x20, 0x95, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE2, 0x32, 0x85, 0xE3, 0x29, 0x2D, 0x33, 0x2D,
+ 0x2D, 0x2D, 0x6A, 0x2D, 0x33, 0x5D, 0x49, 0x82,
+ 0x49, 0x49, 0x82, 0x73, 0x5C, 0x9E, 0x2C, 0x55,
+ 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x95,
+ 0x2C, 0x95, 0x55, 0xCB, 0x90, 0x90, 0xCB, 0x95,
+ 0x2C, 0x6D, 0x41, 0x6F, 0x3E, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x82, 0x3E, 0x4E, 0x38, 0xCA, 0x20, 0x20,
+ 0x20, 0x55, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x65,
+ 0x42, 0xA0, 0xD4, 0xE3, 0x29, 0x2D, 0x82, 0x5D,
+ 0x5D, 0x82, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x3E, 0x49, 0x49, 0x49, 0x5C, 0x56, 0xD6,
+ 0xA1, 0xA1, 0xA1, 0x95, 0x55, 0x55, 0x55, 0x95,
+ 0xA1, 0x55, 0x90, 0x70, 0x94, 0x70, 0x95, 0x2C,
+ 0x2C, 0xD6, 0xDD, 0x6F, 0x33, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x5D, 0x5D, 0x82, 0x69, 0x22, 0x62, 0x80, 0x34,
+ 0x94, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0xE5, 0x65, 0x6B,
+ 0xD5, 0x88, 0x5B, 0xE3, 0x29, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x49, 0x49, 0x49, 0x82,
+ 0x49, 0x49, 0x89, 0x49, 0x82, 0x49, 0x71, 0xBA,
+ 0x6D, 0x6D, 0xA1, 0x95, 0x55, 0xCB, 0x55, 0x55,
+ 0x2C, 0x55, 0x70, 0x70, 0x70, 0x90, 0x95, 0xA1,
+ 0x2C, 0xA1, 0x41, 0x76, 0x5D, 0x5D, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x5D, 0x82, 0x5D, 0x89, 0x5E, 0x96, 0x65,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0x65, 0xEC, 0xB1,
+ 0x20, 0x20, 0xCA, 0x23, 0x29, 0x33, 0x49, 0x5D,
+ 0x49, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49, 0x82,
+ 0x49, 0x82, 0x5D, 0x5D, 0x5D, 0x2D, 0x5C, 0x8F,
+ 0x6D, 0xD6, 0x2C, 0x55, 0x90, 0xCB, 0x95, 0x95,
+ 0x95, 0x55, 0x70, 0x94, 0x70, 0x55, 0x2C, 0xA1,
+ 0x95, 0xE8, 0x5F, 0x76, 0x33, 0x5D, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x3E, 0x9C, 0x2F, 0x68,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0x65, 0xE5, 0x65, 0xE5, 0x6B, 0x90, 0x80, 0x20,
+ 0x20, 0x20, 0x4F, 0x81, 0x50, 0x3E, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x69, 0x69, 0x49, 0x5D, 0x2D, 0xC4, 0x46, 0xA3,
+ 0xD6, 0x55, 0x70, 0x94, 0x94, 0x70, 0xCB, 0x55,
+ 0x55, 0xCB, 0x70, 0x47, 0x70, 0x95, 0xA1, 0xA1,
+ 0x95, 0xBD, 0x75, 0x2D, 0x33, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x5D, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x5D, 0x2D, 0xB5, 0xDB,
+ 0xD6, 0x65, 0xE5, 0x65, 0xE5, 0xE5, 0x65, 0xE5,
+ 0x65, 0x65, 0x6B, 0x95, 0x2B, 0x88, 0x20, 0x20,
+ 0x20, 0x20, 0x8B, 0x81, 0x29, 0x33, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x3E, 0x3E, 0x5E, 0x41, 0x97, 0x27, 0xD6,
+ 0x55, 0x94, 0xE6, 0xE6, 0x47, 0x70, 0x55, 0x55,
+ 0x94, 0x70, 0x94, 0x94, 0x70, 0x55, 0xA1, 0x2C,
+ 0x6D, 0xC5, 0x39, 0x6A, 0x5D, 0x5D, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x3E, 0xEA, 0x30, 0x77,
+ 0xE1, 0xC9, 0x94, 0x2C, 0xD6, 0xD6, 0xA1, 0x55,
+ 0x47, 0x9F, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x80, 0x91, 0x81, 0x6A, 0x2D, 0x49, 0x49,
+ 0x49, 0x5D, 0x5D, 0x49, 0x49, 0x5D, 0x5D, 0x82,
+ 0xEB, 0x4A, 0x41, 0xC2, 0x8F, 0xF5, 0xA1, 0x55,
+ 0x94, 0x28, 0xA0, 0x47, 0x70, 0x55, 0x95, 0x95,
+ 0x47, 0x70, 0x70, 0x94, 0x90, 0x95, 0xA1, 0x2C,
+ 0xE8, 0xA6, 0x39, 0x76, 0x50, 0x50, 0x2D, 0x2D,
+ 0x3E, 0x3E, 0x5D, 0x3E, 0x5D, 0x5D, 0x49, 0x82,
+ 0x49, 0x49, 0x49, 0x82, 0x82, 0x50, 0x75, 0xE0,
+ 0x57, 0x20, 0x88, 0x88, 0x20, 0x20, 0x88, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x79, 0x91, 0x81, 0x76, 0x33, 0x49, 0x49,
+ 0x5D, 0x82, 0x49, 0x49, 0x3E, 0x6A, 0xEA, 0x29,
+ 0xDF, 0x97, 0xBF, 0x6D, 0x6D, 0xD6, 0x55, 0x47,
+ 0x28, 0x28, 0x47, 0x70, 0x55, 0x95, 0x2C, 0x2C,
+ 0x95, 0x95, 0x55, 0x90, 0x90, 0x95, 0xA1, 0xA1,
+ 0xD6, 0x26, 0x45, 0x81, 0x5F, 0x30, 0x48, 0x6F,
+ 0x6F, 0x29, 0x29, 0x6A, 0x2D, 0x2D, 0x5D, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x2D, 0x76, 0x6E, 0x77,
+ 0x5B, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x79, 0xA9, 0xB8, 0x39, 0x50, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x3E, 0x2D, 0x29, 0x76, 0xCD, 0x37,
+ 0xB9, 0xA1, 0xA1, 0x6D, 0x6D, 0x2C, 0x94, 0x28,
+ 0xD5, 0xE6, 0x70, 0x55, 0x95, 0xA1, 0x2C, 0xA1,
+ 0xBF, 0xA1, 0x95, 0xCB, 0x55, 0x95, 0xA1, 0x2C,
+ 0x95, 0x83, 0xDE, 0x87, 0xB6, 0xBE, 0x40, 0x6E,
+ 0x81, 0x81, 0x78, 0x78, 0x39, 0x6F, 0xEA, 0x2D,
+ 0x2D, 0x33, 0x33, 0x33, 0x76, 0x30, 0x64, 0x54,
+ 0x5B, 0x66, 0x20, 0x20, 0x66, 0x20, 0x88, 0x20,
+ 0x20, 0x20, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x88, 0x34, 0x8B, 0xF1, 0x23, 0x6F, 0x50, 0x2D,
+ 0x2D, 0x6A, 0x29, 0x6F, 0x78, 0x84, 0x9B, 0xD2,
+ 0x2C, 0x2C, 0xD6, 0x6D, 0x6D, 0x2C, 0x47, 0xA0,
+ 0xE6, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0xA1,
+ 0xD2, 0x95, 0x55, 0xCB, 0x55, 0x2C, 0xD6, 0xA1,
+ 0x95, 0x95, 0xA1, 0xD6, 0x6D, 0x6D, 0xBA, 0xF3,
+ 0x8D, 0x36, 0x74, 0x36, 0xF1, 0xB8, 0x23, 0x78,
+ 0x62, 0x4A, 0x29, 0x62, 0x23, 0xF1, 0x54, 0x31,
+ 0x57, 0x2B, 0x90, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C, 0xCB,
+ 0xE6, 0x7D, 0xCA, 0xB7, 0xB8, 0x75, 0x6F, 0x6F,
+ 0x76, 0x6F, 0x78, 0x81, 0x53, 0xBD, 0x6D, 0x2C,
+ 0x95, 0x95, 0xA1, 0x6D, 0xA1, 0x55, 0x94, 0xE6,
+ 0x70, 0xCB, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xA1,
+ 0xD0, 0x94, 0x94, 0x90, 0x95, 0x2C, 0xD6, 0xA1,
+ 0x95, 0x55, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x2C,
+ 0xD6, 0x68, 0xAB, 0x6C, 0xA4, 0x77, 0x77, 0xAD,
+ 0x40, 0x53, 0x6E, 0x40, 0xB7, 0x54, 0x31, 0xD7,
+ 0xAC, 0xD6, 0x55, 0x55, 0x95, 0x95, 0x95, 0x55,
+ 0x95, 0x2C, 0x2C, 0xA1, 0x95, 0x95, 0x2C, 0xA1,
+ 0x6D, 0xD2, 0x7C, 0x54, 0xAD, 0x40, 0x6E, 0x81,
+ 0x81, 0x6E, 0x36, 0xDA, 0xE8, 0xD6, 0xD6, 0x2C,
+ 0x2C, 0x2C, 0xA1, 0xD6, 0x95, 0x90, 0x94, 0x47,
+ 0x94, 0x94, 0x70, 0x55, 0x2C, 0xD6, 0xA1, 0x95,
+ 0x95, 0x28, 0x47, 0x90, 0x95, 0x2C, 0xA1, 0x2C,
+ 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C,
+ 0x2C, 0xA1, 0x55, 0x70, 0x95, 0x2C, 0xB2, 0xB4,
+ 0xC3, 0xC3, 0x54, 0x54, 0xA9, 0x31, 0xCA, 0x2A,
+ 0x95, 0x90, 0x55, 0x95, 0x2C, 0xA1, 0x2C, 0x95,
+ 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xD6,
+ 0x6D, 0x2A, 0xB2, 0x4F, 0x31, 0x2E, 0xE0, 0xAD,
+ 0xB7, 0xC8, 0xB4, 0xF5, 0x2C, 0xA1, 0xA1, 0xA1,
+ 0x95, 0x2C, 0xA1, 0x2C, 0x95, 0x70, 0x94, 0x94,
+ 0x94, 0x94, 0x70, 0x95, 0xD6, 0xD6, 0x2C, 0x95,
+ 0x94, 0x28, 0x47, 0xCB, 0x95, 0x2C, 0xA1, 0xA1,
+ 0x95, 0x55, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x95,
+ 0x95, 0x2C, 0x55, 0x70, 0x70, 0x70, 0x94, 0x2C,
+ 0x63, 0xBB, 0xA5, 0xD7, 0xCA, 0xB3, 0x6D, 0x2C,
+ 0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x95, 0x95,
+ 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+ 0xD6, 0x2C, 0x70, 0x95, 0xAC, 0xC0, 0xDB, 0xEF,
+ 0xEF, 0xA2, 0xE8, 0x95, 0x95, 0xA1, 0xD6, 0xA1,
+ 0x95, 0x55, 0x2C, 0x95, 0x55, 0x70, 0x70, 0x70,
+ 0x94, 0x70, 0x55, 0xD6, 0x6D, 0x6D, 0x95, 0x55,
+ 0x70, 0x47, 0x70, 0x95, 0x2C, 0x2C, 0x2C, 0xA1,
+ 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x55,
+ 0x55, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55, 0x95,
+ 0xA1, 0xF5, 0xBF, 0xBF, 0xA1, 0x95, 0x95, 0x95,
+ 0x95, 0x55, 0x2C, 0x2C, 0x95, 0x55, 0x55, 0x95,
+ 0x95, 0x95, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0xA1,
+ 0x2C, 0x55, 0x70, 0x94, 0x90, 0x2C, 0x6D, 0x6D,
+ 0x6D, 0xA1, 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1,
+ 0x2C, 0x55, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x95, 0xD6, 0x6D, 0xBF, 0xD6, 0x55, 0xCB,
+ 0x55, 0x55, 0x55, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+ 0xA1, 0x95, 0x2C, 0xA1, 0xA1, 0xA1, 0x2C, 0x95,
+ 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+ 0x6D, 0xBF, 0x6D, 0x2C, 0x55, 0x55, 0x95, 0x95,
+ 0xCB, 0xCB, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x95,
+ 0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C,
+ 0xA1, 0x95, 0xCB, 0xCB, 0x95, 0x95, 0x2C, 0x2C,
+ 0x2C, 0xA1, 0x2C, 0x2C, 0x2C, 0xA1, 0xA1, 0x2C,
+ 0x2C, 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x2C, 0xA1, 0x6D, 0xBF, 0x6D, 0xA1, 0x55, 0x55,
+ 0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+ 0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x95,
+ 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xD6,
+ 0x6D, 0x6D, 0xA1, 0x95, 0xCB, 0x55, 0x95, 0x55,
+ 0x90, 0x70, 0xCB, 0xCB, 0x90, 0xCB, 0x95, 0x95,
+ 0x2C, 0x2C, 0xA1, 0xD6, 0xA1, 0xA1, 0xA1, 0xA1,
+ 0xA1, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+ 0x2C, 0xA1, 0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C,
+ 0x2C, 0x95, 0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1,
+ 0xD6, 0xD6, 0x6D, 0x6D, 0xA1, 0x55, 0xCB, 0x55
+};
+
+#endif
+
+#ifdef INCLUDE_LINUX_LOGOBW
+
+unsigned char linux_logo_bw[] __initdata = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
+ 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
+ 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
+ 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
+ 0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
+ 0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
+ 0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
+ 0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
+ 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
+ 0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF,
+ 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E,
+ 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
+ 0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC,
+ 0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF,
+ 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11,
+ 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06,
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
+ 0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1,
+ 0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF,
+ 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10,
+ 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
+ 0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
+ 0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7,
+ 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
+ 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8,
+ 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
+ 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
+ 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F,
+ 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
+ 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18,
+ 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
+ 0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
+ 0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01,
+ 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
+ 0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40,
+ 0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF,
+ 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23,
+ 0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
+ 0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
+ 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00,
+ 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
+ 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
+ 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
+ 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
+ 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
+ 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
+ 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
+ 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
+ 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
+ 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
+ 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
+ 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
+ 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
+ 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
+ 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
+ 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
+ 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
+ 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+#endif
+
+#ifdef INCLUDE_LINUX_LOGO16
+
+unsigned char linux_logo16_red[] __initdata = {
+ 0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x35, 0x83, 0xa5,
+ 0x65, 0x8f, 0x98, 0xc9, 0xdb, 0xe1, 0xe7, 0xf8
+};
+
+unsigned char linux_logo16_green[] __initdata = {
+ 0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x2e, 0x83, 0xa5,
+ 0x65, 0x6e, 0x98, 0x89, 0xbf, 0xac, 0xda, 0xf8
+};
+
+unsigned char linux_logo16_blue[] __initdata = {
+ 0x00, 0x90, 0xaf, 0x9c, 0xf7, 0x2b, 0x82, 0xa5,
+ 0x65, 0x41, 0x97, 0x1e, 0x60, 0x29, 0xa5, 0xf8
+};
+
+unsigned char linux_logo16[] __initdata = {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa1, 0x11, 0x11,
+ 0x61, 0x16, 0x66, 0x66, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0xa8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x87, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x73, 0x33, 0x33, 0x3a, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x27, 0x77, 0x77, 0x77, 0x33, 0x3a, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xa3, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x55, 0x50, 0x08, 0x33, 0x77, 0x77,
+ 0x77, 0x72, 0x72, 0x27, 0x77, 0x77, 0x33, 0x33,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xa3, 0x33, 0x33, 0x77, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x58, 0x85, 0x00, 0x11, 0x11, 0xaa,
+ 0xa3, 0x37, 0x77, 0x72, 0x22, 0x22, 0x77, 0x73,
+ 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3,
+ 0x33, 0x37, 0x77, 0x33, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x56, 0x85, 0x00, 0x06, 0x66, 0x11,
+ 0x11, 0x1a, 0xa3, 0x37, 0x77, 0x72, 0x22, 0x77,
+ 0x73, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33,
+ 0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x55, 0x00, 0x00, 0x06, 0x66, 0x66,
+ 0x66, 0x66, 0x11, 0x1a, 0xa3, 0x77, 0x72, 0x22,
+ 0x77, 0x73, 0x3a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33,
+ 0x33, 0x33, 0x33, 0xa0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,
+ 0x66, 0x66, 0x66, 0x66, 0x11, 0xa3, 0x77, 0x22,
+ 0x22, 0x77, 0x33, 0x33, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33,
+ 0x33, 0x3a, 0xa1, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x33,
+ 0xaa, 0x11, 0x16, 0x66, 0x66, 0x61, 0x1a, 0x37,
+ 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x33,
+ 0x3a, 0xa1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x22,
+ 0x22, 0x77, 0x3a, 0x11, 0x66, 0x66, 0x66, 0x1a,
+ 0x37, 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, 0x3a,
+ 0xa1, 0x11, 0x11, 0x10, 0x00, 0x00, 0x50, 0x00,
+ 0x00, 0x05, 0x80, 0x50, 0x00, 0x00, 0x07, 0x72,
+ 0x22, 0x22, 0x22, 0x73, 0xa1, 0x66, 0x66, 0x61,
+ 0x1a, 0x77, 0x22, 0x27, 0x73, 0x33, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x3a, 0xaa,
+ 0x11, 0x11, 0x1a, 0xa0, 0x08, 0x71, 0x05, 0x00,
+ 0x00, 0x12, 0x22, 0x50, 0x00, 0x00, 0x07, 0x77,
+ 0x77, 0x72, 0x22, 0x22, 0x27, 0x31, 0x16, 0x66,
+ 0x61, 0x13, 0x77, 0x22, 0x77, 0x33, 0x3a, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xa1,
+ 0x11, 0x1a, 0x33, 0x70, 0x07, 0x2e, 0x70, 0x00,
+ 0x01, 0x44, 0x42, 0x60, 0x00, 0x00, 0x02, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x31, 0x66,
+ 0x66, 0x61, 0xa3, 0x72, 0x22, 0x77, 0x33, 0xaa,
+ 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xaa, 0x11,
+ 0x1a, 0x33, 0x77, 0x30, 0x04, 0x82, 0x40, 0x00,
+ 0x54, 0x48, 0x54, 0x40, 0x00, 0x00, 0x01, 0xaa,
+ 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x31,
+ 0x66, 0x66, 0x11, 0x37, 0x22, 0x27, 0x73, 0x3a,
+ 0xaa, 0xaa, 0xa3, 0x33, 0x3a, 0xaa, 0xaa, 0xaa,
+ 0xa3, 0x77, 0xaa, 0x10, 0x50, 0x08, 0x46, 0x05,
+ 0x54, 0x80, 0x50, 0x42, 0x00, 0x00, 0x08, 0x66,
+ 0x66, 0x1a, 0x32, 0x22, 0x22, 0x22, 0x22, 0x27,
+ 0x31, 0x66, 0x66, 0x13, 0x72, 0x22, 0x77, 0x33,
+ 0xaa, 0xaa, 0xaa, 0x33, 0xaa, 0xa1, 0xaa, 0xa3,
+ 0x37, 0xa1, 0x1a, 0x30, 0x50, 0x06, 0x26, 0x00,
+ 0x54, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0xe2,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, 0x22,
+ 0x27, 0xa6, 0x66, 0x61, 0xa7, 0x72, 0x27, 0x73,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33,
+ 0x31, 0x11, 0x37, 0x70, 0x02, 0x00, 0xab, 0xbb,
+ 0xb6, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xee, 0xee,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22,
+ 0x22, 0x23, 0x16, 0x66, 0x1a, 0x37, 0x22, 0x77,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x3a,
+ 0x11, 0xa7, 0x33, 0x10, 0x04, 0x09, 0xbd, 0xdd,
+ 0xbd, 0xd0, 0x04, 0x45, 0x00, 0x0e, 0xee, 0xee,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22,
+ 0x22, 0x22, 0x71, 0x66, 0x66, 0x13, 0x72, 0x27,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x11,
+ 0xa3, 0x73, 0xa1, 0x60, 0x08, 0xbd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdb, 0x90, 0x00, 0x02, 0xec, 0xee,
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0x22,
+ 0x22, 0x22, 0x27, 0xa6, 0x66, 0x61, 0x37, 0x27,
+ 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x1a,
+ 0x33, 0xa1, 0x16, 0x60, 0x0b, 0xbd, 0xdd, 0xdd,
+ 0xcd, 0xdd, 0xdd, 0xd9, 0x00, 0x00, 0xec, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0xa2,
+ 0x22, 0x22, 0x22, 0x7a, 0x66, 0x66, 0x13, 0x77,
+ 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x11, 0x33,
+ 0xaa, 0x11, 0x66, 0x60, 0x9b, 0xdd, 0xdd, 0xdd,
+ 0xcd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0xec, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x61,
+ 0x72, 0x22, 0x22, 0x22, 0xa1, 0x66, 0x61, 0x37,
+ 0x1a, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x13, 0x3a,
+ 0x11, 0x11, 0x11, 0x10, 0x5b, 0xdd, 0xdd, 0xdc,
+ 0xdd, 0xdd, 0xbd, 0xd9, 0x00, 0x00, 0xec, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x86,
+ 0x17, 0x22, 0x22, 0x22, 0x23, 0x16, 0x66, 0xaa,
+ 0xaa, 0xa3, 0x3a, 0xaa, 0xaa, 0x1a, 0x3a, 0xa1,
+ 0x11, 0x11, 0x1a, 0x70, 0x05, 0xbd, 0xdd, 0xdd,
+ 0xdb, 0x5b, 0xdd, 0xb0, 0x00, 0x60, 0x2e, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe6, 0x88,
+ 0x66, 0x32, 0x22, 0x22, 0x22, 0x36, 0x66, 0x11,
+ 0x33, 0x33, 0x3a, 0xaa, 0x11, 0xaa, 0xaa, 0xa1,
+ 0x11, 0x1a, 0x3a, 0x60, 0x02, 0x99, 0xbb, 0xb9,
+ 0x9b, 0xbb, 0xbc, 0x22, 0x00, 0x86, 0x5e, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe1, 0x68,
+ 0x86, 0x63, 0x22, 0x22, 0x22, 0x2a, 0x66, 0x66,
+ 0x33, 0x33, 0xaa, 0xaa, 0x1a, 0xaa, 0xaa, 0x11,
+ 0x1a, 0xa7, 0x68, 0x80, 0x02, 0x2b, 0xbd, 0xbb,
+ 0xbb, 0xb9, 0x22, 0x22, 0x00, 0x06, 0x6e, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0xa6,
+ 0x88, 0x86, 0x32, 0x22, 0x22, 0x27, 0xa6, 0x66,
+ 0x33, 0x3a, 0xaa, 0xa1, 0xaa, 0xaa, 0xa1, 0x11,
+ 0xa3, 0xa6, 0x88, 0x80, 0x02, 0x22, 0x9b, 0xbb,
+ 0xbb, 0x22, 0x24, 0xf4, 0x60, 0x00, 0x0c, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc2, 0x21,
+ 0x68, 0x88, 0x63, 0x22, 0x22, 0x22, 0x71, 0x66,
+ 0x33, 0x3a, 0x11, 0x11, 0xaa, 0xaa, 0x11, 0xaa,
+ 0x71, 0x88, 0x88, 0x00, 0x02, 0xe2, 0x26, 0x99,
+ 0x22, 0x22, 0x4f, 0xf4, 0x40, 0x00, 0x0c, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x22, 0x22,
+ 0x16, 0x88, 0x86, 0xa2, 0x22, 0x22, 0x27, 0x11,
+ 0x33, 0xa1, 0x11, 0x11, 0xaa, 0x31, 0x1a, 0xa3,
+ 0x68, 0x88, 0x81, 0x00, 0x54, 0x42, 0x22, 0x22,
+ 0x22, 0x44, 0xff, 0xff, 0x48, 0x00, 0x00, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x22,
+ 0x21, 0x88, 0x88, 0x6a, 0x22, 0x22, 0x22, 0x31,
+ 0x3a, 0xa1, 0x11, 0x1a, 0xa3, 0x11, 0x33, 0x36,
+ 0x88, 0x86, 0x30, 0x00, 0x4f, 0x44, 0x22, 0x22,
+ 0x24, 0xff, 0xff, 0xff, 0x44, 0x00, 0x00, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x95, 0x22, 0x72,
+ 0x22, 0x18, 0x88, 0x86, 0x32, 0x22, 0x22, 0x27,
+ 0xaa, 0x11, 0x11, 0x1a, 0x31, 0x13, 0x33, 0x68,
+ 0x88, 0x6a, 0x00, 0x02, 0x4f, 0x4f, 0x42, 0x24,
+ 0x4f, 0xff, 0xff, 0xff, 0xf4, 0x50, 0x00, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x73,
+ 0x72, 0x26, 0x88, 0x88, 0x63, 0x22, 0x22, 0x22,
+ 0x11, 0x11, 0x11, 0xa3, 0xa1, 0x73, 0xa6, 0x88,
+ 0x81, 0xa5, 0x00, 0x04, 0x4f, 0x4f, 0x44, 0x4f,
+ 0xff, 0xff, 0xff, 0xff, 0xf4, 0x40, 0x00, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x12, 0x27,
+ 0xaa, 0x22, 0x68, 0x55, 0x86, 0x72, 0x22, 0x22,
+ 0x11, 0x11, 0x1a, 0x33, 0x13, 0x3a, 0x18, 0x88,
+ 0x1a, 0x10, 0x00, 0x44, 0x4f, 0x4f, 0xff, 0x4f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x61, 0x22,
+ 0x3a, 0xa2, 0x26, 0x85, 0x58, 0x67, 0x22, 0x22,
+ 0x61, 0x61, 0x1a, 0x7a, 0x37, 0x31, 0x88, 0x81,
+ 0x11, 0x00, 0x05, 0xe4, 0x44, 0xff, 0xff, 0xff,
+ 0x4f, 0xf4, 0x44, 0xff, 0xff, 0xf5, 0x00, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x12,
+ 0x2a, 0xaa, 0x72, 0x68, 0x55, 0x81, 0x22, 0x22,
+ 0x66, 0x61, 0xa3, 0x33, 0x73, 0x16, 0x88, 0x11,
+ 0x10, 0x00, 0x08, 0x74, 0x44, 0x4f, 0x44, 0x44,
+ 0xf4, 0xf4, 0x44, 0x44, 0xe2, 0x44, 0x00, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x81,
+ 0x22, 0xaa, 0xa7, 0x26, 0x85, 0x88, 0x12, 0x22,
+ 0x66, 0x61, 0x37, 0xa7, 0x3a, 0x66, 0x66, 0x11,
+ 0x80, 0x00, 0x0a, 0x72, 0x44, 0x4f, 0x44, 0x4f,
+ 0xff, 0x44, 0x44, 0x22, 0x22, 0x24, 0x00, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x85, 0x88,
+ 0x12, 0x2a, 0xaa, 0x22, 0x68, 0x58, 0x63, 0x22,
+ 0x66, 0x1a, 0x73, 0x77, 0x31, 0x66, 0x61, 0x11,
+ 0x00, 0x00, 0x07, 0x44, 0xff, 0x4f, 0xf4, 0x4f,
+ 0xff, 0x4f, 0x44, 0xf4, 0x42, 0x22, 0x40, 0x9b,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x85, 0x55,
+ 0x81, 0x27, 0xaa, 0xa2, 0x78, 0x88, 0x86, 0x72,
+ 0x66, 0x13, 0x77, 0x73, 0x11, 0x66, 0x61, 0x76,
+ 0x00, 0x50, 0x84, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x42, 0x40, 0x9b,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x68, 0x55,
+ 0x58, 0x12, 0x3a, 0xaa, 0x23, 0x88, 0x88, 0xa7,
+ 0x66, 0xa7, 0x77, 0x7a, 0x16, 0x66, 0x1a, 0x15,
+ 0x05, 0x00, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0x24, 0x9b,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x26, 0x55,
+ 0x55, 0x81, 0x23, 0xaa, 0x32, 0x18, 0x88, 0x6a,
+ 0x61, 0x37, 0x77, 0x31, 0x66, 0x66, 0x17, 0x60,
+ 0x05, 0x08, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4e, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0xa2, 0x65,
+ 0x55, 0x58, 0xa2, 0x7a, 0xa2, 0x26, 0x88, 0x61,
+ 0x61, 0x32, 0x27, 0xa1, 0x66, 0x61, 0x31, 0x60,
+ 0x00, 0x04, 0x4f, 0xf4, 0xff, 0x44, 0x44, 0xff,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x9b, 0xaa, 0x26,
+ 0x55, 0x55, 0x87, 0x27, 0x33, 0x27, 0x68, 0x61,
+ 0x1a, 0x72, 0x27, 0xa6, 0x66, 0x6a, 0x71, 0x00,
+ 0x80, 0x84, 0xff, 0xf4, 0xff, 0x44, 0x44, 0xff,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99,
+ 0x9b, 0x9b, 0x99, 0xb9, 0xb9, 0x99, 0xaa, 0xa2,
+ 0x85, 0x55, 0x56, 0x22, 0x27, 0x22, 0x36, 0x66,
+ 0x13, 0x22, 0x23, 0x16, 0x86, 0x63, 0x73, 0x00,
+ 0x00, 0x44, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4f, 0x99,
+ 0x9b, 0x99, 0x99, 0x99, 0xb9, 0x99, 0xaa, 0xaa,
+ 0x28, 0x55, 0x58, 0x12, 0x22, 0x22, 0x21, 0x11,
+ 0xa3, 0x27, 0x7a, 0x66, 0x86, 0x17, 0x75, 0x05,
+ 0x05, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff,
+ 0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x44, 0x4f, 0x99,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x3a, 0xaa,
+ 0xa2, 0x85, 0x58, 0x67, 0x72, 0x22, 0x27, 0xa1,
+ 0x37, 0x27, 0x7a, 0x68, 0x86, 0xa2, 0x70, 0x00,
+ 0x02, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xf4, 0x99,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x23, 0xaa,
+ 0xa7, 0x78, 0x88, 0x81, 0x77, 0x22, 0x27, 0x3a,
+ 0x72, 0x73, 0x71, 0x68, 0x66, 0x32, 0x50, 0x00,
+ 0x04, 0x4f, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x95,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x55, 0x12, 0x3a,
+ 0xaa, 0x21, 0x88, 0x81, 0x77, 0x27, 0x73, 0x73,
+ 0x72, 0x33, 0x36, 0x86, 0x61, 0x72, 0x00, 0x00,
+ 0x04, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x8a, 0x27,
+ 0xaa, 0x77, 0x68, 0x61, 0x23, 0x71, 0x11, 0x3a,
+ 0x27, 0xa3, 0x36, 0x86, 0x61, 0x20, 0x00, 0x00,
+ 0x04, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x59,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x95, 0x58, 0x77,
+ 0x27, 0x32, 0x36, 0x63, 0x23, 0x71, 0x66, 0x11,
+ 0x27, 0x13, 0xa6, 0x86, 0x6a, 0x20, 0x00, 0x50,
+ 0x04, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x99,
+ 0x9b, 0xbb, 0xbb, 0xbb, 0xb9, 0x99, 0x68, 0x13,
+ 0x32, 0x22, 0x73, 0xa7, 0x2a, 0x31, 0x88, 0x66,
+ 0x7a, 0x13, 0x18, 0x66, 0x63, 0x20, 0x00, 0x06,
+ 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x49, 0x95,
+ 0xa9, 0xa9, 0x99, 0x97, 0x92, 0x99, 0x65, 0x6a,
+ 0x17, 0x22, 0x23, 0x72, 0x27, 0xaa, 0x88, 0x88,
+ 0xa1, 0x17, 0x68, 0x66, 0x67, 0x70, 0x00, 0x05,
+ 0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x49, 0x9c,
+ 0x2e, 0xee, 0xee, 0xee, 0xee, 0xa9, 0x65, 0x8a,
+ 0x1a, 0xaa, 0x37, 0x72, 0x27, 0x37, 0x88, 0x88,
+ 0x11, 0x17, 0x68, 0x66, 0x67, 0x10, 0x9d, 0xd0,
+ 0x84, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0xf4, 0x4f,
+ 0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x4f, 0x69,
+ 0xcc, 0xee, 0xee, 0xee, 0xec, 0x99, 0x88, 0x63,
+ 0x61, 0x68, 0x61, 0x72, 0x22, 0x7a, 0x68, 0x88,
+ 0x11, 0x17, 0x88, 0x66, 0x12, 0x1b, 0xdd, 0xdd,
+ 0x02, 0x44, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xff, 0xff, 0x4f, 0x4c, 0xc5,
+ 0x0c, 0xc1, 0x11, 0x1c, 0xc0, 0x26, 0x66, 0x17,
+ 0x66, 0x88, 0x88, 0x12, 0x22, 0x23, 0xa8, 0x88,
+ 0x11, 0x13, 0x88, 0x66, 0x17, 0xbb, 0xdd, 0xdd,
+ 0xd0, 0x8f, 0xff, 0xf4, 0xf4, 0x44, 0xf4, 0x4f,
+ 0xff, 0x4f, 0x44, 0xf4, 0x4f, 0x44, 0xdd, 0xdd,
+ 0x00, 0x00, 0x00, 0x05, 0x9d, 0x21, 0x66, 0x27,
+ 0xa6, 0x65, 0x58, 0x67, 0x22, 0x27, 0x28, 0x88,
+ 0x11, 0xaa, 0x86, 0x68, 0x1a, 0xbb, 0xdd, 0xdd,
+ 0xdb, 0x05, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x4f,
+ 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xdd, 0xdb,
+ 0x00, 0x00, 0x00, 0x00, 0xdd, 0xda, 0x66, 0x22,
+ 0x71, 0x15, 0x55, 0x81, 0x22, 0x22, 0x76, 0x88,
+ 0x11, 0x31, 0x88, 0x88, 0xab, 0xbd, 0xdd, 0xdd,
+ 0xdd, 0x00, 0x04, 0x44, 0xff, 0xff, 0x4f, 0x4f,
+ 0xff, 0x4f, 0x44, 0xf4, 0xf4, 0x44, 0xdd, 0xdb,
+ 0x00, 0x00, 0x00, 0x0b, 0xdd, 0xda, 0x11, 0x22,
+ 0x23, 0x68, 0x55, 0x86, 0x22, 0x22, 0x7a, 0x88,
+ 0x1a, 0x71, 0x88, 0x89, 0xbb, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xd0, 0x00, 0x4f, 0x44, 0xff, 0x4f, 0x4f,
+ 0xff, 0x4f, 0x44, 0xf4, 0xff, 0xe2, 0xdd, 0xdb,
+ 0x90, 0x00, 0x05, 0xbd, 0xdd, 0xb8, 0x63, 0x22,
+ 0x27, 0xa6, 0x55, 0x88, 0x77, 0x22, 0x22, 0x88,
+ 0x1a, 0x28, 0xbd, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdb, 0x00, 0x07, 0x44, 0x4f, 0x4f, 0x4f,
+ 0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x22, 0xdd, 0xdb,
+ 0xbb, 0x9b, 0xbb, 0xbd, 0xdd, 0xd5, 0x86, 0x22,
+ 0x22, 0x77, 0x85, 0x88, 0x17, 0x22, 0x22, 0x88,
+ 0xaa, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0x00, 0x00, 0x54, 0x4f, 0x4f, 0x4f,
+ 0xff, 0x4f, 0x44, 0xf4, 0x44, 0x22, 0xbd, 0xdd,
+ 0xbb, 0xbb, 0xbb, 0xdd, 0xdd, 0xdd, 0x88, 0x72,
+ 0x27, 0x22, 0x88, 0x88, 0x67, 0x72, 0x22, 0x18,
+ 0x33, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xd0, 0x00, 0x05, 0x4f, 0x4f, 0x4f,
+ 0xff, 0x4f, 0x44, 0x44, 0x4f, 0x22, 0xbd, 0xdd,
+ 0xdb, 0xbb, 0xdd, 0xdd, 0xdd, 0xdd, 0x88, 0x17,
+ 0x27, 0x72, 0x68, 0x88, 0x87, 0x32, 0x22, 0x36,
+ 0x37, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xd5, 0x00, 0x00, 0x4f, 0x4f, 0x4f,
+ 0xff, 0xf4, 0xf4, 0xf4, 0xf4, 0x22, 0xbb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x67,
+ 0x72, 0x77, 0x38, 0x88, 0x83, 0x37, 0x22, 0x26,
+ 0x72, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0x00, 0x00, 0x4f, 0x4f, 0x4f,
+ 0xff, 0xf4, 0xf4, 0xf4, 0x44, 0x25, 0xbb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd3,
+ 0x32, 0x73, 0x76, 0x88, 0x81, 0x33, 0x22, 0x2a,
+ 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xb0, 0x54, 0x4f, 0x4f, 0x4f,
+ 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x00, 0xbb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xa7, 0x73, 0x26, 0x88, 0x86, 0x7a, 0x72, 0x27,
+ 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0xff, 0x4f, 0x4f,
+ 0xff, 0xf4, 0xf4, 0x44, 0x40, 0x05, 0xbb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0x13, 0x23, 0x21, 0x68, 0x86, 0x17, 0x72, 0x22,
+ 0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0x4f, 0x4f, 0x4f,
+ 0xff, 0xff, 0x44, 0x42, 0x00, 0x05, 0xbd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0x87, 0x27, 0x27, 0x16, 0x66, 0x67, 0x22, 0x22,
+ 0x72, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0x94, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x00, 0x00, 0x05, 0xbb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb8,
+ 0x86, 0x22, 0x22, 0x7a, 0x68, 0x81, 0x22, 0x22,
+ 0x37, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x44, 0x44, 0x44,
+ 0x44, 0x47, 0x00, 0x00, 0x00, 0x05, 0xbd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x68,
+ 0x58, 0x72, 0x22, 0x27, 0x18, 0x86, 0x72, 0x22,
+ 0x1a, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x18, 0x85,
+ 0x58, 0x12, 0x22, 0x36, 0x18, 0x88, 0x32, 0x22,
+ 0x61, 0x3b, 0xbb, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x7a, 0x68, 0x85,
+ 0x88, 0x62, 0x27, 0x16, 0x18, 0x88, 0x12, 0x27,
+ 0x86, 0x18, 0x9b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbd,
+ 0xdd, 0xdd, 0xdd, 0xbb, 0xb5, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xbb, 0xbd,
+ 0xdd, 0xdd, 0xdb, 0xbb, 0x87, 0x31, 0x68, 0x65,
+ 0x88, 0x82, 0x23, 0x16, 0x18, 0x88, 0x12, 0x23,
+ 0x88, 0x67, 0x27, 0xa8, 0x9b, 0xbb, 0xbb, 0xbb,
+ 0xbd, 0xdd, 0xbb, 0xbb, 0x95, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x9b, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0x96, 0x87, 0x16, 0x68, 0x18,
+ 0x88, 0x62, 0x31, 0x66, 0x18, 0x88, 0x62, 0x73,
+ 0x88, 0x63, 0x27, 0x33, 0x65, 0x55, 0x99, 0x9b,
+ 0xbb, 0xbb, 0xbb, 0x99, 0x55, 0x0a, 0xa1, 0x86,
+ 0x81, 0x68, 0x88, 0x55, 0x58, 0x85, 0x9b, 0xbb,
+ 0xbb, 0xbb, 0x95, 0x88, 0x83, 0x66, 0x66, 0x18,
+ 0x66, 0x82, 0xa1, 0x66, 0x18, 0x88, 0x62, 0x33,
+ 0x88, 0x81, 0x27, 0x7a, 0x18, 0x58, 0x86, 0x85,
+ 0x99, 0x99, 0x99, 0x95, 0x53, 0x2a, 0xaa, 0x88,
+ 0x67, 0x31, 0x68, 0x55, 0x58, 0x85, 0x59, 0xbb,
+ 0xbb, 0xb9, 0x58, 0x68, 0x83, 0x66, 0x61, 0x16,
+ 0x66, 0x62, 0x16, 0x66, 0x68, 0x88, 0x62, 0xaa,
+ 0x88, 0x86, 0x27, 0x77, 0x78, 0x55, 0x88, 0x22,
+ 0x25, 0x55, 0x95, 0x55, 0x6a, 0xa2, 0x2a, 0x88,
+ 0x62, 0x27, 0x37, 0x38, 0x88, 0x87, 0x55, 0x59,
+ 0x95, 0x58, 0x16, 0x88, 0x8a, 0x66, 0x63, 0x68,
+ 0x86, 0x67, 0x66, 0x66, 0x68, 0x88, 0x12, 0x11,
+ 0x88, 0x88, 0x72, 0x77, 0x78, 0x85, 0x58, 0x17,
+ 0x23, 0x32, 0x55, 0x55, 0x81, 0x13, 0x73, 0x66,
+ 0x62, 0x7a, 0xaa, 0x38, 0x88, 0x58, 0x27, 0x55,
+ 0x58, 0x32, 0x38, 0x88, 0x81, 0x66, 0xa2, 0x88,
+ 0x86, 0x61, 0x66, 0x61, 0x66, 0x68, 0x13, 0x11,
+ 0x88, 0x88, 0x12, 0x22, 0x71, 0x85, 0x58, 0x62,
+ 0x23, 0xa2, 0x68, 0x88, 0x81, 0x66, 0x88, 0x88,
+ 0x63, 0x2a, 0xaa, 0x28, 0x88, 0x55, 0x86, 0x61,
+ 0x66, 0x66, 0x68, 0x88, 0x66, 0x66, 0x77, 0x88,
+ 0x68, 0x16, 0x66, 0x62, 0x66, 0x68, 0xa1, 0x61,
+ 0x88, 0x88, 0x62, 0x22, 0x22, 0x85, 0x55, 0x83,
+ 0x72, 0x37, 0xa8, 0x88, 0x61, 0x66, 0x85, 0x55,
+ 0x86, 0x23, 0xaa, 0x71, 0x88, 0x85, 0x88, 0x66,
+ 0x88, 0x86, 0x88, 0x88, 0x16, 0x61, 0x21, 0x88,
+ 0x66, 0xa6, 0x86, 0x17, 0x66, 0x66, 0x31, 0x61,
+ 0x88, 0x88, 0x87, 0x72, 0x22, 0x68, 0x55, 0x86,
+ 0x77, 0x77, 0x36, 0x88, 0x13, 0x68, 0x85, 0x55,
+ 0x58, 0x12, 0x73, 0x72, 0x76, 0x88, 0x88, 0x68,
+ 0x88, 0x88, 0x88, 0x66, 0x36, 0x63, 0x26, 0x86,
+ 0x86, 0x36, 0x86, 0x11, 0x66, 0x66, 0x76, 0x61,
+ 0x88, 0x88, 0x81, 0x22, 0x22, 0x38, 0x85, 0x58,
+ 0x37, 0x22, 0x21, 0x68, 0xa2, 0x31, 0x68, 0x55,
+ 0x55, 0x81, 0x22, 0x22, 0xa8, 0x88, 0x88, 0x68,
+ 0x86, 0x88, 0x68, 0x81, 0x36, 0x17, 0x21, 0x68,
+ 0x86, 0x16, 0x66, 0x26, 0x66, 0x61, 0x36, 0x66,
+ 0x68, 0x88, 0x86, 0x27, 0x22, 0x28, 0x88, 0x88,
+ 0x17, 0x72, 0x2a, 0x66, 0xa2, 0x22, 0x36, 0x55,
+ 0x55, 0x58, 0x37, 0x3a, 0x16, 0x66, 0x66, 0x66,
+ 0x66, 0x18, 0x88, 0x67, 0x16, 0x12, 0x71, 0x68,
+ 0x81, 0x68, 0x61, 0x76, 0x66, 0x6a, 0x16, 0x66,
+ 0x88, 0x88, 0x86, 0x77, 0x22, 0x26, 0x88, 0x88,
+ 0x13, 0x37, 0x71, 0x66, 0xa2, 0x33, 0x2a, 0x85,
+ 0x55, 0x55, 0x17, 0x73, 0x16, 0x66, 0x66, 0x68,
+ 0x63, 0x88, 0x88, 0xa2, 0x66, 0xa2, 0xa6, 0x88,
+ 0x61, 0x68, 0x6a, 0x76, 0x66, 0x6a, 0x66, 0x6a
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/list.h b/pfinet/linux-src/include/linux/list.h
new file mode 100644
index 00000000..e77559a6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/list.h
@@ -0,0 +1,99 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#ifdef __KERNEL__
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD(name) \
+ struct list_head name = { &name, &name }
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head * new,
+ struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/*
+ * Insert a new entry after the specified head..
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+static __inline__ void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static __inline__ int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/*
+ * Splice in "list" into "head"
+ */
+static __inline__ void list_splice(struct list_head *list, struct list_head *head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/lists.h b/pfinet/linux-src/include/linux/lists.h
new file mode 100644
index 00000000..6a2240a2
--- /dev/null
+++ b/pfinet/linux-src/include/linux/lists.h
@@ -0,0 +1,62 @@
+/*
+ * lists.h: Simple list macros for Linux
+ */
+
+#define DLNODE(ptype) \
+ struct { \
+ ptype * dl_prev; \
+ ptype * dl_next; \
+ }
+
+#define DNODE_SINGLE(node) {(node),(node)}
+#define DNODE_NULL {0,0}
+
+#define DLIST_INIT(listnam) \
+ (listnam).dl_prev = &(listnam); \
+ (listnam).dl_next = &(listnam);
+
+#define DLIST_NEXT(listnam) listnam.dl_next
+#define DLIST_PREV(listnam) listnam.dl_prev
+
+#define DLIST_INSERT_AFTER(node, new, listnam) do { \
+ (new)->listnam.dl_prev = (node); \
+ (new)->listnam.dl_next = (node)->listnam.dl_next; \
+ (node)->listnam.dl_next->listnam.dl_prev = (new); \
+ (node)->listnam.dl_next = (new); \
+ } while (0)
+
+#define DLIST_INSERT_BEFORE(node, new, listnam) do { \
+ (new)->listnam.dl_next = (node); \
+ (new)->listnam.dl_prev = (node)->listnam.dl_prev; \
+ (node)->listnam.dl_prev->listnam.dl_next = (new); \
+ (node)->listnam.dl_prev = (new); \
+ } while (0)
+
+#define DLIST_DELETE(node, listnam) do { \
+ node->listnam.dl_prev->listnam.dl_next = \
+ node->listnam.dl_next; \
+ node->listnam.dl_next->listnam.dl_prev = \
+ node->listnam.dl_prev; \
+ } while (0)
+
+/*
+ * queue-style operations, which have a head and tail
+ */
+
+#define QUEUE_INIT(head, listnam, ptype) \
+ (head)->listnam.dl_prev = (head)->listnam.dl_next = (ptype)(head);
+
+#define QUEUE_FIRST(head, listnam) (head)->DLIST_NEXT(listnam)
+#define QUEUE_LAST(head, listnam) (head)->DLIST_PREV(listnam)
+#define QUEUE_EMPTY(head, listnam) \
+ ((QUEUE_FIRST(head, listnam) == QUEUE_LAST(head, listnam)) && \
+ ((u_long)QUEUE_FIRST(head, listnam) == (u_long)head))
+
+#define QUEUE_ENTER(head, new, listnam, ptype) do { \
+ (new)->listnam.dl_prev = (ptype)(head); \
+ (new)->listnam.dl_next = (head)->listnam.dl_next; \
+ (head)->listnam.dl_next->listnam.dl_prev = (new); \
+ (head)->listnam.dl_next = (new); \
+ } while (0)
+
+#define QUEUE_REMOVE(head, node, listnam) DLIST_DELETE(node, listnam)
diff --git a/pfinet/linux-src/include/linux/locks.h b/pfinet/linux-src/include/linux/locks.h
new file mode 100644
index 00000000..2094a4d1
--- /dev/null
+++ b/pfinet/linux-src/include/linux/locks.h
@@ -0,0 +1,62 @@
+#ifndef _LINUX_LOCKS_H
+#define _LINUX_LOCKS_H
+
+#ifndef _LINUX_MM_H
+#include <linux/mm.h>
+#endif
+#ifndef _LINUX_PAGEMAP_H
+#include <linux/pagemap.h>
+#endif
+
+/*
+ * Buffer cache locking - note that interrupts may only unlock, not
+ * lock buffers.
+ */
+extern void __wait_on_buffer(struct buffer_head *);
+
+extern inline void wait_on_buffer(struct buffer_head * bh)
+{
+ if (test_bit(BH_Lock, &bh->b_state))
+ __wait_on_buffer(bh);
+}
+
+extern inline void lock_buffer(struct buffer_head * bh)
+{
+ while (test_and_set_bit(BH_Lock, &bh->b_state))
+ __wait_on_buffer(bh);
+}
+
+extern inline void unlock_buffer(struct buffer_head *bh)
+{
+ clear_bit(BH_Lock, &bh->b_state);
+ wake_up(&bh->b_wait);
+}
+
+/*
+ * super-block locking. Again, interrupts may only unlock
+ * a super-block (although even this isn't done right now.
+ * nfs may need it).
+ */
+extern void __wait_on_super(struct super_block *);
+
+extern inline void wait_on_super(struct super_block * sb)
+{
+ if (sb->s_lock)
+ __wait_on_super(sb);
+}
+
+extern inline void lock_super(struct super_block * sb)
+{
+ if (sb->s_lock)
+ __wait_on_super(sb);
+ sb->s_lock = 1;
+}
+
+extern inline void unlock_super(struct super_block * sb)
+{
+ sb->s_lock = 0;
+ wake_up(&sb->s_wait);
+}
+
+#endif /* _LINUX_LOCKS_H */
+
diff --git a/pfinet/linux-src/include/linux/loop.h b/pfinet/linux-src/include/linux/loop.h
new file mode 100644
index 00000000..d276911c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/loop.h
@@ -0,0 +1,130 @@
+#ifndef _LINUX_LOOP_H
+#define _LINUX_LOOP_H
+
+#include <linux/kdev_t.h>
+
+/*
+ * include/linux/loop.h
+ *
+ * Written by Theodore Ts'o, 3/29/93.
+ *
+ * Copyright 1993 by Theodore Ts'o. Redistribution of this file is
+ * permitted under the GNU Public License.
+ */
+
+#define LO_NAME_SIZE 64
+#define LO_KEY_SIZE 32
+
+#ifdef __KERNEL__
+
+struct loop_device {
+ int lo_number;
+ struct dentry *lo_dentry;
+ int lo_refcnt;
+ kdev_t lo_device;
+ int lo_offset;
+ int lo_encrypt_type;
+ int lo_encrypt_key_size;
+ int lo_flags;
+ int (*transfer)(struct loop_device *, int cmd,
+ char *raw_buf, char *loop_buf, int size,
+ int real_block);
+ char lo_name[LO_NAME_SIZE];
+ char lo_encrypt_key[LO_KEY_SIZE];
+ __u32 lo_init[2];
+ uid_t lo_key_owner; /* Who set the key */
+ int (*ioctl)(struct loop_device *, int cmd,
+ unsigned long arg);
+
+ struct file * lo_backing_file;
+ void *key_data;
+ char key_reserved[48]; /* for use by the filter modules */
+};
+
+typedef int (* transfer_proc_t)(struct loop_device *, int cmd,
+ char *raw_buf, char *loop_buf, int size,
+ int real_block);
+
+#endif /* __KERNEL__ */
+
+/*
+ * Loop flags
+ */
+#define LO_FLAGS_DO_BMAP 0x00000001
+#define LO_FLAGS_READ_ONLY 0x00000002
+
+/*
+ * Note that this structure gets the wrong offsets when directly used
+ * from a glibc program, because glibc has a 32bit dev_t.
+ * Prevent people from shooting in their own foot.
+ */
+#if __GLIBC__ >= 2 && !defined(dev_t)
+#error "Wrong dev_t in loop.h"
+#endif
+
+/*
+ * This uses kdev_t because glibc currently has no appropiate
+ * conversion version for the loop ioctls.
+ * The situation is very unpleasant
+ */
+
+struct loop_info {
+ int lo_number; /* ioctl r/o */
+ dev_t lo_device; /* ioctl r/o */
+ unsigned long lo_inode; /* ioctl r/o */
+ dev_t lo_rdevice; /* ioctl r/o */
+ int lo_offset;
+ int lo_encrypt_type;
+ int lo_encrypt_key_size; /* ioctl w/o */
+ int lo_flags; /* ioctl r/o */
+ char lo_name[LO_NAME_SIZE];
+ unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+ unsigned long lo_init[2];
+ char reserved[4];
+};
+
+/*
+ * Loop filter types
+ */
+
+#define LO_CRYPT_NONE 0
+#define LO_CRYPT_XOR 1
+#define LO_CRYPT_DES 2
+#define LO_CRYPT_FISH2 3 /* Brand new Twofish encryption */
+#define LO_CRYPT_BLOW 4
+#define LO_CRYPT_CAST128 5
+#define LO_CRYPT_IDEA 6
+#define LO_CRYPT_DUMMY 9
+#define LO_CRYPT_SKIPJACK 10
+#define MAX_LO_CRYPT 20
+
+#ifdef __KERNEL__
+/* Support for loadable transfer modules */
+struct loop_func_table {
+ int number; /* filter type */
+ int (*transfer)(struct loop_device *lo, int cmd,
+ char *raw_buf, char *loop_buf, int size,
+ int real_block);
+ int (*init)(struct loop_device *, struct loop_info *);
+ /* release is called from loop_unregister_transfer or clr_fd */
+ int (*release)(struct loop_device *);
+ int (*ioctl)(struct loop_device *, int cmd, unsigned long arg);
+ /* lock and unlock manage the module use counts */
+ void (*lock)(struct loop_device *);
+ void (*unlock)(struct loop_device *);
+};
+
+int loop_register_transfer(struct loop_func_table *funcs);
+int loop_unregister_transfer(int number);
+
+#endif
+/*
+ * IOCTL commands --- we will commandeer 0x4C ('L')
+ */
+
+#define LOOP_SET_FD 0x4C00
+#define LOOP_CLR_FD 0x4C01
+#define LOOP_SET_STATUS 0x4C02
+#define LOOP_GET_STATUS 0x4C03
+
+#endif
diff --git a/pfinet/linux-src/include/linux/lp.h b/pfinet/linux-src/include/linux/lp.h
new file mode 100644
index 00000000..44474dcf
--- /dev/null
+++ b/pfinet/linux-src/include/linux/lp.h
@@ -0,0 +1,188 @@
+#ifndef _LINUX_LP_H
+#define _LINUX_LP_H
+
+/*
+ * usr/include/linux/lp.h c.1991-1992 James Wiegand
+ * many modifications copyright (C) 1992 Michael K. Johnson
+ * Interrupt support added 1993 Nigel Gamble
+ */
+
+/*
+ * Per POSIX guidelines, this module reserves the LP and lp prefixes
+ * These are the lp_table[minor].flags flags...
+ */
+#define LP_EXIST 0x0001
+#define LP_SELEC 0x0002
+#define LP_BUSY 0x0004
+#define LP_BUSY_BIT_POS 2
+#define LP_OFFL 0x0008
+#define LP_NOPA 0x0010
+#define LP_ERR 0x0020
+#define LP_ABORT 0x0040
+#define LP_CAREFUL 0x0080 /* obsoleted -arca */
+#define LP_ABORTOPEN 0x0100
+#define LP_TRUST_IRQ 0x0200
+
+/* timeout for each character. This is relative to bus cycles -- it
+ * is the count in a busy loop. THIS IS THE VALUE TO CHANGE if you
+ * have extremely slow printing, or if the machine seems to slow down
+ * a lot when you print. If you have slow printing, increase this
+ * number and recompile, and if your system gets bogged down, decrease
+ * this number. This can be changed with the tunelp(8) command as well.
+ */
+
+#define LP_INIT_CHAR 1000
+
+/* The parallel port specs apparently say that there needs to be
+ * a .5usec wait before and after the strobe.
+ */
+
+#define LP_INIT_WAIT 1
+
+/* This is the amount of time that the driver waits for the printer to
+ * catch up when the printer's buffer appears to be filled. If you
+ * want to tune this and have a fast printer (i.e. HPIIIP), decrease
+ * this number, and if you have a slow printer, increase this number.
+ * This is in hundredths of a second, the default 2 being .05 second.
+ * Or use the tunelp(8) command, which is especially nice if you want
+ * change back and forth between character and graphics printing, which
+ * are wildly different...
+ */
+
+#define LP_INIT_TIME 2
+
+/* IOCTL numbers */
+#define LPCHAR 0x0601 /* corresponds to LP_INIT_CHAR */
+#define LPTIME 0x0602 /* corresponds to LP_INIT_TIME */
+#define LPABORT 0x0604 /* call with TRUE arg to abort on error,
+ FALSE to retry. Default is retry. */
+#define LPSETIRQ 0x0605 /* call with new IRQ number,
+ or 0 for polling (no IRQ) */
+#define LPGETIRQ 0x0606 /* get the current IRQ number */
+#define LPWAIT 0x0608 /* corresponds to LP_INIT_WAIT */
+/* NOTE: LPCAREFUL is obsoleted and it' s always the default right now -arca */
+#define LPCAREFUL 0x0609 /* call with TRUE arg to require out-of-paper, off-
+ line, and error indicators good on all writes,
+ FALSE to ignore them. Default is ignore. */
+#define LPABORTOPEN 0x060a /* call with TRUE arg to abort open() on error,
+ FALSE to ignore error. Default is ignore. */
+#define LPGETSTATUS 0x060b /* return LP_S(minor) */
+#define LPRESET 0x060c /* reset printer */
+#ifdef LP_STATS
+#define LPGETSTATS 0x060d /* get statistics (struct lp_stats) */
+#endif
+#define LPGETFLAGS 0x060e /* get status flags */
+#define LPTRUSTIRQ 0x060f /* set/unset the LP_TRUST_IRQ flag */
+
+/* timeout for printk'ing a timeout, in jiffies (100ths of a second).
+ This is also used for re-checking error conditions if LP_ABORT is
+ not set. This is the default behavior. */
+
+#define LP_TIMEOUT_INTERRUPT (60 * HZ)
+#define LP_TIMEOUT_POLLED (10 * HZ)
+
+#ifdef __KERNEL__
+
+/* Magic numbers for defining port-device mappings */
+#define LP_PARPORT_UNSPEC -4
+#define LP_PARPORT_AUTO -3
+#define LP_PARPORT_OFF -2
+#define LP_PARPORT_NONE -1
+
+#define LP_F(minor) lp_table[(minor)].flags /* flags for busy, etc. */
+#define LP_CHAR(minor) lp_table[(minor)].chars /* busy timeout */
+#define LP_TIME(minor) lp_table[(minor)].time /* wait time */
+#define LP_WAIT(minor) lp_table[(minor)].wait /* strobe wait */
+#define LP_IRQ(minor) lp_table[(minor)].dev->port->irq /* interrupt # */
+ /* PARPORT_IRQ_NONE means polled */
+#ifdef LP_STATS
+#define LP_STAT(minor) lp_table[(minor)].stats /* statistics area */
+#endif
+#define LP_BUFFER_SIZE 256
+
+#define LP_BASE(x) lp_table[(x)].dev->port->base
+
+#ifdef LP_STATS
+struct lp_stats {
+ unsigned long chars;
+ unsigned long sleeps;
+ unsigned int maxrun;
+ unsigned int maxwait;
+ unsigned int meanwait;
+ unsigned int mdev;
+};
+#endif
+
+struct lp_struct {
+ struct pardevice *dev;
+ unsigned long flags;
+ unsigned int chars;
+ unsigned int time;
+ unsigned int wait;
+ char *lp_buffer;
+#ifdef LP_STATS
+ unsigned int lastcall;
+ unsigned int runchars;
+ struct lp_stats stats;
+#endif
+ struct wait_queue *wait_q;
+ unsigned int last_error;
+ volatile unsigned int irq_detected:1;
+ volatile unsigned int irq_missed:1;
+};
+
+/*
+ * The following constants describe the various signals of the printer port
+ * hardware. Note that the hardware inverts some signals and that some
+ * signals are active low. An example is LP_STROBE, which must be programmed
+ * with 1 for being active and 0 for being inactive, because the strobe signal
+ * gets inverted, but it is also active low.
+ */
+
+/*
+ * bit defines for 8255 status port
+ * base + 1
+ * accessed with LP_S(minor), which gets the byte...
+ */
+#define LP_PBUSY 0x80 /* inverted input, active high */
+#define LP_PACK 0x40 /* unchanged input, active low */
+#define LP_POUTPA 0x20 /* unchanged input, active high */
+#define LP_PSELECD 0x10 /* unchanged input, active high */
+#define LP_PERRORP 0x08 /* unchanged input, active low */
+
+/*
+ * defines for 8255 control port
+ * base + 2
+ * accessed with LP_C(minor)
+ */
+#define LP_PINTEN 0x10 /* high to read data in or-ed with data out */
+#define LP_PSELECP 0x08 /* inverted output, active low */
+#define LP_PINITP 0x04 /* unchanged output, active low */
+#define LP_PAUTOLF 0x02 /* inverted output, active low */
+#define LP_PSTROBE 0x01 /* short high output on raising edge */
+
+/*
+ * the value written to ports to test existence. PC-style ports will
+ * return the value written. AT-style ports will return 0. so why not
+ * make them the same ?
+ */
+#define LP_DUMMY 0x00
+
+/*
+ * This is the port delay time, in microseconds.
+ * It is used only in the lp_init() and lp_reset() routine.
+ */
+#define LP_DELAY 50
+
+#define LP_POLLED(minor) (lp_table[(minor)].dev->port->irq == PARPORT_IRQ_NONE)
+#define LP_PREEMPTED(minor) (lp_table[(minor)].dev->port->waithead != NULL)
+
+/*
+ * function prototypes
+ */
+
+extern int lp_init(void);
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/lp_intern.h b/pfinet/linux-src/include/linux/lp_intern.h
new file mode 100644
index 00000000..c7af535f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/lp_intern.h
@@ -0,0 +1,22 @@
+#ifndef _LINUX_LP_INTERN_H_
+#define _LINUX_LP_INTERN_H_
+
+/*
+ * split in two parts by Joerg Dorchain
+ * usr/include/linux/lp.h modified for Amiga by Michael Rausch
+ * modified for Atari by Andreas Schwab
+ * bug fixed by Jes Sorensen 18/8-94:
+ * It was not possible to compile the kernel only for Atari or Amiga.
+ *
+ * linux i386 version c.1991-1992 James Wiegand
+ * many modifications copyright (C) 1992 Michael K. Johnson
+ * Interrupt support added 1993 Nigel Gamble
+ */
+
+#include <linux/types.h>
+#include <linux/lp_m68k.h>
+
+int lp_internal_init(void);
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/lp_m68k.h b/pfinet/linux-src/include/linux/lp_m68k.h
new file mode 100644
index 00000000..cddecc98
--- /dev/null
+++ b/pfinet/linux-src/include/linux/lp_m68k.h
@@ -0,0 +1,135 @@
+#ifndef _LINUX_LP_H
+#define _LINUX_LP_H
+
+/*
+ * split in two parts by Joerg Dorchain
+ * usr/include/linux/lp.h modified for Amiga by Michael Rausch
+ * modified for Atari by Andreas Schwab
+ * bug fixed by Jes Sorensen 18/8-94:
+ * It was not possible to compile the kernel only for Atari or Amiga.
+ *
+ * linux i386 version c.1991-1992 James Wiegand
+ * many modifications copyright (C) 1992 Michael K. Johnson
+ * Interrupt support added 1993 Nigel Gamble
+ */
+
+/*
+ * many many printers are we going to support? currently, this is the
+ * hardcoded limit
+ */
+#define MAX_LP 5
+
+/*
+ * Per POSIX guidelines, this module reserves the LP and lp prefixes
+ * These are the lp_table[minor].flags flags...
+ */
+#define LP_EXIST 0x0001
+#define LP_BUSY 0x0004
+#define LP_ABORT 0x0040
+#define LP_CAREFUL 0x0080
+#define LP_ABORTOPEN 0x0100
+
+/* timeout for each character. This is relative to bus cycles -- it
+ * is the count in a busy loop. THIS IS THE VALUE TO CHANGE if you
+ * have extremely slow printing, or if the machine seems to slow down
+ * a lot when you print. If you have slow printing, increase this
+ * number and recompile, and if your system gets bogged down, decrease
+ * this number. This can be changed with the tunelp(8) command as well.
+ */
+
+#define LP_INIT_CHAR 1000
+
+/* The parallel port specs apparently say that there needs to be
+ * a .5usec wait before and after the strobe. Since there are wildly
+ * different computers running linux, I can't come up with a perfect
+ * value, but since it worked well on most printers before without,
+ * I'll initialize it to 0.
+ */
+
+#define LP_INIT_WAIT 0
+
+/* This is the amount of time that the driver waits for the printer to
+ * catch up when the printer's buffer appears to be filled. If you
+ * want to tune this and have a fast printer (i.e. HPIIIP), decrease
+ * this number, and if you have a slow printer, increase this number.
+ * This is in hundredths of a second, the default 2 being .05 second.
+ * Or use the tunelp(8) command, which is especially nice if you want
+ * change back and forth between character and graphics printing, which
+ * are wildly different...
+ */
+
+#define LP_INIT_TIME 40
+
+/* IOCTL numbers */
+#define LPCHAR 0x0601 /* corresponds to LP_INIT_CHAR */
+#define LPTIME 0x0602 /* corresponds to LP_INIT_TIME */
+#define LPABORT 0x0604 /* call with TRUE arg to abort on error,
+ FALSE to retry. Default is retry. */
+#define LPSETIRQ 0x0605 /* call with new IRQ number,
+ or 0 for polling (no IRQ) */
+#define LPGETIRQ 0x0606 /* get the current IRQ number */
+#define LPWAIT 0x0608 /* corresponds to LP_INIT_WAIT */
+#define LPCAREFUL 0x0609 /* call with TRUE arg to require out-of-paper, off-
+ line, and error indicators good on all writes,
+ FALSE to ignore them. Default is ignore. */
+#define LPABORTOPEN 0x060a /* call with TRUE arg to abort open() on error,
+ FALSE to ignore error. Default is ignore. */
+#define LPGETSTATUS 0x060b /* return LP_S(minor) */
+#define LPRESET 0x060c /* reset printer */
+
+/* timeout for printk'ing a timeout, in jiffies (100ths of a second).
+ This is also used for re-checking error conditions if LP_ABORT is
+ not set. This is the default behavior. */
+
+#define LP_TIMEOUT_INTERRUPT (60 * HZ)
+#define LP_TIMEOUT_POLLED (10 * HZ)
+
+
+#define LP_BUFFER_SIZE 1024 /*256*/
+
+enum lp_type {
+LP_UNKNOWN = 0,
+LP_AMIGA = 1,
+LP_ATARI = 2,
+LP_MFC = 3,
+LP_IOEXT = 4,
+LP_MVME167 = 5,
+LP_BVME6000 = 6
+};
+
+/*
+ * warning: this structure is in kernel space and has to fit in one page,
+ * i.e. must not be larger than 4k
+ */
+struct lp_struct {
+ char *name;
+ unsigned int irq;
+ void (*lp_out)(int,int); /*output char function*/
+ int (*lp_is_busy)(int);
+ int (*lp_has_pout)(int);
+ int (*lp_is_online)(int);
+ int (*lp_dummy)(int);
+ int (*lp_ioctl)(int, unsigned int, unsigned long);
+ int (*lp_open)(int); /* for module use counter */
+ void (*lp_release)(int); /* for module use counter */
+ int flags; /*for BUSY... */
+ unsigned int chars; /*busy timeout */
+ unsigned int time; /*wait time */
+ unsigned int wait;
+ struct wait_queue *lp_wait_q; /*strobe wait */
+ void *base; /* hardware drivers internal use*/
+ enum lp_type type;
+ char lp_buffer[LP_BUFFER_SIZE];
+ int do_print;
+ unsigned long copy_size,bytes_written;
+};
+
+extern struct lp_struct *lp_table[MAX_LP];
+extern unsigned int lp_irq;
+
+void lp_interrupt(int dev);
+int lp_m68k_init(void);
+int register_parallel(struct lp_struct *, int);
+void unregister_parallel(int);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/lp_mfc.h b/pfinet/linux-src/include/linux/lp_mfc.h
new file mode 100644
index 00000000..cf8cfb44
--- /dev/null
+++ b/pfinet/linux-src/include/linux/lp_mfc.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_LP_MFC_H_
+#define _LINUX_LP_MFC_H_
+
+/*
+ * created 6.11.95 Joerg Dorchain
+ */
+
+#include <linux/types.h>
+#include <linux/lp_m68k.h>
+
+int lp_mfc_init(void);
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/major.h b/pfinet/linux-src/include/linux/major.h
new file mode 100644
index 00000000..571c9be0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/major.h
@@ -0,0 +1,131 @@
+#ifndef _LINUX_MAJOR_H
+#define _LINUX_MAJOR_H
+
+/*
+ * This file has definitions for major device numbers.
+ * For the device number assignments, see Documentation/devices.txt.
+ */
+
+/* limits */
+
+/*
+ * Important: Don't change this to 256. Major number 255 is and must be
+ * reserved for future expansion into a larger dev_t space.
+ */
+#define MAX_CHRDEV 255
+#define MAX_BLKDEV 255
+
+#define UNNAMED_MAJOR 0
+#define MEM_MAJOR 1
+#define RAMDISK_MAJOR 1
+#define FLOPPY_MAJOR 2
+#define PTY_MASTER_MAJOR 2
+#define IDE0_MAJOR 3
+#define PTY_SLAVE_MAJOR 3
+#define HD_MAJOR IDE0_MAJOR
+#define TTY_MAJOR 4
+#define TTYAUX_MAJOR 5
+#define LP_MAJOR 6
+#define VCS_MAJOR 7
+#define LOOP_MAJOR 7
+#define SCSI_DISK0_MAJOR 8
+#define SCSI_TAPE_MAJOR 9
+#define MD_MAJOR 9
+#define MISC_MAJOR 10
+#define SCSI_CDROM_MAJOR 11
+#define QIC02_TAPE_MAJOR 12
+#define XT_DISK_MAJOR 13
+#define SOUND_MAJOR 14
+#define CDU31A_CDROM_MAJOR 15
+#define JOYSTICK_MAJOR 15
+#define GOLDSTAR_CDROM_MAJOR 16
+#define OPTICS_CDROM_MAJOR 17
+#define SANYO_CDROM_MAJOR 18
+#define CYCLADES_MAJOR 19
+#define CYCLADESAUX_MAJOR 20
+#define MITSUMI_X_CDROM_MAJOR 20
+#define MFM_ACORN_MAJOR 21 /* ARM Linux /dev/mfm */
+#define SCSI_GENERIC_MAJOR 21
+#define Z8530_MAJOR 34
+#define DIGI_MAJOR 23
+#define IDE1_MAJOR 22
+#define DIGICU_MAJOR 22
+#define MITSUMI_CDROM_MAJOR 23
+#define CDU535_CDROM_MAJOR 24
+#define STL_SERIALMAJOR 24
+#define MATSUSHITA_CDROM_MAJOR 25
+#define STL_CALLOUTMAJOR 25
+#define MATSUSHITA_CDROM2_MAJOR 26
+#define QIC117_TAPE_MAJOR 27
+#define MATSUSHITA_CDROM3_MAJOR 27
+#define MATSUSHITA_CDROM4_MAJOR 28
+#define STL_SIOMEMMAJOR 28
+#define ACSI_MAJOR 28
+#define AZTECH_CDROM_MAJOR 29
+#define GRAPHDEV_MAJOR 29 /* SparcLinux & Linux/68k /dev/fb */
+#define SHMIQ_MAJOR 85 /* Linux/MIPS, SGI /dev/shmiq */
+#define CM206_CDROM_MAJOR 32
+#define IDE2_MAJOR 33
+#define IDE3_MAJOR 34
+#define NETLINK_MAJOR 36
+#define PS2ESDI_MAJOR 36
+#define IDETAPE_MAJOR 37
+#define Z2RAM_MAJOR 37
+#define APBLOCK_MAJOR 38 /* AP1000 Block device */
+#define DDV_MAJOR 39 /* AP1000 DDV block device */
+#define NBD_MAJOR 43 /* Network block device */
+#define RISCOM8_NORMAL_MAJOR 48
+#define DAC960_MAJOR 48 /* 48..55 */
+#define RISCOM8_CALLOUT_MAJOR 49
+#define MKISS_MAJOR 55
+#define DSP56K_MAJOR 55 /* DSP56001 processor device */
+
+#define IDE4_MAJOR 56
+#define IDE5_MAJOR 57
+
+#define SCSI_DISK1_MAJOR 65
+#define SCSI_DISK2_MAJOR 66
+#define SCSI_DISK3_MAJOR 67
+#define SCSI_DISK4_MAJOR 68
+#define SCSI_DISK5_MAJOR 69
+#define SCSI_DISK6_MAJOR 70
+#define SCSI_DISK7_MAJOR 71
+
+#define LVM_BLK_MAJOR 58 /* Logical Volume Manager */
+
+#define COMPAQ_SMART2_MAJOR 72
+#define COMPAQ_SMART2_MAJOR1 73
+#define COMPAQ_SMART2_MAJOR2 74
+#define COMPAQ_SMART2_MAJOR3 75
+#define COMPAQ_SMART2_MAJOR4 76
+#define COMPAQ_SMART2_MAJOR5 77
+#define COMPAQ_SMART2_MAJOR6 78
+#define COMPAQ_SMART2_MAJOR7 79
+
+#define SPECIALIX_NORMAL_MAJOR 75
+#define SPECIALIX_CALLOUT_MAJOR 76
+
+#define LVM_CHAR_MAJOR 109 /* Logical Volume Manager */
+
+#define AURORA_MAJOR 79
+
+#define UNIX98_PTY_MASTER_MAJOR 128
+#define UNIX98_PTY_MAJOR_COUNT 8
+#define UNIX98_PTY_SLAVE_MAJOR (UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT)
+
+/*
+ * Tests for SCSI devices.
+ */
+
+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+ ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
+
+#define SCSI_BLK_MAJOR(M) \
+ (SCSI_DISK_MAJOR(M) \
+ || (M) == SCSI_CDROM_MAJOR)
+
+static __inline__ int scsi_blk_major(int m) {
+ return SCSI_BLK_MAJOR(m);
+}
+
+#endif
diff --git a/pfinet/linux-src/include/linux/malloc.h b/pfinet/linux-src/include/linux/malloc.h
new file mode 100644
index 00000000..f3ebf185
--- /dev/null
+++ b/pfinet/linux-src/include/linux/malloc.h
@@ -0,0 +1,5 @@
+#ifndef _LINUX_MALLOC_H
+#define _LINUX_MALLOC_H
+
+#include <linux/slab.h>
+#endif /* _LINUX_MALLOC_H */
diff --git a/pfinet/linux-src/include/linux/mc146818rtc.h b/pfinet/linux-src/include/linux/mc146818rtc.h
new file mode 100644
index 00000000..0a2efb6e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/mc146818rtc.h
@@ -0,0 +1,149 @@
+/* mc146818rtc.h - register definitions for the Real-Time-Clock / CMOS RAM
+ * Copyright Torsten Duwe <duwe@informatik.uni-erlangen.de> 1993
+ * derived from Data Sheet, Copyright Motorola 1984 (!).
+ * It was written to be part of the Linux operating system.
+ */
+/* permission is hereby granted to copy, modify and redistribute this code
+ * in terms of the GNU Library General Public License, Version 2 or later,
+ * at your option.
+ */
+
+#ifndef _MC146818RTC_H
+#define _MC146818RTC_H
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_ALWAYS_BCD 1
+#endif
+
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+/**********************************************************************
+ * register summary
+ **********************************************************************/
+#define RTC_SECONDS 0
+#define RTC_SECONDS_ALARM 1
+#define RTC_MINUTES 2
+#define RTC_MINUTES_ALARM 3
+#define RTC_HOURS 4
+#define RTC_HOURS_ALARM 5
+/* RTC_*_alarm is always true if 2 MSBs are set */
+# define RTC_ALARM_DONT_CARE 0xC0
+
+#define RTC_DAY_OF_WEEK 6
+#define RTC_DAY_OF_MONTH 7
+#define RTC_MONTH 8
+#define RTC_YEAR 9
+
+/* control registers - Moto names
+ */
+#define RTC_REG_A 10
+#define RTC_REG_B 11
+#define RTC_REG_C 12
+#define RTC_REG_D 13
+
+/**********************************************************************
+ * register details
+ **********************************************************************/
+#define RTC_FREQ_SELECT RTC_REG_A
+
+/* update-in-progress - set to "1" 244 microsecs before RTC goes off the bus,
+ * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete,
+ * totalling to a max high interval of 2.228 ms.
+ */
+# define RTC_UIP 0x80
+# define RTC_DIV_CTL 0x70
+ /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */
+# define RTC_REF_CLCK_4MHZ 0x00
+# define RTC_REF_CLCK_1MHZ 0x10
+# define RTC_REF_CLCK_32KHZ 0x20
+ /* 2 values for divider stage reset, others for "testing purposes only" */
+# define RTC_DIV_RESET1 0x60
+# define RTC_DIV_RESET2 0x70
+ /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
+# define RTC_RATE_SELECT 0x0F
+
+/**********************************************************************/
+#define RTC_CONTROL RTC_REG_B
+# define RTC_SET 0x80 /* disable updates for clock setting */
+# define RTC_PIE 0x40 /* periodic interrupt enable */
+# define RTC_AIE 0x20 /* alarm interrupt enable */
+# define RTC_UIE 0x10 /* update-finished interrupt enable */
+# define RTC_SQWE 0x08 /* enable square-wave output */
+# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
+# define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
+# define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
+
+/**********************************************************************/
+#define RTC_INTR_FLAGS RTC_REG_C
+/* caution - cleared by read */
+# define RTC_IRQF 0x80 /* any of the following 3 is active */
+# define RTC_PF 0x40
+# define RTC_AF 0x20
+# define RTC_UF 0x10
+
+/**********************************************************************/
+#define RTC_VALID RTC_REG_D
+# define RTC_VRT 0x80 /* valid RAM and time */
+/**********************************************************************/
+
+/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+ * determines if the following two #defines are needed
+ */
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+/*
+ * The struct used to pass data via the following ioctl. Similar to the
+ * struct tm in <time.h>, but it needs to be here so that the kernel
+ * source is self contained, allowing cross-compiles, etc. etc.
+ */
+
+struct rtc_time {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+};
+
+/*
+ * ioctl calls that are permitted to the /dev/rtc interface, if
+ * CONFIG_RTC was enabled.
+ */
+
+#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */
+#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */
+#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
+#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */
+#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */
+#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */
+
+#define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */
+#define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */
+#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time) /* Read RTC time */
+#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time) /* Set RTC time */
+#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */
+#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */
+#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
+#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
+
+
+#endif /* _MC146818RTC_H */
diff --git a/pfinet/linux-src/include/linux/mca.h b/pfinet/linux-src/include/linux/mca.h
new file mode 100644
index 00000000..5b6a6ebf
--- /dev/null
+++ b/pfinet/linux-src/include/linux/mca.h
@@ -0,0 +1,100 @@
+/*
+ * Header for Microchannel Architecture Bus
+ * Written by Martin Kolinek, February 1996
+*/
+
+#ifndef _LINUX_MCA_H
+#define _LINUX_MCA_H
+
+/* The detection of MCA bus is done in the real mode (using BIOS).
+ * The information is exported to the protected code, where this
+ * variable is set to one in case MCA bus was detected.
+*/
+extern int MCA_bus;
+
+/* maximal number of MCA slots - actually, some machines have less, but
+they all have sufficient number of POS registers to cover 8. */
+#define MCA_MAX_SLOT_NR 8
+
+/* MCA_NOTFOUND is an error condition. The other two indicate
+ motherboard POS registers contain the adapter. They might be
+ returned by the mca_find_adapter() function, and can be used as
+ arguments to mca_read_stored_pos(). I'm not going to allow direct
+ access to the motherboard registers until we run across an adapter
+ that requires it. We don't know enough about them to know if it's
+ safe.
+
+ See Documentation/mca.txt or one of the existing drivers for
+ more information.
+*/
+#define MCA_NOTFOUND (-1)
+#define MCA_INTEGSCSI (MCA_MAX_SLOT_NR)
+#define MCA_INTEGVIDEO (MCA_MAX_SLOT_NR+1)
+
+/* max number of adapters, including both slots and various integrated
+things. */
+#define MCA_NUMADAPTERS (MCA_MAX_SLOT_NR+2)
+
+/* returns the slot of the first enabled adapter matching id. User can
+specify a starting slot beyond zero, to deal with detecting multiple
+devices. Returns MCA_NOTFOUND if id not found. Also checks the
+integrated adapters. */
+extern int mca_find_adapter(int id, int start);
+extern int mca_find_unused_adapter(int id, int start);
+
+/* adapter state info - returns 0 if no */
+extern int mca_isadapter(int slot);
+extern int mca_isenabled(int slot);
+
+extern int mca_is_adapter_used(int slot);
+extern int mca_mark_as_used(int slot);
+extern void mca_mark_as_unused(int slot);
+
+/* gets a byte out of POS register (stored in memory) */
+extern unsigned char mca_read_stored_pos(int slot, int reg);
+
+/*
+ This can be expanded later. Right now, it gives us a way of
+ getting meaningful information into the MCA_info structure,
+ so we can have a more interesting /proc/mca.
+*/
+extern void mca_set_adapter_name(int slot, char* name);
+extern char* mca_get_adapter_name(int slot);
+
+/*
+ This sets up an information callback for /proc/mca/slot?. The
+ function is called with the buffer, slot, and device pointer (or
+ some equally informative context information, or nothing, if you
+ prefer), and is expected to put useful information into the
+ buffer. The adapter name, id, and POS registers get printed
+ before this is called though, so don't do it again.
+
+ This should be called with a NULL procfn when a module
+ unregisters, thus preventing kernel crashes and other such
+ nastiness.
+*/
+typedef int (*MCA_ProcFn)(char* buf, int slot, void* dev);
+extern void mca_set_adapter_procfn(int slot, MCA_ProcFn, void* dev);
+
+/* These routines actually mess with the hardware POS registers. They
+temporarily disable the device (and interrupts), so make sure you know
+what you're doing if you use them. Furthermore, writing to a POS may
+result in two devices trying to share a resource, which in turn can
+result in multiple devices sharing memory spaces, IRQs, or even trashing
+hardware. YOU HAVE BEEN WARNED.
+
+You can only access slots with this. Motherboard registers are off
+limits.
+*/
+
+/* read a byte from the specified POS register. */
+extern unsigned char mca_read_pos(int slot, int reg);
+
+/* write a byte to the specified POS register. */
+extern void mca_write_pos(int slot, int reg, unsigned char byte);
+
+/* Should only be called by the NMI interrupt handler, this will do some
+fancy stuff to figure out what might have generated a NMI. */
+extern void mca_handle_nmi(void);
+
+#endif /* _LINUX_MCA_H */
diff --git a/pfinet/linux-src/include/linux/md.h b/pfinet/linux-src/include/linux/md.h
new file mode 100644
index 00000000..f4f4f548
--- /dev/null
+++ b/pfinet/linux-src/include/linux/md.h
@@ -0,0 +1,300 @@
+/*
+ md.h : Multiple Devices driver for Linux
+ Copyright (C) 1994-96 Marc ZYNGIER
+ <zyngier@ufr-info-p7.ibp.fr> or
+ <maz@gloups.fdn.fr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ You should have received a copy of the GNU General Public License
+ (for example /usr/src/linux/COPYING); if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _MD_H
+#define _MD_H
+
+#include <linux/major.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/*
+ * Different major versions are not compatible.
+ * Different minor versions are only downward compatible.
+ * Different patchlevel versions are downward and upward compatible.
+ */
+#define MD_MAJOR_VERSION 0
+#define MD_MINOR_VERSION 36
+#define MD_PATCHLEVEL_VERSION 6
+
+#define MD_DEFAULT_DISK_READAHEAD (256 * 1024)
+
+/* ioctls */
+#define REGISTER_DEV _IO (MD_MAJOR, 1)
+#define START_MD _IO (MD_MAJOR, 2)
+#define STOP_MD _IO (MD_MAJOR, 3)
+#define REGISTER_DEV_NEW _IO (MD_MAJOR, 4)
+
+/*
+ personalities :
+ Byte 0 : Chunk size factor
+ Byte 1 : Fault tolerance count for each physical device
+ ( 0 means no fault tolerance,
+ 0xFF means always tolerate faults), not used by now.
+ Byte 2 : Personality
+ Byte 3 : Reserved.
+ */
+
+#define FAULT_SHIFT 8
+#define PERSONALITY_SHIFT 16
+
+#define FACTOR_MASK 0x000000FFUL
+#define FAULT_MASK 0x0000FF00UL
+#define PERSONALITY_MASK 0x00FF0000UL
+
+#define MD_RESERVED 0 /* Not used by now */
+#define LINEAR (1UL << PERSONALITY_SHIFT)
+#define STRIPED (2UL << PERSONALITY_SHIFT)
+#define RAID0 STRIPED
+#define RAID1 (3UL << PERSONALITY_SHIFT)
+#define RAID5 (4UL << PERSONALITY_SHIFT)
+#define MAX_PERSONALITY 5
+
+/*
+ * MD superblock.
+ *
+ * The MD superblock maintains some statistics on each MD configuration.
+ * Each real device in the MD set contains it near the end of the device.
+ * Some of the ideas are copied from the ext2fs implementation.
+ *
+ * We currently use 4096 bytes as follows:
+ *
+ * word offset function
+ *
+ * 0 - 31 Constant generic MD device information.
+ * 32 - 63 Generic state information.
+ * 64 - 127 Personality specific information.
+ * 128 - 511 12 32-words descriptors of the disks in the raid set.
+ * 512 - 911 Reserved.
+ * 912 - 1023 Disk specific descriptor.
+ */
+
+/*
+ * If x is the real device size in bytes, we return an apparent size of:
+ *
+ * y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
+ *
+ * and place the 4kB superblock at offset y.
+ */
+#define MD_RESERVED_BYTES (64 * 1024)
+#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
+#define MD_RESERVED_BLOCKS (MD_RESERVED_BYTES / BLOCK_SIZE)
+
+#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
+#define MD_NEW_SIZE_BLOCKS(x) ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
+
+#define MD_SB_BYTES 4096
+#define MD_SB_WORDS (MD_SB_BYTES / 4)
+#define MD_SB_BLOCKS (MD_SB_BYTES / BLOCK_SIZE)
+#define MD_SB_SECTORS (MD_SB_BYTES / 512)
+
+/*
+ * The following are counted in 32-bit words
+ */
+#define MD_SB_GENERIC_OFFSET 0
+#define MD_SB_PERSONALITY_OFFSET 64
+#define MD_SB_DISKS_OFFSET 128
+#define MD_SB_DESCRIPTOR_OFFSET 992
+
+#define MD_SB_GENERIC_CONSTANT_WORDS 32
+#define MD_SB_GENERIC_STATE_WORDS 32
+#define MD_SB_GENERIC_WORDS (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
+#define MD_SB_PERSONALITY_WORDS 64
+#define MD_SB_DISKS_WORDS 384
+#define MD_SB_DESCRIPTOR_WORDS 32
+#define MD_SB_RESERVED_WORDS (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
+#define MD_SB_EQUAL_WORDS (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
+#define MD_SB_DISKS (MD_SB_DISKS_WORDS / MD_SB_DESCRIPTOR_WORDS)
+
+/*
+ * Device "operational" state bits
+ */
+#define MD_FAULTY_DEVICE 0 /* Device is faulty / operational */
+#define MD_ACTIVE_DEVICE 1 /* Device is a part or the raid set / spare disk */
+#define MD_SYNC_DEVICE 2 /* Device is in sync with the raid set */
+
+typedef struct md_device_descriptor_s {
+ __u32 number; /* 0 Device number in the entire set */
+ __u32 major; /* 1 Device major number */
+ __u32 minor; /* 2 Device minor number */
+ __u32 raid_disk; /* 3 The role of the device in the raid set */
+ __u32 state; /* 4 Operational state */
+ __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
+} md_descriptor_t;
+
+#define MD_SB_MAGIC 0xa92b4efc
+
+/*
+ * Superblock state bits
+ */
+#define MD_SB_CLEAN 0
+#define MD_SB_ERRORS 1
+
+typedef struct md_superblock_s {
+
+ /*
+ * Constant generic information
+ */
+ __u32 md_magic; /* 0 MD identifier */
+ __u32 major_version; /* 1 major version to which the set conforms */
+ __u32 minor_version; /* 2 minor version to which the set conforms */
+ __u32 patch_version; /* 3 patchlevel version to which the set conforms */
+ __u32 gvalid_words; /* 4 Number of non-reserved words in this section */
+ __u32 set_magic; /* 5 Raid set identifier */
+ __u32 ctime; /* 6 Creation time */
+ __u32 level; /* 7 Raid personality (mirroring, raid5, ...) */
+ __u32 size; /* 8 Apparent size of each individual disk, in kB */
+ __u32 nr_disks; /* 9 Number of total disks in the raid set */
+ __u32 raid_disks; /* 10 Number of disks in a fully functional raid set */
+ __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 11];
+
+ /*
+ * Generic state information
+ */
+ __u32 utime; /* 0 Superblock update time */
+ __u32 state; /* 1 State bits (clean, ...) */
+ __u32 active_disks; /* 2 Number of currently active disks (some non-faulty disks might not be in sync) */
+ __u32 working_disks; /* 3 Number of working disks */
+ __u32 failed_disks; /* 4 Number of failed disks */
+ __u32 spare_disks; /* 5 Number of spare disks */
+ __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 6];
+
+ /*
+ * Personality information
+ */
+ __u32 parity_algorithm;
+ __u32 chunk_size;
+ __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 2];
+
+ /*
+ * Disks information
+ */
+ md_descriptor_t disks[MD_SB_DISKS];
+
+ /*
+ * Reserved
+ */
+ __u32 reserved[MD_SB_RESERVED_WORDS];
+
+ /*
+ * Active descriptor
+ */
+ md_descriptor_t descriptor;
+} md_superblock_t;
+
+#ifdef __KERNEL__
+
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <asm/semaphore.h>
+
+/*
+ * Kernel-based reconstruction is mostly working, but still requires
+ * some additional work.
+ */
+#define SUPPORT_RECONSTRUCTION 0
+
+#define MAX_REAL 8 /* Max number of physical dev per md dev */
+#define MAX_MD_DEV 4 /* Max number of md dev */
+
+#define FACTOR(a) ((a)->repartition & FACTOR_MASK)
+#define MAX_FAULT(a) (((a)->repartition & FAULT_MASK)>>8)
+#define PERSONALITY(a) ((a)->repartition & PERSONALITY_MASK)
+
+#define FACTOR_SHIFT(a) (PAGE_SHIFT + (a) - 10)
+
+struct real_dev
+{
+ kdev_t dev; /* Device number */
+ int size; /* Device size (in blocks) */
+ int offset; /* Real device offset (in blocks) in md dev
+ (only used in linear mode) */
+ struct inode *inode; /* Lock inode */
+ md_superblock_t *sb;
+ u32 sb_offset;
+};
+
+struct md_dev;
+
+#define SPARE_INACTIVE 0
+#define SPARE_WRITE 1
+#define SPARE_ACTIVE 2
+
+struct md_personality
+{
+ char *name;
+ int (*map)(struct md_dev *mddev, kdev_t *rdev,
+ unsigned long *rsector, unsigned long size);
+ int (*make_request)(struct md_dev *mddev, int rw, struct buffer_head * bh);
+ void (*end_request)(struct buffer_head * bh, int uptodate);
+ int (*run)(int minor, struct md_dev *mddev);
+ int (*stop)(int minor, struct md_dev *mddev);
+ int (*status)(char *page, int minor, struct md_dev *mddev);
+ int (*ioctl)(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+ int max_invalid_dev;
+ int (*error_handler)(struct md_dev *mddev, kdev_t dev);
+
+/*
+ * Some personalities (RAID-1, RAID-5) can get disks hot-added and
+ * hot-removed. Hot removal is different from failure. (failure marks
+ * a disk inactive, but the disk is still part of the array)
+ */
+ int (*hot_add_disk) (struct md_dev *mddev, kdev_t dev);
+ int (*hot_remove_disk) (struct md_dev *mddev, kdev_t dev);
+ int (*mark_spare) (struct md_dev *mddev, md_descriptor_t *descriptor, int state);
+};
+
+struct md_dev
+{
+ struct real_dev devices[MAX_REAL];
+ struct md_personality *pers;
+ md_superblock_t *sb;
+ int sb_dirty;
+ int repartition;
+ int busy;
+ int nb_dev;
+ void *private;
+};
+
+struct md_thread {
+ void (*run) (void *data);
+ void *data;
+ struct wait_queue *wqueue;
+ unsigned long flags;
+ struct semaphore *sem;
+ struct task_struct *tsk;
+};
+
+#define THREAD_WAKEUP 0
+
+extern struct md_dev md_dev[MAX_MD_DEV];
+extern int md_size[MAX_MD_DEV];
+extern int md_maxreadahead[MAX_MD_DEV];
+
+extern char *partition_name (kdev_t dev);
+
+extern int register_md_personality (int p_num, struct md_personality *p);
+extern int unregister_md_personality (int p_num);
+extern struct md_thread *md_register_thread (void (*run) (void *data), void *data);
+extern void md_unregister_thread (struct md_thread *thread);
+extern void md_wakeup_thread(struct md_thread *thread);
+extern int md_update_sb (int minor);
+extern int md_do_sync(struct md_dev *mddev);
+
+#endif __KERNEL__
+#endif _MD_H
diff --git a/pfinet/linux-src/include/linux/minix_fs.h b/pfinet/linux-src/include/linux/minix_fs.h
new file mode 100644
index 00000000..4682ee56
--- /dev/null
+++ b/pfinet/linux-src/include/linux/minix_fs.h
@@ -0,0 +1,127 @@
+#ifndef _LINUX_MINIX_FS_H
+#define _LINUX_MINIX_FS_H
+
+/*
+ * The minix filesystem constants/structures
+ */
+
+/*
+ * Thanks to Kees J Bot for sending me the definitions of the new
+ * minix filesystem (aka V2) with bigger inodes and 32-bit block
+ * pointers.
+ */
+
+#define MINIX_ROOT_INO 1
+
+/* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */
+#define MINIX_LINK_MAX 250
+#define MINIX2_LINK_MAX 65530
+
+#define MINIX_I_MAP_SLOTS 8
+#define MINIX_Z_MAP_SLOTS 64
+#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
+#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
+#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */
+#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */
+#define MINIX_VALID_FS 0x0001 /* Clean fs. */
+#define MINIX_ERROR_FS 0x0002 /* fs has errors. */
+
+#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
+#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
+
+#define MINIX_V1 0x0001 /* original minix fs */
+#define MINIX_V2 0x0002 /* minix V2 fs */
+
+#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version
+
+/*
+ * This is the original minix inode layout on disk.
+ * Note the 8-bit gid and atime and ctime.
+ */
+struct minix_inode {
+ __u16 i_mode;
+ __u16 i_uid;
+ __u32 i_size;
+ __u32 i_time;
+ __u8 i_gid;
+ __u8 i_nlinks;
+ __u16 i_zone[9];
+};
+
+/*
+ * The new minix inode has all the time entries, as well as
+ * long block numbers and a third indirect block (7+1+1+1
+ * instead of 7+1+1). Also, some previously 8-bit values are
+ * now 16-bit. The inode is now 64 bytes instead of 32.
+ */
+struct minix2_inode {
+ __u16 i_mode;
+ __u16 i_nlinks;
+ __u16 i_uid;
+ __u16 i_gid;
+ __u32 i_size;
+ __u32 i_atime;
+ __u32 i_mtime;
+ __u32 i_ctime;
+ __u32 i_zone[10];
+};
+
+/*
+ * minix super-block data on disk
+ */
+struct minix_super_block {
+ __u16 s_ninodes;
+ __u16 s_nzones;
+ __u16 s_imap_blocks;
+ __u16 s_zmap_blocks;
+ __u16 s_firstdatazone;
+ __u16 s_log_zone_size;
+ __u32 s_max_size;
+ __u16 s_magic;
+ __u16 s_state;
+ __u32 s_zones;
+};
+
+struct minix_dir_entry {
+ __u16 inode;
+ char name[0];
+};
+
+#ifdef __KERNEL__
+
+extern struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry);
+extern int minix_create(struct inode * dir, struct dentry *dentry, int mode);
+extern int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode);
+extern int minix_rmdir(struct inode * dir, struct dentry *dentry);
+extern int minix_unlink(struct inode * dir, struct dentry *dentry);
+extern int minix_symlink(struct inode * inode, struct dentry *dentry,
+ const char * symname);
+extern int minix_link(struct dentry * old_dentry, struct inode * dir, struct dentry *dentry);
+extern int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev);
+extern int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
+ struct inode * new_dir, struct dentry *new_dentry);
+extern struct inode * minix_new_inode(const struct inode * dir);
+extern void minix_free_inode(struct inode * inode);
+extern unsigned long minix_count_free_inodes(struct super_block *sb);
+extern int minix_new_block(struct super_block * sb);
+extern void minix_free_block(struct super_block * sb, int block);
+extern unsigned long minix_count_free_blocks(struct super_block *sb);
+
+extern int minix_bmap(struct inode *,int);
+
+extern struct buffer_head * minix_getblk(struct inode *, int, int);
+extern struct buffer_head * minix_bread(struct inode *, int, int);
+
+extern void minix_truncate(struct inode *);
+extern int init_minix_fs(void);
+extern int minix_sync_inode(struct inode *);
+extern int minix_sync_file(struct file *, struct dentry *);
+
+extern struct inode_operations minix_file_inode_operations;
+extern struct inode_operations minix_dir_inode_operations;
+extern struct inode_operations minix_symlink_inode_operations;
+extern struct dentry_operations minix_dentry_operations;
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/minix_fs_i.h b/pfinet/linux-src/include/linux/minix_fs_i.h
new file mode 100644
index 00000000..c3711e52
--- /dev/null
+++ b/pfinet/linux-src/include/linux/minix_fs_i.h
@@ -0,0 +1,14 @@
+#ifndef _MINIX_FS_I
+#define _MINIX_FS_I
+
+/*
+ * minix fs inode data in memory
+ */
+struct minix_inode_info {
+ union {
+ __u16 i1_data[16];
+ __u32 i2_data[16];
+ } u;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/minix_fs_sb.h b/pfinet/linux-src/include/linux/minix_fs_sb.h
new file mode 100644
index 00000000..54c82af9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/minix_fs_sb.h
@@ -0,0 +1,26 @@
+#ifndef _MINIX_FS_SB
+#define _MINIX_FS_SB
+
+/*
+ * minix super-block data in memory
+ */
+struct minix_sb_info {
+ unsigned long s_ninodes;
+ unsigned long s_nzones;
+ unsigned long s_imap_blocks;
+ unsigned long s_zmap_blocks;
+ unsigned long s_firstdatazone;
+ unsigned long s_log_zone_size;
+ unsigned long s_max_size;
+ int s_dirsize;
+ int s_namelen;
+ int s_link_max;
+ struct buffer_head ** s_imap;
+ struct buffer_head ** s_zmap;
+ struct buffer_head * s_sbh;
+ struct minix_super_block * s_ms;
+ unsigned short s_mount_state;
+ unsigned short s_version;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/miscdevice.h b/pfinet/linux-src/include/linux/miscdevice.h
new file mode 100644
index 00000000..e04dc1b4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/miscdevice.h
@@ -0,0 +1,43 @@
+#ifndef _LINUX_MISCDEVICE_H
+#define _LINUX_MISCDEVICE_H
+
+#define BUSMOUSE_MINOR 0
+#define PSMOUSE_MINOR 1
+#define MS_BUSMOUSE_MINOR 2
+#define ATIXL_BUSMOUSE_MINOR 3
+#define AMIGAMOUSE_MINOR 4
+#define ATARIMOUSE_MINOR 5
+#define SUN_MOUSE_MINOR 6
+#define APOLLO_MOUSE_MINOR 7
+#define PC110PAD_MINOR 9
+#define MAC_MOUSE_MINOR 10
+#define WATCHDOG_MINOR 130 /* Watchdog timer */
+#define TEMP_MINOR 131 /* Temperature Sensor */
+#define RTC_MINOR 135
+#define SUN_OPENPROM_MINOR 139
+#define NVRAM_MINOR 144
+#define I2O_MINOR 166
+#define MISC_DYNAMIC_MINOR 255
+
+#define SGI_GRAPHICS_MINOR 146
+#define SGI_OPENGL_MINOR 147
+#define SGI_GFX_MINOR 148
+#define SGI_STREAMS_MOUSE 149
+#define SGI_STREAMS_KEYBOARD 150
+/* drivers/sgi/char/usema.c */
+#define SGI_USEMACLONE 151
+
+extern int misc_init(void);
+
+struct miscdevice
+{
+ int minor;
+ const char *name;
+ struct file_operations *fops;
+ struct miscdevice * next, * prev;
+};
+
+extern int misc_register(struct miscdevice * misc);
+extern int misc_deregister(struct miscdevice * misc);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/mm.h b/pfinet/linux-src/include/linux/mm.h
new file mode 100644
index 00000000..0dc98d55
--- /dev/null
+++ b/pfinet/linux-src/include/linux/mm.h
@@ -0,0 +1,393 @@
+#ifndef _LINUX_MM_H
+#define _LINUX_MM_H
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+
+#ifdef __KERNEL__
+
+#include <linux/string.h>
+
+extern unsigned long max_mapnr;
+extern unsigned long num_physpages;
+extern void * high_memory;
+extern int page_cluster;
+
+#include <asm/page.h>
+#include <asm/atomic.h>
+
+/*
+ * Linux kernel virtual memory manager primitives.
+ * The idea being to have a "virtual" mm in the same way
+ * we have a virtual fs - giving a cleaner interface to the
+ * mm details, and allowing different kinds of memory mappings
+ * (from shared memory to executable loading to arbitrary
+ * mmap() functions).
+ */
+
+/*
+ * This struct defines a memory VMM memory area. There is one of these
+ * per VM-area/task. A VM area is any part of the process virtual memory
+ * space that has a special rule for the page-fault handlers (ie a shared
+ * library, the executable area etc).
+ */
+struct vm_area_struct {
+ struct mm_struct * vm_mm; /* VM area parameters */
+ unsigned long vm_start;
+ unsigned long vm_end;
+
+ /* linked list of VM areas per task, sorted by address */
+ struct vm_area_struct *vm_next;
+
+ pgprot_t vm_page_prot;
+ unsigned short vm_flags;
+
+ /* AVL tree of VM areas per task, sorted by address */
+ short vm_avl_height;
+ struct vm_area_struct * vm_avl_left;
+ struct vm_area_struct * vm_avl_right;
+
+ /* For areas with inode, the list inode->i_mmap, for shm areas,
+ * the list of attaches, otherwise unused.
+ */
+ struct vm_area_struct *vm_next_share;
+ struct vm_area_struct **vm_pprev_share;
+
+ struct vm_operations_struct * vm_ops;
+ unsigned long vm_offset;
+ struct file * vm_file;
+ unsigned long vm_pte; /* shared mem */
+};
+
+/*
+ * vm_flags..
+ */
+#define VM_READ 0x0001 /* currently active flags */
+#define VM_WRITE 0x0002
+#define VM_EXEC 0x0004
+#define VM_SHARED 0x0008
+
+#define VM_MAYREAD 0x0010 /* limits for mprotect() etc */
+#define VM_MAYWRITE 0x0020
+#define VM_MAYEXEC 0x0040
+#define VM_MAYSHARE 0x0080
+
+#define VM_GROWSDOWN 0x0100 /* general info on the segment */
+#define VM_GROWSUP 0x0200
+#define VM_SHM 0x0400 /* shared memory area, don't swap out */
+#define VM_DENYWRITE 0x0800 /* ETXTBSY on write attempts.. */
+
+#define VM_EXECUTABLE 0x1000
+#define VM_LOCKED 0x2000
+#define VM_IO 0x4000 /* Memory mapped I/O or similar */
+
+#define VM_STACK_FLAGS 0x0177
+
+/*
+ * mapping from the currently active vm_flags protection bits (the
+ * low four bits) to a page protection mask..
+ */
+extern pgprot_t protection_map[16];
+
+
+/*
+ * These are the virtual MM functions - opening of an area, closing and
+ * unmapping it (needed to keep files on disk up-to-date etc), pointer
+ * to the functions called when a no-page or a wp-page exception occurs.
+ */
+struct vm_operations_struct {
+ void (*open)(struct vm_area_struct * area);
+ void (*close)(struct vm_area_struct * area);
+ void (*unmap)(struct vm_area_struct *area, unsigned long, size_t);
+ void (*protect)(struct vm_area_struct *area, unsigned long, size_t, unsigned int newprot);
+ int (*sync)(struct vm_area_struct *area, unsigned long, size_t, unsigned int flags);
+ void (*advise)(struct vm_area_struct *area, unsigned long, size_t, unsigned int advise);
+ unsigned long (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access);
+ unsigned long (*wppage)(struct vm_area_struct * area, unsigned long address,
+ unsigned long page);
+ int (*swapout)(struct vm_area_struct *, struct page *);
+ pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long);
+};
+
+/*
+ * Try to keep the most commonly accessed fields in single cache lines
+ * here (16 bytes or greater). This ordering should be particularly
+ * beneficial on 32-bit processors.
+ *
+ * The first line is data used in page cache lookup, the second line
+ * is used for linear searches (eg. clock algorithm scans).
+ */
+typedef struct page {
+ /* these must be first (free area handling) */
+ struct page *next;
+ struct page *prev;
+ struct inode *inode;
+ unsigned long offset;
+ struct page *next_hash;
+ atomic_t count;
+ unsigned long flags; /* atomic flags, some possibly updated asynchronously */
+ struct wait_queue *wait;
+ struct page **pprev_hash;
+ struct buffer_head * buffers;
+} mem_map_t;
+
+/* Page flag bit values */
+#define PG_locked 0
+#define PG_error 1
+#define PG_referenced 2
+#define PG_dirty 3
+#define PG_uptodate 4
+#define PG_free_after 5
+#define PG_decr_after 6
+#define PG_swap_unlock_after 7
+#define PG_DMA 8
+#define PG_Slab 9
+#define PG_swap_cache 10
+#define PG_skip 11
+#define PG_reserved 31
+
+/* Make it prettier to test the above... */
+#define PageLocked(page) (test_bit(PG_locked, &(page)->flags))
+#define PageError(page) (test_bit(PG_error, &(page)->flags))
+#define PageReferenced(page) (test_bit(PG_referenced, &(page)->flags))
+#define PageDirty(page) (test_bit(PG_dirty, &(page)->flags))
+#define PageUptodate(page) (test_bit(PG_uptodate, &(page)->flags))
+#define PageFreeAfter(page) (test_bit(PG_free_after, &(page)->flags))
+#define PageDecrAfter(page) (test_bit(PG_decr_after, &(page)->flags))
+#define PageSwapUnlockAfter(page) (test_bit(PG_swap_unlock_after, &(page)->flags))
+#define PageDMA(page) (test_bit(PG_DMA, &(page)->flags))
+#define PageSlab(page) (test_bit(PG_Slab, &(page)->flags))
+#define PageSwapCache(page) (test_bit(PG_swap_cache, &(page)->flags))
+#define PageReserved(page) (test_bit(PG_reserved, &(page)->flags))
+
+#define PageSetSlab(page) (set_bit(PG_Slab, &(page)->flags))
+#define PageSetSwapCache(page) (set_bit(PG_swap_cache, &(page)->flags))
+
+#define PageTestandSetDirty(page) \
+ (test_and_set_bit(PG_dirty, &(page)->flags))
+#define PageTestandSetSwapCache(page) \
+ (test_and_set_bit(PG_swap_cache, &(page)->flags))
+
+#define PageClearSlab(page) (clear_bit(PG_Slab, &(page)->flags))
+#define PageClearSwapCache(page)(clear_bit(PG_swap_cache, &(page)->flags))
+
+#define PageTestandClearDirty(page) \
+ (test_and_clear_bit(PG_dirty, &(page)->flags))
+#define PageTestandClearSwapCache(page) \
+ (test_and_clear_bit(PG_swap_cache, &(page)->flags))
+
+/*
+ * Various page->flags bits:
+ *
+ * PG_reserved is set for a page which must never be accessed (which
+ * may not even be present).
+ *
+ * PG_DMA is set for those pages which lie in the range of
+ * physical addresses capable of carrying DMA transfers.
+ *
+ * Multiple processes may "see" the same page. E.g. for untouched
+ * mappings of /dev/null, all processes see the same page full of
+ * zeroes, and text pages of executables and shared libraries have
+ * only one copy in memory, at most, normally.
+ *
+ * For the non-reserved pages, page->count denotes a reference count.
+ * page->count == 0 means the page is free.
+ * page->count == 1 means the page is used for exactly one purpose
+ * (e.g. a private data page of one process).
+ *
+ * A page may be used for kmalloc() or anyone else who does a
+ * get_free_page(). In this case the page->count is at least 1, and
+ * all other fields are unused but should be 0 or NULL. The
+ * management of this page is the responsibility of the one who uses
+ * it.
+ *
+ * The other pages (we may call them "process pages") are completely
+ * managed by the Linux memory manager: I/O, buffers, swapping etc.
+ * The following discussion applies only to them.
+ *
+ * A page may belong to an inode's memory mapping. In this case,
+ * page->inode is the pointer to the inode, and page->offset is the
+ * file offset of the page (not necessarily a multiple of PAGE_SIZE).
+ *
+ * A page may have buffers allocated to it. In this case,
+ * page->buffers is a circular list of these buffer heads. Else,
+ * page->buffers == NULL.
+ *
+ * For pages belonging to inodes, the page->count is the number of
+ * attaches, plus 1 if buffers are allocated to the page.
+ *
+ * All pages belonging to an inode make up a doubly linked list
+ * inode->i_pages, using the fields page->next and page->prev. (These
+ * fields are also used for freelist management when page->count==0.)
+ * There is also a hash table mapping (inode,offset) to the page
+ * in memory if present. The lists for this hash table use the fields
+ * page->next_hash and page->pprev_hash.
+ *
+ * All process pages can do I/O:
+ * - inode pages may need to be read from disk,
+ * - inode pages which have been modified and are MAP_SHARED may need
+ * to be written to disk,
+ * - private pages which have been modified may need to be swapped out
+ * to swap space and (later) to be read back into memory.
+ * During disk I/O, PG_locked is used. This bit is set before I/O
+ * and reset when I/O completes. page->wait is a wait queue of all
+ * tasks waiting for the I/O on this page to complete.
+ * PG_uptodate tells whether the page's contents is valid.
+ * When a read completes, the page becomes uptodate, unless a disk I/O
+ * error happened.
+ * When a write completes, and PG_free_after is set, the page is
+ * freed without any further delay.
+ *
+ * For choosing which pages to swap out, inode pages carry a
+ * PG_referenced bit, which is set any time the system accesses
+ * that page through the (inode,offset) hash table.
+ *
+ * PG_skip is used on sparc/sparc64 architectures to "skip" certain
+ * parts of the address space.
+ *
+ * PG_error is set to indicate that an I/O error occurred on this page.
+ */
+
+extern mem_map_t * mem_map;
+
+/*
+ * This is timing-critical - most of the time in getting a new page
+ * goes to clearing the page. If you want a page without the clearing
+ * overhead, just use __get_free_page() directly..
+ */
+#define __get_free_page(gfp_mask) __get_free_pages((gfp_mask),0)
+#define __get_dma_pages(gfp_mask, order) __get_free_pages((gfp_mask) | GFP_DMA,(order))
+extern unsigned long FASTCALL(__get_free_pages(int gfp_mask, unsigned long gfp_order));
+
+extern inline unsigned long get_free_page(int gfp_mask)
+{
+ unsigned long page;
+
+ page = __get_free_page(gfp_mask);
+ if (page)
+ clear_page(page);
+ return page;
+}
+
+extern int low_on_memory;
+
+/* memory.c & swap.c*/
+
+#define free_page(addr) free_pages((addr),0)
+extern void FASTCALL(free_pages(unsigned long addr, unsigned long order));
+extern void FASTCALL(__free_page(struct page *));
+
+extern void show_free_areas(void);
+extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
+ unsigned long address);
+
+extern void free_page_tables(struct mm_struct * mm);
+extern void clear_page_tables(struct mm_struct *, unsigned long, int);
+extern int new_page_tables(struct task_struct * tsk);
+
+extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size);
+extern int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma);
+extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
+extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot);
+
+extern void vmtruncate(struct inode * inode, unsigned long offset);
+extern int handle_mm_fault(struct task_struct *tsk,struct vm_area_struct *vma, unsigned long address, int write_access);
+extern void make_pages_present(unsigned long addr, unsigned long end);
+
+extern int pgt_cache_water[2];
+extern int check_pgt_cache(void);
+
+extern unsigned long paging_init(unsigned long start_mem, unsigned long end_mem);
+extern void mem_init(unsigned long start_mem, unsigned long end_mem);
+extern void show_mem(void);
+extern void oom(struct task_struct * tsk);
+extern void si_meminfo(struct sysinfo * val);
+
+/* mmap.c */
+extern void vma_init(void);
+extern void merge_segments(struct mm_struct *, unsigned long, unsigned long);
+extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
+extern void build_mmap_avl(struct mm_struct *);
+extern void exit_mmap(struct mm_struct *);
+extern unsigned long get_unmapped_area(unsigned long, unsigned long);
+
+extern unsigned long do_mmap(struct file *, unsigned long, unsigned long,
+ unsigned long, unsigned long, unsigned long);
+extern int do_munmap(unsigned long, size_t);
+
+/* filemap.c */
+extern void remove_inode_page(struct page *);
+extern unsigned long page_unuse(struct page *);
+extern int shrink_mmap(int, int);
+extern void truncate_inode_pages(struct inode *, unsigned long);
+extern unsigned long get_cached_page(struct inode *, unsigned long, int);
+extern void put_cached_page(unsigned long);
+
+/*
+ * GFP bitmasks..
+ */
+#define __GFP_WAIT 0x01
+#define __GFP_LOW 0x02
+#define __GFP_MED 0x04
+#define __GFP_HIGH 0x08
+#define __GFP_IO 0x10
+#define __GFP_SWAP 0x20
+
+#define __GFP_DMA 0x80
+
+#define GFP_BUFFER (__GFP_LOW | __GFP_WAIT)
+#define GFP_ATOMIC (__GFP_HIGH)
+#define GFP_USER (__GFP_LOW | __GFP_WAIT | __GFP_IO)
+#define GFP_KERNEL (__GFP_MED | __GFP_WAIT | __GFP_IO)
+#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
+#define GFP_KSWAPD (__GFP_IO | __GFP_SWAP)
+
+/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
+ platforms, used as appropriate on others */
+
+#define GFP_DMA __GFP_DMA
+
+/* vma is the first one with address < vma->vm_end,
+ * and even address < vma->vm_start. Have to extend vma. */
+static inline int expand_stack(struct vm_area_struct * vma, unsigned long address)
+{
+ unsigned long grow;
+
+ address &= PAGE_MASK;
+ grow = vma->vm_start - address;
+ if ((vma->vm_end - address
+ > current->rlim[RLIMIT_STACK].rlim_cur) ||
+ ((current->rlim[RLIMIT_AS].rlim_cur < RLIM_INFINITY) &&
+ ((vma->vm_mm->total_vm << PAGE_SHIFT) + grow
+ > current->rlim[RLIMIT_AS].rlim_cur)))
+ return -ENOMEM;
+ vma->vm_start = address;
+ vma->vm_offset -= grow;
+ vma->vm_mm->total_vm += grow >> PAGE_SHIFT;
+ if (vma->vm_flags & VM_LOCKED)
+ vma->vm_mm->locked_vm += grow >> PAGE_SHIFT;
+ return 0;
+}
+
+/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
+extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);
+
+/* Look up the first VMA which intersects the interval start_addr..end_addr-1,
+ NULL if none. Assume start_addr < end_addr. */
+static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr)
+{
+ struct vm_area_struct * vma = find_vma(mm,start_addr);
+
+ if (vma && end_addr <= vma->vm_start)
+ vma = NULL;
+ return vma;
+}
+
+#define buffer_under_min() ((buffermem >> PAGE_SHIFT) * 100 < \
+ buffer_mem.min_percent * num_physpages)
+#define pgcache_under_min() (page_cache_size * 100 < \
+ page_cache.min_percent * num_physpages)
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/mman.h b/pfinet/linux-src/include/linux/mman.h
new file mode 100644
index 00000000..3bc0430b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/mman.h
@@ -0,0 +1,8 @@
+#ifndef _LINUX_MMAN_H
+#define _LINUX_MMAN_H
+
+#include <asm/mman.h>
+
+#define MREMAP_MAYMOVE 1
+
+#endif /* _LINUX_MMAN_H */
diff --git a/pfinet/linux-src/include/linux/modsetver.h b/pfinet/linux-src/include/linux/modsetver.h
new file mode 100644
index 00000000..7d0b9d37
--- /dev/null
+++ b/pfinet/linux-src/include/linux/modsetver.h
@@ -0,0 +1,10 @@
+/* Symbol versioning nastiness. */
+
+#define __SYMBOL_VERSION(x) __ver_ ## x
+#define __VERSIONED_SYMBOL2(x,v) x ## _R ## v
+#define __VERSIONED_SYMBOL1(x,v) __VERSIONED_SYMBOL2(x,v)
+#define __VERSIONED_SYMBOL(x) __VERSIONED_SYMBOL1(x,__SYMBOL_VERSION(x))
+
+#ifndef _set_ver
+#define _set_ver(x) __VERSIONED_SYMBOL(x)
+#endif
diff --git a/pfinet/linux-src/include/linux/module.h b/pfinet/linux-src/include/linux/module.h
new file mode 100644
index 00000000..94cce874
--- /dev/null
+++ b/pfinet/linux-src/include/linux/module.h
@@ -0,0 +1,287 @@
+/*
+ * Dynamic loading of modules into the kernel.
+ *
+ * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
+ */
+
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/config.h>
+
+#ifdef __GENKSYMS__
+# define _set_ver(sym) sym
+# undef MODVERSIONS
+# define MODVERSIONS
+#else /* ! __GENKSYMS__ */
+# if !defined(MODVERSIONS) && defined(EXPORT_SYMTAB)
+# define _set_ver(sym) sym
+# include <linux/modversions.h>
+# endif
+#endif /* __GENKSYMS__ */
+
+#include <asm/atomic.h>
+
+/* Don't need to bring in all of uaccess.h just for this decl. */
+struct exception_table_entry;
+
+/* Used by get_kernel_syms, which is obsolete. */
+struct kernel_sym
+{
+ unsigned long value;
+ char name[60]; /* should have been 64-sizeof(long); oh well */
+};
+
+struct module_symbol
+{
+ unsigned long value;
+ const char *name;
+};
+
+struct module_ref
+{
+ struct module *dep; /* "parent" pointer */
+ struct module *ref; /* "child" pointer */
+ struct module_ref *next_ref;
+};
+
+/* TBD */
+struct module_persist;
+
+struct module
+{
+ unsigned long size_of_struct; /* == sizeof(module) */
+ struct module *next;
+ const char *name;
+ unsigned long size;
+
+ union
+ {
+ atomic_t usecount;
+ long pad;
+ } uc; /* Needs to keep its size - so says rth */
+
+ unsigned long flags; /* AUTOCLEAN et al */
+
+ unsigned nsyms;
+ unsigned ndeps;
+
+ struct module_symbol *syms;
+ struct module_ref *deps;
+ struct module_ref *refs;
+ int (*init)(void);
+ void (*cleanup)(void);
+ const struct exception_table_entry *ex_table_start;
+ const struct exception_table_entry *ex_table_end;
+#ifdef __alpha__
+ unsigned long gp;
+#endif
+ /* Members past this point are extensions to the basic
+ module support and are optional. Use mod_opt_member()
+ to examine them. */
+ const struct module_persist *persist_start;
+ const struct module_persist *persist_end;
+ int (*can_unload)(void);
+};
+
+struct module_info
+{
+ unsigned long addr;
+ unsigned long size;
+ unsigned long flags;
+ long usecount;
+};
+
+/* Bits of module.flags. */
+
+#define MOD_UNINITIALIZED 0
+#define MOD_RUNNING 1
+#define MOD_DELETED 2
+#define MOD_AUTOCLEAN 4
+#define MOD_VISITED 8
+#define MOD_USED_ONCE 16
+#define MOD_JUST_FREED 32
+
+/* Values for query_module's which. */
+
+#define QM_MODULES 1
+#define QM_DEPS 2
+#define QM_REFS 3
+#define QM_SYMBOLS 4
+#define QM_INFO 5
+
+/* When struct module is extended, we must test whether the new member
+ is present in the header received from insmod before we can use it.
+ This function returns true if the member is present. */
+
+#define mod_member_present(mod,member) \
+ ((unsigned long)(&((struct module *)0L)->member + 1) \
+ <= (mod)->size_of_struct)
+
+/* Backwards compatibility definition. */
+
+#define GET_USE_COUNT(module) (atomic_read(&(module)->uc.usecount))
+
+/* Poke the use count of a module. */
+
+#define __MOD_INC_USE_COUNT(mod) \
+ (atomic_inc(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED|MOD_USED_ONCE)
+#define __MOD_DEC_USE_COUNT(mod) \
+ (atomic_dec(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED)
+#define __MOD_IN_USE(mod) \
+ (mod_member_present((mod), can_unload) && (mod)->can_unload \
+ ? (mod)->can_unload() : atomic_read(&(mod)->uc.usecount))
+
+/* Indirect stringification. */
+
+#define __MODULE_STRING_1(x) #x
+#define __MODULE_STRING(x) __MODULE_STRING_1(x)
+
+/* Find a symbol exported by the kernel or another module */
+extern unsigned long get_module_symbol(char *, char *);
+
+#if defined(MODULE) && !defined(__GENKSYMS__)
+
+/* Embedded module documentation macros. */
+
+/* For documentation purposes only. */
+
+#define MODULE_AUTHOR(name) \
+const char __module_author[] __attribute__((section(".modinfo"))) = \
+"author=" name
+
+#define MODULE_DESCRIPTION(desc) \
+const char __module_description[] __attribute__((section(".modinfo"))) = \
+"description=" desc
+
+/* Could potentially be used by kmod... */
+
+#define MODULE_SUPPORTED_DEVICE(dev) \
+const char __module_device[] __attribute__((section(".modinfo"))) = \
+"device=" dev
+
+/* Used to verify parameters given to the module. The TYPE arg should
+ be a string in the following format:
+ [min[-max]]{b,h,i,l,s}
+ The MIN and MAX specifiers delimit the length of the array. If MAX
+ is omitted, it defaults to MIN; if both are omitted, the default is 1.
+ The final character is a type specifier:
+ b byte
+ h short
+ i int
+ l long
+ s string
+*/
+
+#define MODULE_PARM(var,type) \
+const char __module_parm_##var[] \
+__attribute__((section(".modinfo"))) = \
+"parm_" __MODULE_STRING(var) "=" type
+
+#define MODULE_PARM_DESC(var,desc) \
+const char __module_parm_desc_##var[] \
+__attribute__((section(".modinfo"))) = \
+"parm_desc_" __MODULE_STRING(var) "=" desc
+
+/* The attributes of a section are set the first time the section is
+ seen; we want .modinfo to not be allocated. */
+
+__asm__(".section .modinfo\n\t.previous");
+
+/* Define the module variable, and usage macros. */
+extern struct module __this_module;
+
+#define MOD_INC_USE_COUNT __MOD_INC_USE_COUNT(&__this_module)
+#define MOD_DEC_USE_COUNT __MOD_DEC_USE_COUNT(&__this_module)
+#define MOD_IN_USE __MOD_IN_USE(&__this_module)
+
+#ifndef __NO_VERSION__
+#include <linux/version.h>
+const char __module_kernel_version[] __attribute__((section(".modinfo"))) =
+"kernel_version=" UTS_RELEASE;
+#ifdef MODVERSIONS
+const char __module_using_checksums[] __attribute__((section(".modinfo"))) =
+"using_checksums=1";
+#endif
+#endif
+
+#else /* MODULE */
+
+#define MODULE_AUTHOR(name)
+#define MODULE_DESCRIPTION(desc)
+#define MODULE_SUPPORTED_DEVICE(name)
+#define MODULE_PARM(var,type)
+#define MODULE_PARM_DESC(var,desc)
+
+#ifndef __GENKSYMS__
+
+#define MOD_INC_USE_COUNT do { } while (0)
+#define MOD_DEC_USE_COUNT do { } while (0)
+#define MOD_IN_USE 1
+
+extern struct module *module_list;
+
+#endif /* !__GENKSYMS__ */
+
+#endif /* MODULE */
+
+/* Export a symbol either from the kernel or a module.
+
+ In the kernel, the symbol is added to the kernel's global symbol table.
+
+ In a module, it controls which variables are exported. If no
+ variables are explicitly exported, the action is controled by the
+ insmod -[xX] flags. Otherwise, only the variables listed are exported.
+ This obviates the need for the old register_symtab() function. */
+
+#if defined(__GENKSYMS__)
+
+/* We want the EXPORT_SYMBOL tag left intact for recognition. */
+
+#elif !defined(AUTOCONF_INCLUDED)
+
+#define __EXPORT_SYMBOL(sym,str) error config_must_be_included_before_module
+#define EXPORT_SYMBOL(var) error config_must_be_included_before_module
+#define EXPORT_SYMBOL_NOVERS(var) error config_must_be_included_before_module
+
+#elif !defined(CONFIG_MODULES)
+
+#define __EXPORT_SYMBOL(sym,str)
+#define EXPORT_SYMBOL(var)
+#define EXPORT_SYMBOL_NOVERS(var)
+
+#elif !defined(EXPORT_SYMTAB)
+
+/* If things weren't set up in the Makefiles to get EXPORT_SYMTAB defined,
+ then they weren't set up to run genksyms properly so MODVERSIONS breaks. */
+#define __EXPORT_SYMBOL(sym,str) error EXPORT_SYMTAB_not_defined
+#define EXPORT_SYMBOL(var) error EXPORT_SYMTAB_not_defined
+#define EXPORT_SYMBOL_NOVERS(var) error EXPORT_SYMTAB_not_defined
+
+#else
+
+#define __EXPORT_SYMBOL(sym, str) \
+const char __kstrtab_##sym[] \
+__attribute__((section(".kstrtab"))) = str; \
+const struct module_symbol __ksymtab_##sym \
+__attribute__((section("__ksymtab"))) = \
+{ (unsigned long)&sym, __kstrtab_##sym }
+
+#if defined(MODVERSIONS) || !defined(CONFIG_MODVERSIONS)
+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
+#else
+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
+#endif
+
+#define EXPORT_SYMBOL_NOVERS(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
+
+#endif /* __GENKSYMS__ */
+
+#ifdef MODULE
+/* Force a module to export no symbols. */
+#define EXPORT_NO_SYMBOLS __asm__(".section __ksymtab\n.previous")
+#else
+#define EXPORT_NO_SYMBOLS
+#endif /* MODULE */
+
+#endif /* _LINUX_MODULE_H */
diff --git a/pfinet/linux-src/include/linux/mount.h b/pfinet/linux-src/include/linux/mount.h
new file mode 100644
index 00000000..1e697071
--- /dev/null
+++ b/pfinet/linux-src/include/linux/mount.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Definitions for mount interface. This describes the in the kernel build
+ * linkedlist with mounted filesystems.
+ *
+ * Author: Marco van Wieringen <mvw@planets.elm.net>
+ *
+ * Version: $Id: mount.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $
+ *
+ */
+#ifndef _LINUX_MOUNT_H
+#define _LINUX_MOUNT_H
+
+#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
+#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */
+
+struct quota_mount_options
+{
+ unsigned int flags; /* Flags for diskquotas on this device */
+ struct semaphore dqio_sem; /* lock device while I/O in progress */
+ struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */
+ struct file *files[MAXQUOTAS]; /* fp's to quotafiles */
+ time_t inode_expire[MAXQUOTAS]; /* expiretime for inode-quota */
+ time_t block_expire[MAXQUOTAS]; /* expiretime for block-quota */
+ char rsquash[MAXQUOTAS]; /* for quotas treat root as any other user */
+};
+
+struct vfsmount
+{
+ kdev_t mnt_dev; /* Device this applies to */
+ char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
+ char *mnt_dirname; /* Name of directory mounted on */
+ unsigned int mnt_flags; /* Flags of this device */
+ struct super_block *mnt_sb; /* pointer to superblock */
+ struct quota_mount_options mnt_dquot; /* Diskquota specific mount options */
+ struct vfsmount *mnt_next; /* pointer to next in linkedlist */
+};
+
+struct vfsmount *lookup_vfsmnt(kdev_t dev);
+
+/*
+ * Umount options
+ */
+
+#define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */
+
+#endif /* _LINUX_MOUNT_H */
diff --git a/pfinet/linux-src/include/linux/mpp.h b/pfinet/linux-src/include/linux/mpp.h
new file mode 100644
index 00000000..2dd02ff4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/mpp.h
@@ -0,0 +1,18 @@
+#ifndef _LINUX_MPP_H
+#define _LINUX_MPP_H
+
+/*
+ * Definitions related to Massively Parallel Processing support.
+ */
+
+/* All mpp implementations must supply these functions */
+
+extern void mpp_init(void);
+extern void mpp_hw_init(void);
+extern void mpp_procfs_init(void);
+
+extern int mpp_num_cells(void);
+extern int mpp_cid(void);
+extern int get_mppinfo(char *buffer);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/mroute.h b/pfinet/linux-src/include/linux/mroute.h
new file mode 100644
index 00000000..b57519b7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/mroute.h
@@ -0,0 +1,223 @@
+#ifndef __LINUX_MROUTE_H
+#define __LINUX_MROUTE_H
+
+#include <linux/sockios.h>
+#include <linux/in.h>
+
+/*
+ * Based on the MROUTING 3.5 defines primarily to keep
+ * source compatibility with BSD.
+ *
+ * See the mrouted code for the original history.
+ *
+ * Protocol Independent Multicast (PIM) data structures included
+ * Carlos Picoto (cap@di.fc.ul.pt)
+ *
+ */
+
+#define MRT_BASE 200
+#define MRT_INIT (MRT_BASE) /* Activate the kernel mroute code */
+#define MRT_DONE (MRT_BASE+1) /* Shutdown the kernel mroute */
+#define MRT_ADD_VIF (MRT_BASE+2) /* Add a virtual interface */
+#define MRT_DEL_VIF (MRT_BASE+3) /* Delete a virtual interface */
+#define MRT_ADD_MFC (MRT_BASE+4) /* Add a multicast forwarding entry */
+#define MRT_DEL_MFC (MRT_BASE+5) /* Delete a multicast forwarding entry */
+#define MRT_VERSION (MRT_BASE+6) /* Get the kernel multicast version */
+#define MRT_ASSERT (MRT_BASE+7) /* Activate PIM assert mode */
+#define MRT_PIM (MRT_BASE+8) /* enable PIM code */
+
+#define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */
+#define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
+#define SIOCGETRPF (SIOCPROTOPRIVATE+2)
+
+#define MAXVIFS 32
+typedef unsigned long vifbitmap_t; /* User mode code depends on this lot */
+typedef unsigned short vifi_t;
+#define ALL_VIFS ((vifi_t)(-1))
+
+/*
+ * Same idea as select
+ */
+
+#define VIFM_SET(n,m) ((m)|=(1<<(n)))
+#define VIFM_CLR(n,m) ((m)&=~(1<<(n)))
+#define VIFM_ISSET(n,m) ((m)&(1<<(n)))
+#define VIFM_CLRALL(m) ((m)=0)
+#define VIFM_COPY(mfrom,mto) ((mto)=(mfrom))
+#define VIFM_SAME(m1,m2) ((m1)==(m2))
+
+/*
+ * Passed by mrouted for an MRT_ADD_VIF - again we use the
+ * mrouted 3.6 structures for compatibility
+ */
+
+struct vifctl {
+ vifi_t vifc_vifi; /* Index of VIF */
+ unsigned char vifc_flags; /* VIFF_ flags */
+ unsigned char vifc_threshold; /* ttl limit */
+ unsigned int vifc_rate_limit; /* Rate limiter values (NI) */
+ struct in_addr vifc_lcl_addr; /* Our address */
+ struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */
+};
+
+#define VIFF_TUNNEL 0x1 /* IPIP tunnel */
+#define VIFF_SRCRT 0x2 /* NI */
+#define VIFF_REGISTER 0x4 /* register vif */
+
+/*
+ * Cache manipulation structures for mrouted and PIMd
+ */
+
+struct mfcctl
+{
+ struct in_addr mfcc_origin; /* Origin of mcast */
+ struct in_addr mfcc_mcastgrp; /* Group in question */
+ vifi_t mfcc_parent; /* Where it arrived */
+ unsigned char mfcc_ttls[MAXVIFS]; /* Where it is going */
+ unsigned int mfcc_pkt_cnt; /* pkt count for src-grp */
+ unsigned int mfcc_byte_cnt;
+ unsigned int mfcc_wrong_if;
+ int mfcc_expire;
+};
+
+/*
+ * Group count retrieval for mrouted
+ */
+
+struct sioc_sg_req
+{
+ struct in_addr src;
+ struct in_addr grp;
+ unsigned long pktcnt;
+ unsigned long bytecnt;
+ unsigned long wrong_if;
+};
+
+/*
+ * To get vif packet counts
+ */
+
+struct sioc_vif_req
+{
+ vifi_t vifi; /* Which iface */
+ unsigned long icount; /* In packets */
+ unsigned long ocount; /* Out packets */
+ unsigned long ibytes; /* In bytes */
+ unsigned long obytes; /* Out bytes */
+};
+
+/*
+ * This is the format the mroute daemon expects to see IGMP control
+ * data. Magically happens to be like an IP packet as per the original
+ */
+
+struct igmpmsg
+{
+ __u32 unused1,unused2;
+ unsigned char im_msgtype; /* What is this */
+ unsigned char im_mbz; /* Must be zero */
+ unsigned char im_vif; /* Interface (this ought to be a vifi_t!) */
+ unsigned char unused3;
+ struct in_addr im_src,im_dst;
+};
+
+/*
+ * That's all usermode folks
+ */
+
+#ifdef __KERNEL__
+extern struct sock *mroute_socket;
+extern int ip_mroute_setsockopt(struct sock *, int, char *, int);
+extern int ip_mroute_getsockopt(struct sock *, int, char *, int *);
+extern int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern void mroute_close(struct sock *sk);
+extern void ipmr_forward(struct sk_buff *skb, int is_frag);
+extern int ip_mr_find_tunnel(__u32, __u32);
+extern void ip_mr_init(void);
+
+
+struct vif_device
+{
+ struct device *dev; /* Device we are using */
+ unsigned long bytes_in,bytes_out;
+ unsigned long pkt_in,pkt_out; /* Statistics */
+ unsigned long rate_limit; /* Traffic shaping (NI) */
+ unsigned char threshold; /* TTL threshold */
+ unsigned short flags; /* Control flags */
+ __u32 local,remote; /* Addresses(remote for tunnels)*/
+ int link; /* Physical interface index */
+};
+
+struct mfc_cache
+{
+ struct mfc_cache *next; /* Next entry on cache line */
+ __u32 mfc_mcastgrp; /* Group the entry belongs to */
+ __u32 mfc_origin; /* Source of packet */
+ vifi_t mfc_parent; /* Source interface */
+ struct timer_list mfc_timer; /* Expiry timer */
+ int mfc_flags; /* Flags on line */
+ struct sk_buff_head mfc_unresolved; /* Unresolved buffers */
+ int mfc_queuelen; /* Unresolved buffer counter */
+ unsigned long mfc_last_assert;
+ int mfc_minvif;
+ int mfc_maxvif;
+ unsigned long mfc_bytes;
+ unsigned long mfc_pkt;
+ unsigned long mfc_wrong_if;
+ unsigned char mfc_ttls[MAXVIFS]; /* TTL thresholds */
+};
+
+#define MFC_QUEUED 1
+#define MFC_RESOLVED 2
+#define MFC_NOTIFY 4
+
+
+#define MFC_LINES 64
+
+#ifdef __BIG_ENDIAN
+#define MFC_HASH(a,b) ((((a)>>24)^((b)>>26))&(MFC_LINES-1))
+#else
+#define MFC_HASH(a,b) (((a)^((b)>>2))&(MFC_LINES-1))
+#endif
+
+#endif
+
+
+#define MFC_ASSERT_THRESH (3*HZ) /* Maximal freq. of asserts */
+
+/*
+ * Pseudo messages used by mrouted
+ */
+
+#define IGMPMSG_NOCACHE 1 /* Kern cache fill request to mrouted */
+#define IGMPMSG_WRONGVIF 2 /* For PIM assert processing (unused) */
+#define IGMPMSG_WHOLEPKT 3 /* For PIM Register processing */
+
+#ifdef __KERNEL__
+
+#define PIM_V1_VERSION __constant_htonl(0x10000000)
+#define PIM_V1_REGISTER 1
+
+#define PIM_VERSION 2
+#define PIM_REGISTER 1
+
+#define PIM_NULL_REGISTER __constant_htonl(0x40000000)
+
+/* PIMv2 register message header layout (ietf-draft-idmr-pimvsm-v2-00.ps */
+
+struct pimreghdr
+{
+ __u8 type;
+ __u8 reserved;
+ __u16 csum;
+ __u32 flags;
+};
+
+extern int pim_rcv(struct sk_buff * , unsigned short);
+extern int pim_rcv_v1(struct sk_buff * , unsigned short len);
+
+struct rtmsg;
+extern int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/msdos_fs.h b/pfinet/linux-src/include/linux/msdos_fs.h
new file mode 100644
index 00000000..f9ef19e8
--- /dev/null
+++ b/pfinet/linux-src/include/linux/msdos_fs.h
@@ -0,0 +1,336 @@
+#ifndef _LINUX_MSDOS_FS_H
+#define _LINUX_MSDOS_FS_H
+
+/*
+ * The MS-DOS filesystem constants/structures
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/fd.h>
+
+#include <asm/byteorder.h>
+
+#define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */
+#define SECTOR_SIZE 512 /* sector size (bytes) */
+#define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */
+#define MSDOS_DPB (MSDOS_DPS) /* dir entries per block */
+#define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */
+#define MSDOS_DPS (SECTOR_SIZE/sizeof(struct msdos_dir_entry))
+#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */
+#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */
+
+#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */
+
+#define FAT_CACHE 8 /* FAT cache size */
+
+#define MSDOS_MAX_EXTRA 3 /* tolerate up to that number of clusters which are
+ inaccessible because the FAT is too short */
+
+#define ATTR_RO 1 /* read-only */
+#define ATTR_HIDDEN 2 /* hidden */
+#define ATTR_SYS 4 /* system */
+#define ATTR_VOLUME 8 /* volume label */
+#define ATTR_DIR 16 /* directory */
+#define ATTR_ARCH 32 /* archived */
+
+#define ATTR_NONE 0 /* no attribute bits */
+#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
+ /* attribute bits that are copied "as is" */
+#define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
+ /* bits that are used by the Windows 95/Windows NT extended FAT */
+
+#define ATTR_DIR_READ_BOTH 512 /* read both short and long names from the
+ * vfat filesystem. This is used by Samba
+ * to export the vfat filesystem with correct
+ * shortnames. */
+#define ATTR_DIR_READ_SHORT 1024
+
+#define CASE_LOWER_BASE 8 /* base is lower case */
+#define CASE_LOWER_EXT 16 /* extension is lower case */
+
+#define SCAN_ANY 0 /* either hidden or not */
+#define SCAN_HID 1 /* only hidden */
+#define SCAN_NOTHID 2 /* only not hidden */
+#define SCAN_NOTANY 3 /* test name, then use SCAN_HID or SCAN_NOTHID */
+
+#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
+#define IS_FREE(n) (!*(n) || *(const unsigned char *) (n) == DELETED_FLAG || \
+ *(const unsigned char *) (n) == FD_FILL_BYTE)
+
+#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
+ /* valid file mode bits */
+
+#define MSDOS_SB(s) (&((s)->u.msdos_sb))
+#define MSDOS_I(i) (&((i)->u.msdos_i))
+
+#define MSDOS_NAME 11 /* maximum name length */
+#define MSDOS_LONGNAME 256 /* maximum name length */
+#define MSDOS_SLOTS 21 /* max # of slots needed for short and long names */
+#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */
+#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */
+
+#define MSDOS_FAT12 4078 /* maximum number of clusters in a 12 bit FAT */
+
+#define EOF_FAT12 0xFF8 /* standard EOF */
+#define EOF_FAT16 0xFFF8
+#define EOF_FAT32 0xFFFFFF8
+#define EOF_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? EOF_FAT32 : \
+ MSDOS_SB(s)->fat_bits == 16 ? EOF_FAT16 : EOF_FAT12)
+
+/*
+ * Inode flags
+ */
+#define FAT_BINARY_FL 0x00000001 /* File contains binary data */
+
+/*
+ * ioctl commands
+ */
+#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
+#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
+
+/*
+ * Conversion from and to little-endian byte order. (no-op on i386/i486)
+ *
+ * Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian,
+ * BE = big-endian, c: W = word (16 bits), L = longword (32 bits)
+ */
+
+#define CF_LE_W(v) le16_to_cpu(v)
+#define CF_LE_L(v) le32_to_cpu(v)
+#define CT_LE_W(v) cpu_to_le16(v)
+#define CT_LE_L(v) cpu_to_le32(v)
+
+struct fat_boot_sector {
+ __s8 ignored[3]; /* Boot strap short or near jump */
+ __s8 system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+ __u8 sector_size[2]; /* bytes per logical sector */
+ __u8 cluster_size; /* sectors/cluster */
+ __u16 reserved; /* reserved sectors */
+ __u8 fats; /* number of FATs */
+ __u8 dir_entries[2]; /* root directory entries */
+ __u8 sectors[2]; /* number of sectors */
+ __u8 media; /* media code (unused) */
+ __u16 fat_length; /* sectors/FAT */
+ __u16 secs_track; /* sectors per track */
+ __u16 heads; /* number of heads */
+ __u32 hidden; /* hidden sectors (unused) */
+ __u32 total_sect; /* number of sectors (if sectors == 0) */
+
+ /* The following fields are only used by FAT32 */
+ __u32 fat32_length; /* sectors/FAT */
+ __u16 flags; /* bit 8: fat mirroring, low 4: active fat */
+ __u8 version[2]; /* major, minor filesystem version */
+ __u32 root_cluster; /* first cluster in root directory */
+ __u16 info_sector; /* filesystem info sector */
+ __u16 backup_boot; /* backup boot sector */
+ __u16 reserved2[6]; /* Unused */
+};
+
+struct fat_boot_fsinfo {
+ __u32 reserved1; /* Nothing as far as I can tell */
+ __u32 signature; /* 0x61417272L */
+ __u32 free_clusters; /* Free cluster count. -1 if unknown */
+ __u32 next_cluster; /* Most recently allocated cluster.
+ * Unused under Linux. */
+ __u32 reserved2[4];
+};
+
+struct msdos_dir_entry {
+ __s8 name[8],ext[3]; /* name and extension */
+ __u8 attr; /* attribute bits */
+ __u8 lcase; /* Case for base and extension */
+ __u8 ctime_ms; /* Creation time, milliseconds */
+ __u16 ctime; /* Creation time */
+ __u16 cdate; /* Creation date */
+ __u16 adate; /* Last access date */
+ __u16 starthi; /* High 16 bits of cluster in FAT32 */
+ __u16 time,date,start;/* time, date and first cluster */
+ __u32 size; /* file size (in bytes) */
+};
+
+/* Up to 13 characters of the name */
+struct msdos_dir_slot {
+ __u8 id; /* sequence number for slot */
+ __u8 name0_4[10]; /* first 5 characters in name */
+ __u8 attr; /* attribute byte */
+ __u8 reserved; /* always 0 */
+ __u8 alias_checksum; /* checksum for 8.3 alias */
+ __u8 name5_10[12]; /* 6 more characters in name */
+ __u16 start; /* starting cluster number, 0 in long slots */
+ __u8 name11_12[4]; /* last 2 characters in name */
+};
+
+struct vfat_slot_info {
+ int is_long; /* was the found entry long */
+ int long_slots; /* number of long slots in filename */
+ int total_slots; /* total slots (long and short) */
+ loff_t longname_offset; /* dir offset for longname start */
+ loff_t shortname_offset; /* dir offset for shortname start */
+ int ino; /* ino for the file */
+};
+
+/* Determine whether this FS has kB-aligned data. */
+#define MSDOS_CAN_BMAP(mib) (!(((mib)->cluster_size & 1) || \
+ ((mib)->data_start & 1)))
+
+/* Convert attribute bits and a mask to the UNIX mode. */
+#define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO))
+
+/* Convert the UNIX mode to MS-DOS attribute bits. */
+#define MSDOS_MKATTR(m) ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO)
+
+
+#ifdef __KERNEL__
+
+struct fat_cache {
+ kdev_t device; /* device number. 0 means unused. */
+ int start_cluster; /* first cluster of the chain. */
+ int file_cluster; /* cluster number in the file. */
+ int disk_cluster; /* cluster number on disk. */
+ struct fat_cache *next; /* next cache entry */
+};
+
+/* misc.c */
+extern int fat_is_binary(char conversion,char *extension);
+extern void lock_fat(struct super_block *sb);
+extern void unlock_fat(struct super_block *sb);
+extern int fat_add_cluster(struct inode *inode);
+extern struct buffer_head *fat_add_cluster1(struct inode *inode);
+extern int date_dos2unix(__u16 time, __u16 date);
+extern void fat_fs_panic(struct super_block *s,const char *msg);
+extern void fat_lock_creation(void);
+extern void fat_unlock_creation(void);
+extern void fat_date_unix2dos(int unix_date,__u16 *time, __u16 *date);
+extern int fat__get_entry(struct inode *dir,loff_t *pos,struct buffer_head **bh,
+ struct msdos_dir_entry **de,int *ino);
+static __inline__ int fat_get_entry(struct inode *dir,loff_t *pos,
+ struct buffer_head **bh,struct msdos_dir_entry **de,int *ino)
+{
+ /* Fast stuff first */
+ if (*bh && *de &&
+ (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_DPB-1) {
+ *pos += sizeof(struct msdos_dir_entry);
+ (*de)++;
+ (*ino)++;
+ return 0;
+ }
+ return fat__get_entry(dir,pos,bh,de,ino);
+}
+extern int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
+ struct msdos_dir_entry **res_de,int *ino);
+extern int fat_parent_ino(struct inode *dir,int locked);
+extern int fat_subdirs(struct inode *dir);
+void fat_clusters_flush(struct super_block *sb);
+
+/* fat.c */
+extern int fat_access(struct super_block *sb,int nr,int new_value);
+extern int fat_smap(struct inode *inode,int sector);
+extern int fat_free(struct inode *inode,int skip);
+void fat_cache_inval_inode(struct inode *inode);
+void fat_cache_inval_dev(kdev_t device);
+extern void fat_cache_init(void);
+void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu);
+void fat_cache_add(struct inode *inode,int f_clu,int d_clu);
+int fat_get_cluster(struct inode *inode,int cluster);
+
+/* inode.c */
+extern void fat_hash_init(void);
+extern int fat_bmap(struct inode *inode,int block);
+extern int fat_notify_change(struct dentry *, struct iattr *);
+extern void fat_clear_inode(struct inode *inode);
+extern void fat_delete_inode(struct inode *inode);
+extern void fat_put_super(struct super_block *sb);
+extern void fat_attach(struct inode *inode, int ino);
+extern void fat_detach(struct inode *inode);
+extern struct inode *fat_iget(struct super_block*,int);
+extern struct inode *fat_build_inode(struct super_block*,struct msdos_dir_entry*,int,int*);
+extern struct super_block *fat_read_super(struct super_block *s, void *data, int silent, struct inode_operations *dir_ops);
+extern void msdos_put_super(struct super_block *sb);
+extern int fat_statfs(struct super_block *sb,struct statfs *buf, int);
+extern void fat_write_inode(struct inode *inode);
+
+/* dir.c */
+extern struct file_operations fat_dir_operations;
+extern int fat_search_long(struct inode *dir, const char *name, int len,
+ int anycase, loff_t *spos, loff_t *lpos);
+extern int fat_readdir(struct file *filp,
+ void *dirent, filldir_t);
+extern int fat_dir_ioctl(struct inode * inode, struct file * filp,
+ unsigned int cmd, unsigned long arg);
+int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
+ struct msdos_dir_entry **de, int *ino);
+int fat_dir_empty(struct inode *dir);
+
+/* file.c */
+extern struct inode_operations fat_file_inode_operations;
+extern struct inode_operations fat_file_inode_operations_1024;
+extern struct inode_operations fat_file_inode_operations_readpage;
+extern ssize_t fat_file_read(struct file *, char *, size_t, loff_t *);
+extern ssize_t fat_file_write(struct file *, const char *, size_t, loff_t *);
+extern void fat_truncate(struct inode *inode);
+
+/* mmap.c */
+extern int fat_mmap(struct file *, struct vm_area_struct *);
+extern int fat_readpage(struct file *, struct page *);
+
+
+/* vfat.c */
+extern int init_vfat_fs(void);
+
+
+/* msdosfs_syms.c */
+extern int init_msdos_fs(void);
+extern struct file_system_type msdos_fs_type;
+
+/* msdos.c */
+extern struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent);
+
+/* msdos.c - these are for Umsdos */
+extern void msdos_read_inode(struct inode *inode);
+extern struct dentry *msdos_lookup(struct inode *dir,struct dentry *);
+extern int msdos_create(struct inode *dir,struct dentry *dentry,int mode);
+extern int msdos_rmdir(struct inode *dir,struct dentry *dentry);
+extern int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode);
+extern int msdos_unlink(struct inode *dir,struct dentry *dentry);
+extern int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
+ struct inode *new_dir,struct dentry *new_dentry);
+
+/* nls.c */
+extern int init_fat_nls(void);
+extern struct fat_nls_table *fat_load_nls(int codepage);
+
+/* tables.c */
+extern unsigned char fat_uni2esc[];
+extern unsigned char fat_esc2uni[];
+
+/* fatfs_syms.c */
+extern int init_fat_fs(void);
+extern void cleanup_fat_fs(void);
+
+/* nls.c */
+extern int fat_register_nls(struct fat_nls_table * fmt);
+extern int fat_unregister_nls(struct fat_nls_table * fmt);
+extern struct fat_nls_table *fat_find_nls(int codepage);
+extern struct fat_nls_table *fat_load_nls(int codepage);
+extern void fat_unload_nls(int codepage);
+extern int init_fat_nls(void);
+
+/* vfat/namei.c - these are for dmsdos */
+extern int vfat_create(struct inode *dir,struct dentry *dentry,int mode);
+extern int vfat_unlink(struct inode *dir,struct dentry *dentry);
+extern int vfat_mkdir(struct inode *dir,struct dentry *dentry,int mode);
+extern int vfat_rmdir(struct inode *dir,struct dentry *dentry);
+extern int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
+ struct inode *new_dir,struct dentry *new_dentry);
+extern struct super_block *vfat_read_super(struct super_block *sb,void *data,
+ int silent);
+extern void vfat_read_inode(struct inode *inode);
+extern struct dentry *vfat_lookup(struct inode *dir,struct dentry *);
+
+/* vfat/vfatfs_syms.c */
+extern struct file_system_type vfat_fs_type;
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/msdos_fs_i.h b/pfinet/linux-src/include/linux/msdos_fs_i.h
new file mode 100644
index 00000000..929de3db
--- /dev/null
+++ b/pfinet/linux-src/include/linux/msdos_fs_i.h
@@ -0,0 +1,39 @@
+#ifndef _MSDOS_FS_I
+#define _MSDOS_FS_I
+
+#ifndef _LINUX_PIPE_FS_I_H
+#include <linux/pipe_fs_i.h>
+#endif
+
+/*
+ * MS-DOS file system inode data in memory
+ */
+
+struct msdos_inode_info {
+ /*
+ UMSDOS manage special file and fifo as normal empty
+ msdos file. fifo inode processing conflict with msdos
+ processing. So I insert the pipe_inode_info so the
+ information does not overlap. This increases the size of
+ the msdos_inode_info, but the clear winner here is
+ the ext2_inode_info. So it does not change anything to
+ the total size of a struct inode.
+
+ I have not put it conditional. With the advent of loadable
+ file system drivers, it would be very easy to compile
+ a MS-DOS FS driver unaware of UMSDOS and then later to
+ load a (then incompatible) UMSDOS FS driver.
+ */
+ struct pipe_inode_info reserved;
+ int i_start; /* first cluster or 0 */
+ int i_logstart; /* logical first cluster */
+ int i_attrs; /* unused attribute bits */
+ int i_ctime_ms; /* unused change time in milliseconds */
+ int i_binary; /* file contains non-text data */
+ int i_location; /* on-disk position of directory entry or 0 */
+ struct inode *i_fat_inode; /* struct inode of this one */
+ struct list_head i_fat_hash; /* hash by i_location */
+ off_t i_last_pos;/* position of last lookup */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/msdos_fs_sb.h b/pfinet/linux-src/include/linux/msdos_fs_sb.h
new file mode 100644
index 00000000..ae86a980
--- /dev/null
+++ b/pfinet/linux-src/include/linux/msdos_fs_sb.h
@@ -0,0 +1,59 @@
+#ifndef _MSDOS_FS_SB
+#define _MSDOS_FS_SB
+#include<linux/fat_cvf.h>
+
+/*
+ * MS-DOS file system in-core superblock data
+ */
+
+struct fat_mount_options {
+ uid_t fs_uid;
+ gid_t fs_gid;
+ unsigned short fs_umask;
+ unsigned short codepage; /* Codepage for shortname conversions */
+ char *iocharset; /* Charset used for filename input/display */
+ unsigned char name_check; /* r = relaxed, n = normal, s = strict */
+ unsigned char conversion; /* b = binary, t = text, a = auto */
+ unsigned quiet:1, /* set = fake successful chmods and chowns */
+ showexec:1, /* set = only set x bit for com/exe/bat */
+ sys_immutable:1, /* set = system files are immutable */
+ dotsOK:1, /* set = hidden and system files are named '.filename' */
+ isvfat:1, /* 0=no vfat long filename support, 1=vfat support */
+ utf8:1, /* Use of UTF8 character set (Default) */
+ unicode_xlate:1, /* create escape sequences for unhandled Unicode */
+ posixfs:1, /* Allow names like makefile and Makefile to coexist */
+ numtail:1, /* Does first alias have a numeric '~1' type tail? */
+ atari:1, /* Use Atari GEMDOS variation of MS-DOS fs */
+ fat32:1; /* Is this a FAT32 partition? */
+};
+
+struct vfat_unicode {
+ unsigned char uni1;
+ unsigned char uni2;
+};
+
+struct msdos_sb_info {
+ unsigned short cluster_size; /* sectors/cluster */
+ unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
+ unsigned short fat_start;
+ unsigned long fat_length; /* FAT start & length (sec.) */
+ unsigned long dir_start;
+ unsigned short dir_entries; /* root dir start & entries */
+ unsigned long data_start; /* first data sector */
+ unsigned long clusters; /* number of clusters */
+ unsigned long root_cluster; /* first cluster of the root directory */
+ unsigned long fsinfo_offset; /* FAT32 fsinfo offset from start of disk */
+ struct wait_queue *fat_wait;
+ int fat_lock;
+ int prev_free; /* previously returned free cluster number */
+ int free_clusters; /* -1 if undefined */
+ struct fat_mount_options options;
+ struct nls_table *nls_disk; /* Codepage used on disk */
+ struct nls_table *nls_io; /* Charset used for input and display */
+ struct cvf_format* cvf_format;
+ void *dir_ops; /* Opaque; default directory operations */
+ void (*put_super_callback)(struct super_block *);
+ void *private_data;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/msg.h b/pfinet/linux-src/include/linux/msg.h
new file mode 100644
index 00000000..2be62719
--- /dev/null
+++ b/pfinet/linux-src/include/linux/msg.h
@@ -0,0 +1,80 @@
+#ifndef _LINUX_MSG_H
+#define _LINUX_MSG_H
+
+#include <linux/ipc.h>
+
+/* ipcs ctl commands */
+#define MSG_STAT 11
+#define MSG_INFO 12
+
+/* msgrcv options */
+#define MSG_NOERROR 010000 /* no error if message is too big */
+#define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/
+
+/* one msqid structure for each queue on the system */
+struct msqid_ds {
+ struct ipc_perm msg_perm;
+ struct msg *msg_first; /* first message on queue */
+ struct msg *msg_last; /* last message in queue */
+ __kernel_time_t msg_stime; /* last msgsnd time */
+ __kernel_time_t msg_rtime; /* last msgrcv time */
+ __kernel_time_t msg_ctime; /* last change time */
+ struct wait_queue *wwait;
+ struct wait_queue *rwait;
+ unsigned short msg_cbytes; /* current number of bytes on queue */
+ unsigned short msg_qnum; /* number of messages in queue */
+ unsigned short msg_qbytes; /* max number of bytes on queue */
+ __kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_ipc_pid_t msg_lrpid; /* last receive pid */
+};
+
+/* message buffer for msgsnd and msgrcv calls */
+struct msgbuf {
+ long mtype; /* type of message */
+ char mtext[1]; /* message text */
+};
+
+/* buffer for msgctl calls IPC_INFO, MSG_INFO */
+struct msginfo {
+ int msgpool;
+ int msgmap;
+ int msgmax;
+ int msgmnb;
+ int msgmni;
+ int msgssz;
+ int msgtql;
+ unsigned short msgseg;
+};
+
+#define MSGMNI 128 /* <= 1K */ /* max # of msg queue identifiers */
+#define MSGMAX 4056 /* <= 4056 */ /* max size of message (bytes) */
+#define MSGMNB 16384 /* ? */ /* default max size of a message queue */
+
+/* unused */
+#define MSGPOOL (MSGMNI*MSGMNB/1024) /* size in kilobytes of message pool */
+#define MSGTQL MSGMNB /* number of system message headers */
+#define MSGMAP MSGMNB /* number of entries in message map */
+#define MSGSSZ 16 /* message segment size */
+#define __MSGSEG ((MSGPOOL*1024)/ MSGSSZ) /* max no. of segments */
+#define MSGSEG (__MSGSEG <= 0xffff ? __MSGSEG : 0xffff)
+
+#ifdef __KERNEL__
+
+/* one msg structure for each message */
+struct msg {
+ struct msg *msg_next; /* next message on queue */
+ long msg_type;
+ char *msg_spot; /* message text address */
+ time_t msg_stime; /* msgsnd time */
+ short msg_ts; /* message text size */
+};
+
+asmlinkage int sys_msgget (key_t key, int msgflg);
+asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
+asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp,
+ int msgflg);
+asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_MSG_H */
diff --git a/pfinet/linux-src/include/linux/mtio.h b/pfinet/linux-src/include/linux/mtio.h
new file mode 100644
index 00000000..c794ed89
--- /dev/null
+++ b/pfinet/linux-src/include/linux/mtio.h
@@ -0,0 +1,373 @@
+/*
+ * linux/mtio.h header file for Linux. Written by H. Bergman
+ *
+ * Modified for special ioctls provided by zftape in September 1997
+ * by C.-J. Heine.
+ */
+
+#ifndef _LINUX_MTIO_H
+#define _LINUX_MTIO_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/qic117.h>
+
+/*
+ * Structures and definitions for mag tape io control commands
+ */
+
+/* structure for MTIOCTOP - mag tape op command */
+struct mtop {
+ short mt_op; /* operations defined below */
+ int mt_count; /* how many of them */
+};
+
+/* Magnetic Tape operations [Not all operations supported by all drivers]: */
+#define MTRESET 0 /* +reset drive in case of problems */
+#define MTFSF 1 /* forward space over FileMark,
+ * position at first record of next file
+ */
+#define MTBSF 2 /* backward space FileMark (position before FM) */
+#define MTFSR 3 /* forward space record */
+#define MTBSR 4 /* backward space record */
+#define MTWEOF 5 /* write an end-of-file record (mark) */
+#define MTREW 6 /* rewind */
+#define MTOFFL 7 /* rewind and put the drive offline (eject?) */
+#define MTNOP 8 /* no op, set status only (read with MTIOCGET) */
+#define MTRETEN 9 /* retension tape */
+#define MTBSFM 10 /* +backward space FileMark, position at FM */
+#define MTFSFM 11 /* +forward space FileMark, position at FM */
+#define MTEOM 12 /* goto end of recorded media (for appending files).
+ * MTEOM positions after the last FM, ready for
+ * appending another file.
+ */
+#define MTERASE 13 /* erase tape -- be careful! */
+
+#define MTRAS1 14 /* run self test 1 (nondestructive) */
+#define MTRAS2 15 /* run self test 2 (destructive) */
+#define MTRAS3 16 /* reserved for self test 3 */
+
+#define MTSETBLK 20 /* set block length (SCSI) */
+#define MTSETDENSITY 21 /* set tape density (SCSI) */
+#define MTSEEK 22 /* seek to block (Tandberg, etc.) */
+#define MTTELL 23 /* tell block (Tandberg, etc.) */
+#define MTSETDRVBUFFER 24 /* set the drive buffering according to SCSI-2 */
+ /* ordinary buffered operation with code 1 */
+#define MTFSS 25 /* space forward over setmarks */
+#define MTBSS 26 /* space backward over setmarks */
+#define MTWSM 27 /* write setmarks */
+
+#define MTLOCK 28 /* lock the drive door */
+#define MTUNLOCK 29 /* unlock the drive door */
+#define MTLOAD 30 /* execute the SCSI load command */
+#define MTUNLOAD 31 /* execute the SCSI unload command */
+#define MTCOMPRESSION 32/* control compression with SCSI mode page 15 */
+#define MTSETPART 33 /* Change the active tape partition */
+#define MTMKPART 34 /* Format the tape with one or two partitions */
+
+/* structure for MTIOCGET - mag tape get status command */
+
+struct mtget {
+ long mt_type; /* type of magtape device */
+ long mt_resid; /* residual count: (not sure)
+ * number of bytes ignored, or
+ * number of files not skipped, or
+ * number of records not skipped.
+ */
+ /* the following registers are device dependent */
+ long mt_dsreg; /* status register */
+ long mt_gstat; /* generic (device independent) status */
+ long mt_erreg; /* error register */
+ /* The next two fields are not always used */
+ __kernel_daddr_t mt_fileno; /* number of current file on tape */
+ __kernel_daddr_t mt_blkno; /* current block number */
+};
+
+
+
+/*
+ * Constants for mt_type. Not all of these are supported,
+ * and these are not all of the ones that are supported.
+ */
+#define MT_ISUNKNOWN 0x01
+#define MT_ISQIC02 0x02 /* Generic QIC-02 tape streamer */
+#define MT_ISWT5150 0x03 /* Wangtek 5150EQ, QIC-150, QIC-02 */
+#define MT_ISARCHIVE_5945L2 0x04 /* Archive 5945L-2, QIC-24, QIC-02? */
+#define MT_ISCMSJ500 0x05 /* CMS Jumbo 500 (QIC-02?) */
+#define MT_ISTDC3610 0x06 /* Tandberg 6310, QIC-24 */
+#define MT_ISARCHIVE_VP60I 0x07 /* Archive VP60i, QIC-02 */
+#define MT_ISARCHIVE_2150L 0x08 /* Archive Viper 2150L */
+#define MT_ISARCHIVE_2060L 0x09 /* Archive Viper 2060L */
+#define MT_ISARCHIVESC499 0x0A /* Archive SC-499 QIC-36 controller */
+#define MT_ISQIC02_ALL_FEATURES 0x0F /* Generic QIC-02 with all features */
+#define MT_ISWT5099EEN24 0x11 /* Wangtek 5099-een24, 60MB, QIC-24 */
+#define MT_ISTEAC_MT2ST 0x12 /* Teac MT-2ST 155mb drive, Teac DC-1 card (Wangtek type) */
+#define MT_ISEVEREX_FT40A 0x32 /* Everex FT40A (QIC-40) */
+#define MT_ISDDS1 0x51 /* DDS device without partitions */
+#define MT_ISDDS2 0x52 /* DDS device with partitions */
+#define MT_ISSCSI1 0x71 /* Generic ANSI SCSI-1 tape unit */
+#define MT_ISSCSI2 0x72 /* Generic ANSI SCSI-2 tape unit */
+
+/* QIC-40/80/3010/3020 ftape supported drives.
+ * 20bit vendor ID + 0x800000 (see ftape-vendors.h)
+ */
+#define MT_ISFTAPE_UNKNOWN 0x800000 /* obsolete */
+#define MT_ISFTAPE_FLAG 0x800000
+
+struct mt_tape_info {
+ long t_type; /* device type id (mt_type) */
+ char *t_name; /* descriptive name */
+};
+
+#define MT_TAPE_INFO { \
+ {MT_ISUNKNOWN, "Unknown type of tape device"}, \
+ {MT_ISQIC02, "Generic QIC-02 tape streamer"}, \
+ {MT_ISWT5150, "Wangtek 5150, QIC-150"}, \
+ {MT_ISARCHIVE_5945L2, "Archive 5945L-2"}, \
+ {MT_ISCMSJ500, "CMS Jumbo 500"}, \
+ {MT_ISTDC3610, "Tandberg TDC 3610, QIC-24"}, \
+ {MT_ISARCHIVE_VP60I, "Archive VP60i, QIC-02"}, \
+ {MT_ISARCHIVE_2150L, "Archive Viper 2150L"}, \
+ {MT_ISARCHIVE_2060L, "Archive Viper 2060L"}, \
+ {MT_ISARCHIVESC499, "Archive SC-499 QIC-36 controller"}, \
+ {MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \
+ {MT_ISWT5099EEN24, "Wangtek 5099-een24, 60MB"}, \
+ {MT_ISTEAC_MT2ST, "Teac MT-2ST 155mb data cassette drive"}, \
+ {MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \
+ {MT_ISSCSI1, "Generic SCSI-1 tape"}, \
+ {MT_ISSCSI2, "Generic SCSI-2 tape"}, \
+ {0, NULL} \
+}
+
+
+/* structure for MTIOCPOS - mag tape get position command */
+
+struct mtpos {
+ long mt_blkno; /* current block number */
+};
+
+
+/* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended
+ * as an interim solution for QIC-02 until DDI is fully implemented.
+ */
+struct mtconfiginfo {
+ long mt_type; /* drive type */
+ long ifc_type; /* interface card type */
+ unsigned short irqnr; /* IRQ number to use */
+ unsigned short dmanr; /* DMA channel to use */
+ unsigned short port; /* IO port base address */
+
+ unsigned long debug; /* debugging flags */
+
+ unsigned have_dens:1;
+ unsigned have_bsf:1;
+ unsigned have_fsr:1;
+ unsigned have_bsr:1;
+ unsigned have_eod:1;
+ unsigned have_seek:1;
+ unsigned have_tell:1;
+ unsigned have_ras1:1;
+ unsigned have_ras2:1;
+ unsigned have_ras3:1;
+ unsigned have_qfa:1;
+
+ unsigned pad1:5;
+ char reserved[10];
+};
+
+/* structure for MTIOCVOLINFO, query information about the volume
+ * currently positioned at (zftape)
+ */
+struct mtvolinfo {
+ unsigned int mt_volno; /* vol-number */
+ unsigned int mt_blksz; /* blocksize used when recording */
+ unsigned int mt_rawsize; /* raw tape space consumed, in kb */
+ unsigned int mt_size; /* volume size after decompression, in kb */
+ unsigned int mt_cmpr:1; /* this volume has been compressed */
+};
+
+/* raw access to a floppy drive, read and write an arbitrary segment.
+ * For ftape/zftape to support formatting etc.
+ */
+#define MT_FT_RD_SINGLE 0
+#define MT_FT_RD_AHEAD 1
+#define MT_FT_WR_ASYNC 0 /* start tape only when all buffers are full */
+#define MT_FT_WR_MULTI 1 /* start tape, continue until buffers are empty */
+#define MT_FT_WR_SINGLE 2 /* write a single segment and stop afterwards */
+#define MT_FT_WR_DELETE 3 /* write deleted data marks, one segment at time */
+
+struct mtftseg
+{
+ unsigned mt_segno; /* the segment to read or write */
+ unsigned mt_mode; /* modes for read/write (sync/async etc.) */
+ int mt_result; /* result of r/w request, not of the ioctl */
+ void *mt_data; /* User space buffer: must be 29kb */
+};
+
+/* get tape capacity (ftape/zftape)
+ */
+struct mttapesize {
+ unsigned long mt_capacity; /* entire, uncompressed capacity
+ * of a cartridge
+ */
+ unsigned long mt_used; /* what has been used so far, raw
+ * uncompressed amount
+ */
+};
+
+/* possible values of the ftfmt_op field
+ */
+#define FTFMT_SET_PARMS 1 /* set software parms */
+#define FTFMT_GET_PARMS 2 /* get software parms */
+#define FTFMT_FORMAT_TRACK 3 /* start formatting a tape track */
+#define FTFMT_STATUS 4 /* monitor formatting a tape track */
+#define FTFMT_VERIFY 5 /* verify the given segment */
+
+struct ftfmtparms {
+ unsigned char ft_qicstd; /* QIC-40/QIC-80/QIC-3010/QIC-3020 */
+ unsigned char ft_fmtcode; /* Refer to the QIC specs */
+ unsigned char ft_fhm; /* floppy head max */
+ unsigned char ft_ftm; /* floppy track max */
+ unsigned short ft_spt; /* segments per track */
+ unsigned short ft_tpc; /* tracks per cartridge */
+};
+
+struct ftfmttrack {
+ unsigned int ft_track; /* track to format */
+ unsigned char ft_gap3; /* size of gap3, for FORMAT_TRK */
+};
+
+struct ftfmtstatus {
+ unsigned int ft_segment; /* segment currently being formatted */
+};
+
+struct ftfmtverify {
+ unsigned int ft_segment; /* segment to verify */
+ unsigned long ft_bsm; /* bsm as result of VERIFY cmd */
+};
+
+struct mtftformat {
+ unsigned int fmt_op; /* operation to perform */
+ union fmt_arg {
+ struct ftfmtparms fmt_parms; /* format parameters */
+ struct ftfmttrack fmt_track; /* ctrl while formatting */
+ struct ftfmtstatus fmt_status;
+ struct ftfmtverify fmt_verify; /* for verifying */
+ } fmt_arg;
+};
+
+struct mtftcmd {
+ unsigned int ft_wait_before; /* timeout to wait for drive to get ready
+ * before command is sent. Milliseconds
+ */
+ qic117_cmd_t ft_cmd; /* command to send */
+ unsigned char ft_parm_cnt; /* zero: no parm is sent. */
+ unsigned char ft_parms[3]; /* parameter(s) to send to
+ * the drive. The parms are nibbles
+ * driver sends cmd + 2 step pulses */
+ unsigned int ft_result_bits; /* if non zero, number of bits
+ * returned by the tape drive
+ */
+ unsigned int ft_result; /* the result returned by the tape drive*/
+ unsigned int ft_wait_after; /* timeout to wait for drive to get ready
+ * after command is sent. 0: don't wait */
+ int ft_status; /* status returned by ready wait
+ * undefined if timeout was 0.
+ */
+ int ft_error; /* error code if error status was set by
+ * command
+ */
+};
+
+/* mag tape io control commands */
+#define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */
+#define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */
+#define MTIOCPOS _IOR('m', 3, struct mtpos) /* get tape position */
+
+/* The next two are used by the QIC-02 driver for runtime reconfiguration.
+ * See tpqic02.h for struct mtconfiginfo.
+ */
+#define MTIOCGETCONFIG _IOR('m', 4, struct mtconfiginfo) /* get tape config */
+#define MTIOCSETCONFIG _IOW('m', 5, struct mtconfiginfo) /* set tape config */
+
+/* the next six are used by the floppy ftape drivers and its frontends
+ * sorry, but MTIOCTOP commands are write only.
+ */
+#define MTIOCRDFTSEG _IOWR('m', 6, struct mtftseg) /* read a segment */
+#define MTIOCWRFTSEG _IOWR('m', 7, struct mtftseg) /* write a segment */
+#define MTIOCVOLINFO _IOR('m', 8, struct mtvolinfo) /* info about volume */
+#define MTIOCGETSIZE _IOR('m', 9, struct mttapesize)/* get cartridge size*/
+#define MTIOCFTFORMAT _IOWR('m', 10, struct mtftformat) /* format ftape */
+#define MTIOCFTCMD _IOWR('m', 11, struct mtftcmd) /* send QIC-117 cmd */
+
+/* Generic Mag Tape (device independent) status macros for examining
+ * mt_gstat -- HP-UX compatible.
+ * There is room for more generic status bits here, but I don't
+ * know which of them are reserved. At least three or so should
+ * be added to make this really useful.
+ */
+#define GMT_EOF(x) ((x) & 0x80000000)
+#define GMT_BOT(x) ((x) & 0x40000000)
+#define GMT_EOT(x) ((x) & 0x20000000)
+#define GMT_SM(x) ((x) & 0x10000000) /* DDS setmark */
+#define GMT_EOD(x) ((x) & 0x08000000) /* DDS EOD */
+#define GMT_WR_PROT(x) ((x) & 0x04000000)
+/* #define GMT_ ? ((x) & 0x02000000) */
+#define GMT_ONLINE(x) ((x) & 0x01000000)
+#define GMT_D_6250(x) ((x) & 0x00800000)
+#define GMT_D_1600(x) ((x) & 0x00400000)
+#define GMT_D_800(x) ((x) & 0x00200000)
+/* #define GMT_ ? ((x) & 0x00100000) */
+/* #define GMT_ ? ((x) & 0x00080000) */
+#define GMT_DR_OPEN(x) ((x) & 0x00040000) /* door open (no tape) */
+/* #define GMT_ ? ((x) & 0x00020000) */
+#define GMT_IM_REP_EN(x) ((x) & 0x00010000) /* immediate report mode */
+/* 16 generic status bits unused */
+
+
+/* SCSI-tape specific definitions */
+/* Bitfield shifts in the status */
+#define MT_ST_BLKSIZE_SHIFT 0
+#define MT_ST_BLKSIZE_MASK 0xffffff
+#define MT_ST_DENSITY_SHIFT 24
+#define MT_ST_DENSITY_MASK 0xff000000
+
+#define MT_ST_SOFTERR_SHIFT 0
+#define MT_ST_SOFTERR_MASK 0xffff
+
+/* Bitfields for the MTSETDRVBUFFER ioctl */
+#define MT_ST_OPTIONS 0xf0000000
+#define MT_ST_BOOLEANS 0x10000000
+#define MT_ST_SETBOOLEANS 0x30000000
+#define MT_ST_CLEARBOOLEANS 0x40000000
+#define MT_ST_WRITE_THRESHOLD 0x20000000
+#define MT_ST_DEF_BLKSIZE 0x50000000
+#define MT_ST_DEF_OPTIONS 0x60000000
+#define MT_ST_TIMEOUTS 0x70000000
+#define MT_ST_SET_TIMEOUT (MT_ST_TIMEOUTS | 0x000000)
+#define MT_ST_SET_LONG_TIMEOUT (MT_ST_TIMEOUTS | 0x100000)
+
+#define MT_ST_BUFFER_WRITES 0x1
+#define MT_ST_ASYNC_WRITES 0x2
+#define MT_ST_READ_AHEAD 0x4
+#define MT_ST_DEBUGGING 0x8
+#define MT_ST_TWO_FM 0x10
+#define MT_ST_FAST_MTEOM 0x20
+#define MT_ST_AUTO_LOCK 0x40
+#define MT_ST_DEF_WRITES 0x80
+#define MT_ST_CAN_BSR 0x100
+#define MT_ST_NO_BLKLIMS 0x200
+#define MT_ST_CAN_PARTITIONS 0x400
+#define MT_ST_SCSI2LOGICAL 0x800
+#define MT_ST_SYSV 0x1000
+
+/* The mode parameters to be controlled. Parameter chosen with bits 20-28 */
+#define MT_ST_CLEAR_DEFAULT 0xfffff
+#define MT_ST_DEF_DENSITY (MT_ST_DEF_OPTIONS | 0x100000)
+#define MT_ST_DEF_COMPRESSION (MT_ST_DEF_OPTIONS | 0x200000)
+#define MT_ST_DEF_DRVBUFFER (MT_ST_DEF_OPTIONS | 0x300000)
+
+/* The offset for the arguments for the special HP changer load command. */
+#define MT_ST_HPLOADER_OFFSET 10000
+
+#endif /* _LINUX_MTIO_H */
diff --git a/pfinet/linux-src/include/linux/nbd.h b/pfinet/linux-src/include/linux/nbd.h
new file mode 100644
index 00000000..c2c0431f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nbd.h
@@ -0,0 +1,85 @@
+#ifndef LINUX_NBD_H
+#define LINUX_NBD_H
+
+#define NBD_SET_SOCK _IO( 0xab, 0 )
+#define NBD_SET_BLKSIZE _IO( 0xab, 1 )
+#define NBD_SET_SIZE _IO( 0xab, 2 )
+#define NBD_DO_IT _IO( 0xab, 3 )
+#define NBD_CLEAR_SOCK _IO( 0xab, 4 )
+#define NBD_CLEAR_QUE _IO( 0xab, 5 )
+#define NBD_PRINT_DEBUG _IO( 0xab, 6 )
+#define NBD_SET_SIZE_BLOCKS _IO( 0xab, 7 )
+
+#ifdef MAJOR_NR
+
+#include <linux/locks.h>
+#include <asm/semaphore.h>
+
+#define LOCAL_END_REQUEST
+
+#include <linux/blk.h>
+
+#ifdef PARANOIA
+extern int requests_in;
+extern int requests_out;
+#endif
+
+static void
+nbd_end_request(struct request *req)
+{
+#ifdef PARANOIA
+ requests_out++;
+#endif
+ if (end_that_request_first( req, !req->errors, "nbd" ))
+ return;
+ end_that_request_last( req );
+}
+
+#define MAX_NBD 128
+
+struct nbd_device {
+ int refcnt;
+ int flags;
+ int harderror; /* Code of hard error */
+#define NBD_READ_ONLY 0x0001
+#define NBD_WRITE_NOCHK 0x0002
+#define NBD_INITIALISED 0x0004
+ struct socket * sock;
+ struct file * file; /* If == NULL, device is not ready, yet */
+ int magic; /* FIXME: not if debugging is off */
+ struct request *head; /* Requests are added here... */
+ struct request *tail;
+ struct semaphore queue_lock;
+};
+#endif
+
+/* This now IS in some kind of include file... */
+
+/* These are send over network in request/reply magic field */
+
+#define NBD_REQUEST_MAGIC 0x25609513
+#define NBD_REPLY_MAGIC 0x67446698
+/* Do *not* use magics: 0x12560953 0x96744668. */
+
+/*
+ * This is packet used for communication between client and
+ * server. All data are in network byte order.
+ */
+struct nbd_request {
+ u32 magic;
+ u32 type; /* == READ || == WRITE */
+ char handle[8];
+ u64 from;
+ u32 len;
+}
+#ifdef __GNUC__
+ __attribute__ ((packed))
+#endif
+;
+
+struct nbd_reply {
+ u32 magic;
+ u32 error; /* 0 = ok, else error */
+ char handle[8]; /* handle you got from request */
+};
+#endif
diff --git a/pfinet/linux-src/include/linux/ncp.h b/pfinet/linux-src/include/linux/ncp.h
new file mode 100644
index 00000000..229618db
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ncp.h
@@ -0,0 +1,204 @@
+/*
+ * ncp.h
+ *
+ * Copyright (C) 1995 by Volker Lendecke
+ * Modified for sparc by J.F. Chadima
+ * Modified for __constant_ntoh by Frank A. Vorstenbosch
+ *
+ */
+
+#ifndef _LINUX_NCP_H
+#define _LINUX_NCP_H
+
+#include <linux/types.h>
+#include <linux/ipx.h>
+
+#define NCP_PTYPE (0x11)
+#define NCP_PORT (0x0451)
+
+#define NCP_ALLOC_SLOT_REQUEST (0x1111)
+#define NCP_REQUEST (0x2222)
+#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
+
+struct ncp_request_header {
+ __u16 type __attribute__((packed));
+ __u8 sequence __attribute__((packed));
+ __u8 conn_low __attribute__((packed));
+ __u8 task __attribute__((packed));
+ __u8 conn_high __attribute__((packed));
+ __u8 function __attribute__((packed));
+ __u8 data[0] __attribute__((packed));
+};
+
+#define NCP_REPLY (0x3333)
+#define NCP_POSITIVE_ACK (0x9999)
+
+struct ncp_reply_header {
+ __u16 type __attribute__((packed));
+ __u8 sequence __attribute__((packed));
+ __u8 conn_low __attribute__((packed));
+ __u8 task __attribute__((packed));
+ __u8 conn_high __attribute__((packed));
+ __u8 completion_code __attribute__((packed));
+ __u8 connection_state __attribute__((packed));
+ __u8 data[0] __attribute__((packed));
+};
+
+#define NCP_VOLNAME_LEN (16)
+#define NCP_NUMBER_OF_VOLUMES (64)
+struct ncp_volume_info {
+ __u32 total_blocks;
+ __u32 free_blocks;
+ __u32 purgeable_blocks;
+ __u32 not_yet_purgeable_blocks;
+ __u32 total_dir_entries;
+ __u32 available_dir_entries;
+ __u8 sectors_per_block;
+ char volume_name[NCP_VOLNAME_LEN + 1];
+};
+
+/* these define the attribute byte as seen by NCP */
+#define aRONLY (ntohl(0x01000000))
+#define aHIDDEN (__constant_ntohl(0x02000000))
+#define aSYSTEM (__constant_ntohl(0x04000000))
+#define aEXECUTE (ntohl(0x08000000))
+#define aDIR (ntohl(0x10000000))
+#define aARCH (ntohl(0x20000000))
+#define aSHARED (ntohl(0x80000000))
+#define aDONTSUBALLOCATE (ntohl(1L<<(11+8)))
+#define aTRANSACTIONAL (ntohl(1L<<(12+8)))
+#define aPURGE (ntohl(1L<<(16-8)))
+#define aRENAMEINHIBIT (ntohl(1L<<(17-8)))
+#define aDELETEINHIBIT (ntohl(1L<<(18-8)))
+#define aDONTCOMPRESS (nothl(1L<<(27-24)))
+
+#define AR_READ (ntohs(0x0100))
+#define AR_WRITE (ntohs(0x0200))
+#define AR_EXCLUSIVE (ntohs(0x2000))
+
+#define NCP_FILE_ID_LEN 6
+
+/* Defines for Name Spaces */
+#define NW_NS_DOS 0
+#define NW_NS_MAC 1
+#define NW_NS_NFS 2
+#define NW_NS_FTAM 3
+#define NW_NS_OS2 4
+
+/* Defines for ReturnInformationMask */
+#define RIM_NAME (ntohl(0x01000000L))
+#define RIM_SPACE_ALLOCATED (ntohl(0x02000000L))
+#define RIM_ATTRIBUTES (ntohl(0x04000000L))
+#define RIM_DATA_SIZE (ntohl(0x08000000L))
+#define RIM_TOTAL_SIZE (ntohl(0x10000000L))
+#define RIM_EXT_ATTR_INFO (ntohl(0x20000000L))
+#define RIM_ARCHIVE (ntohl(0x40000000L))
+#define RIM_MODIFY (ntohl(0x80000000L))
+#define RIM_CREATION (ntohl(0x00010000L))
+#define RIM_OWNING_NAMESPACE (ntohl(0x00020000L))
+#define RIM_DIRECTORY (ntohl(0x00040000L))
+#define RIM_RIGHTS (ntohl(0x00080000L))
+#define RIM_ALL (ntohl(0xFF0F0000L))
+#define RIM_COMPRESSED_INFO (ntohl(0x00000080L))
+
+/* open/create modes */
+#define OC_MODE_OPEN 0x01
+#define OC_MODE_TRUNCATE 0x02
+#define OC_MODE_REPLACE 0x02
+#define OC_MODE_CREATE 0x08
+
+/* open/create results */
+#define OC_ACTION_NONE 0x00
+#define OC_ACTION_OPEN 0x01
+#define OC_ACTION_CREATE 0x02
+#define OC_ACTION_TRUNCATE 0x04
+#define OC_ACTION_REPLACE 0x04
+
+/* access rights attributes */
+#ifndef AR_READ_ONLY
+#define AR_READ_ONLY 0x0001
+#define AR_WRITE_ONLY 0x0002
+#define AR_DENY_READ 0x0004
+#define AR_DENY_WRITE 0x0008
+#define AR_COMPATIBILITY 0x0010
+#define AR_WRITE_THROUGH 0x0040
+#define AR_OPEN_COMPRESSED 0x0100
+#endif
+
+struct nw_info_struct {
+ __u32 spaceAlloc __attribute__((packed));
+ __u32 attributes __attribute__((packed));
+ __u16 flags __attribute__((packed));
+ __u32 dataStreamSize __attribute__((packed));
+ __u32 totalStreamSize __attribute__((packed));
+ __u16 numberOfStreams __attribute__((packed));
+ __u16 creationTime __attribute__((packed));
+ __u16 creationDate __attribute__((packed));
+ __u32 creatorID __attribute__((packed));
+ __u16 modifyTime __attribute__((packed));
+ __u16 modifyDate __attribute__((packed));
+ __u32 modifierID __attribute__((packed));
+ __u16 lastAccessDate __attribute__((packed));
+ __u16 archiveTime __attribute__((packed));
+ __u16 archiveDate __attribute__((packed));
+ __u32 archiverID __attribute__((packed));
+ __u16 inheritedRightsMask __attribute__((packed));
+ __u32 dirEntNum __attribute__((packed));
+ __u32 DosDirNum __attribute__((packed));
+ __u32 volNumber __attribute__((packed));
+ __u32 EADataSize __attribute__((packed));
+ __u32 EAKeyCount __attribute__((packed));
+ __u32 EAKeySize __attribute__((packed));
+ __u32 NSCreator __attribute__((packed));
+ __u8 nameLen __attribute__((packed));
+ __u8 entryName[256] __attribute__((packed));
+};
+
+/* modify mask - use with MODIFY_DOS_INFO structure */
+#define DM_ATTRIBUTES (ntohl(0x02000000L))
+#define DM_CREATE_DATE (ntohl(0x04000000L))
+#define DM_CREATE_TIME (ntohl(0x08000000L))
+#define DM_CREATOR_ID (ntohl(0x10000000L))
+#define DM_ARCHIVE_DATE (ntohl(0x20000000L))
+#define DM_ARCHIVE_TIME (ntohl(0x40000000L))
+#define DM_ARCHIVER_ID (ntohl(0x80000000L))
+#define DM_MODIFY_DATE (ntohl(0x00010000L))
+#define DM_MODIFY_TIME (ntohl(0x00020000L))
+#define DM_MODIFIER_ID (ntohl(0x00040000L))
+#define DM_LAST_ACCESS_DATE (ntohl(0x00080000L))
+#define DM_INHERITED_RIGHTS_MASK (ntohl(0x00100000L))
+#define DM_MAXIMUM_SPACE (ntohl(0x00200000L))
+
+struct nw_modify_dos_info {
+ __u32 attributes __attribute__((packed));
+ __u16 creationDate __attribute__((packed));
+ __u16 creationTime __attribute__((packed));
+ __u32 creatorID __attribute__((packed));
+ __u16 modifyDate __attribute__((packed));
+ __u16 modifyTime __attribute__((packed));
+ __u32 modifierID __attribute__((packed));
+ __u16 archiveDate __attribute__((packed));
+ __u16 archiveTime __attribute__((packed));
+ __u32 archiverID __attribute__((packed));
+ __u16 lastAccessDate __attribute__((packed));
+ __u16 inheritanceGrantMask __attribute__((packed));
+ __u16 inheritanceRevokeMask __attribute__((packed));
+ __u32 maximumSpace __attribute__((packed));
+};
+
+struct nw_file_info {
+ struct nw_info_struct i;
+ int opened;
+ int access;
+ __u32 server_file_handle __attribute__((packed));
+ __u8 open_create_action __attribute__((packed));
+ __u8 file_handle[6] __attribute__((packed));
+};
+
+struct nw_search_sequence {
+ __u8 volNumber __attribute__((packed));
+ __u32 dirBase __attribute__((packed));
+ __u32 sequence __attribute__((packed));
+};
+
+#endif /* _LINUX_NCP_H */
diff --git a/pfinet/linux-src/include/linux/ncp_fs.h b/pfinet/linux-src/include/linux/ncp_fs.h
new file mode 100644
index 00000000..9c5df534
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ncp_fs.h
@@ -0,0 +1,331 @@
+/*
+ * ncp_fs.h
+ *
+ * Copyright (C) 1995, 1996 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_NCP_FS_H
+#define _LINUX_NCP_FS_H
+
+#include <linux/fs.h>
+#include <linux/in.h>
+#include <linux/types.h>
+
+#include <linux/ncp_mount.h>
+
+/* NLS charsets by ioctl */
+#define NCP_IOCSNAME_LEN 20
+struct ncp_nls_ioctl
+{
+ unsigned char codepage[NCP_IOCSNAME_LEN+1];
+ unsigned char iocharset[NCP_IOCSNAME_LEN+1];
+};
+
+#include <linux/ncp_fs_sb.h>
+#include <linux/ncp_fs_i.h>
+
+/*
+ * ioctl commands
+ */
+
+struct ncp_ioctl_request {
+ unsigned int function;
+ unsigned int size;
+ char *data;
+};
+
+struct ncp_fs_info {
+ int version;
+ struct sockaddr_ipx addr;
+ __kernel_uid_t mounted_uid;
+ int connection; /* Connection number the server assigned us */
+ int buffer_size; /* The negotiated buffer size, to be
+ used for read/write requests! */
+
+ int volume_number;
+ __u32 directory_id;
+};
+
+struct ncp_sign_init
+{
+ char sign_root[8];
+ char sign_last[16];
+};
+
+struct ncp_lock_ioctl
+{
+#define NCP_LOCK_LOG 0
+#define NCP_LOCK_SH 1
+#define NCP_LOCK_EX 2
+#define NCP_LOCK_CLEAR 256
+ int cmd;
+ int origin;
+ unsigned int offset;
+ unsigned int length;
+#define NCP_LOCK_DEFAULT_TIMEOUT 18
+#define NCP_LOCK_MAX_TIMEOUT 180
+ int timeout;
+};
+
+struct ncp_setroot_ioctl
+{
+ int volNumber;
+ int namespace;
+ __u32 dirEntNum;
+};
+
+struct ncp_objectname_ioctl
+{
+#define NCP_AUTH_NONE 0x00
+#define NCP_AUTH_BIND 0x31
+#define NCP_AUTH_NDS 0x32
+ int auth_type;
+ size_t object_name_len;
+ void* object_name; /* an userspace data, in most cases user name */
+};
+
+struct ncp_privatedata_ioctl
+{
+ size_t len;
+ void* data; /* ~1000 for NDS */
+};
+
+#define NCP_IOC_NCPREQUEST _IOR('n', 1, struct ncp_ioctl_request)
+#define NCP_IOC_GETMOUNTUID _IOW('n', 2, __kernel_uid_t)
+
+#if 1
+#ifdef __KERNEL__
+/* remove after ncpfs-2.0.13 gets released or at the beginning of kernel-2.1. codefreeze */
+#define NCP_IOC_GETMOUNTUID_INT _IOW('n', 2, unsigned int)
+#endif
+#endif
+
+#define NCP_IOC_CONN_LOGGED_IN _IO('n', 3)
+
+#define NCP_GET_FS_INFO_VERSION (1)
+#define NCP_IOC_GET_FS_INFO _IOWR('n', 4, struct ncp_fs_info)
+
+#define NCP_IOC_SIGN_INIT _IOR('n', 5, struct ncp_sign_init)
+#define NCP_IOC_SIGN_WANTED _IOR('n', 6, int)
+#define NCP_IOC_SET_SIGN_WANTED _IOW('n', 6, int)
+
+#define NCP_IOC_LOCKUNLOCK _IOR('n', 7, struct ncp_lock_ioctl)
+
+#define NCP_IOC_GETROOT _IOW('n', 8, struct ncp_setroot_ioctl)
+#define NCP_IOC_SETROOT _IOR('n', 8, struct ncp_setroot_ioctl)
+
+#define NCP_IOC_GETOBJECTNAME _IOWR('n', 9, struct ncp_objectname_ioctl)
+#define NCP_IOC_SETOBJECTNAME _IOR('n', 9, struct ncp_objectname_ioctl)
+#define NCP_IOC_GETPRIVATEDATA _IOWR('n', 10, struct ncp_privatedata_ioctl)
+#define NCP_IOC_SETPRIVATEDATA _IOR('n', 10, struct ncp_privatedata_ioctl)
+
+#define NCP_IOC_GETCHARSETS _IOWR('n', 11, struct ncp_nls_ioctl)
+#define NCP_IOC_SETCHARSETS _IOR('n', 11, struct ncp_nls_ioctl)
+
+/*
+ * The packet size to allocate. One page should be enough.
+ */
+#define NCP_PACKET_SIZE 4070
+
+#define NCP_MAXPATHLEN 255
+#define NCP_MAXNAMELEN 14
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#undef NCPFS_PARANOIA
+#ifndef DEBUG_NCP
+#define DEBUG_NCP 0
+#endif
+#if DEBUG_NCP > 0
+#define DPRINTK(format, args...) printk(format , ## args)
+#else
+#define DPRINTK(format, args...)
+#endif
+
+#if DEBUG_NCP > 1
+#define DDPRINTK(format, args...) printk(format , ## args)
+#else
+#define DDPRINTK(format, args...)
+#endif
+
+/* The readdir cache size controls how many directory entries are
+ * cached.
+ */
+#define NCP_READDIR_CACHE_SIZE 64
+
+#define NCP_MAX_RPC_TIMEOUT (6*HZ)
+
+/*
+ * This is the ncpfs part of the inode structure. This must contain
+ * all the information we need to work with an inode after creation.
+ * (Move to ncp_fs_i.h once it stabilizes, and add a union in fs.h)
+ */
+struct ncpfs_i {
+ __u32 dirEntNum __attribute__((packed));
+ __u32 DosDirNum __attribute__((packed));
+ __u32 volNumber __attribute__((packed));
+#ifdef CONFIG_NCPFS_SMALLDOS
+ __u32 origNS;
+#endif
+#ifdef CONFIG_NCPFS_STRONG
+ __u32 nwattr;
+#endif
+ int opened;
+ int access;
+ __u32 server_file_handle __attribute__((packed));
+ __u8 open_create_action __attribute__((packed));
+ __u8 file_handle[6] __attribute__((packed));
+};
+
+/*
+ * This is an extension of the nw_file_info structure with
+ * the additional information we need to create an inode.
+ */
+struct ncpfs_inode_info {
+ ino_t ino; /* dummy inode number */
+ struct nw_file_info nw_info;
+};
+
+/* Guess, what 0x564c is :-) */
+#define NCP_SUPER_MAGIC 0x564c
+
+
+#define NCP_SBP(sb) ((struct ncp_server *)((sb)->u.generic_sbp))
+
+#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb)
+/* We don't have an ncpfs union yet, so use smbfs ... */
+#define NCP_FINFO(inode) ((struct ncpfs_i *)&((inode)->u.smbfs_i))
+
+#ifdef DEBUG_NCP_MALLOC
+
+#include <linux/malloc.h>
+
+extern int ncp_malloced;
+extern int ncp_current_malloced;
+
+static inline void *
+ ncp_kmalloc(unsigned int size, int priority)
+{
+ ncp_malloced += 1;
+ ncp_current_malloced += 1;
+ return kmalloc(size, priority);
+}
+
+static inline void ncp_kfree_s(void *obj, int size)
+{
+ ncp_current_malloced -= 1;
+ kfree_s(obj, size);
+}
+
+#else /* DEBUG_NCP_MALLOC */
+
+#define ncp_kmalloc(s,p) kmalloc(s,p)
+#define ncp_kfree_s(o,s) kfree_s(o,s)
+
+#endif /* DEBUG_NCP_MALLOC */
+
+/* linux/fs/ncpfs/inode.c */
+int ncp_notify_change(struct dentry *, struct iattr *attr);
+struct super_block *ncp_read_super(struct super_block *, void *, int);
+struct inode *ncp_iget(struct super_block *, struct ncpfs_inode_info *);
+void ncp_update_inode(struct inode *, struct nw_file_info *);
+void ncp_update_inode2(struct inode *, struct nw_file_info *);
+extern int init_ncp_fs(void);
+
+/* linux/fs/ncpfs/dir.c */
+extern struct inode_operations ncp_dir_inode_operations;
+int ncp_conn_logged_in(struct ncp_server *);
+void ncp_init_dir_cache(void);
+void ncp_invalid_dir_cache(struct inode *);
+void ncp_free_dir_cache(void);
+int ncp_date_dos2unix(__u16 time, __u16 date);
+void ncp_date_unix2dos(int unix_date, __u16 * time, __u16 * date);
+
+/* linux/fs/ncpfs/ioctl.c */
+int ncp_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+
+/* linux/fs/ncpfs/sock.c */
+int ncp_request2(struct ncp_server *server, int function,
+ void* reply, int max_reply_size);
+static int inline ncp_request(struct ncp_server *server, int function) {
+ return ncp_request2(server, function, server->packet, server->packet_size);
+}
+int ncp_connect(struct ncp_server *server);
+int ncp_disconnect(struct ncp_server *server);
+void ncp_lock_server(struct ncp_server *server);
+void ncp_unlock_server(struct ncp_server *server);
+
+/* linux/fs/ncpfs/file.c */
+extern struct inode_operations ncp_file_inode_operations;
+int ncp_make_open(struct inode *, int);
+
+/* linux/fs/ncpfs/mmap.c */
+int ncp_mmap(struct file *, struct vm_area_struct *);
+
+/* linux/fs/ncpfs/ncplib_kernel.c */
+int ncp_make_closed(struct inode *);
+
+static inline void str_upper(char *name)
+{
+ while (*name) {
+ if (*name >= 'a' && *name <= 'z') {
+ *name -= ('a' - 'A');
+ }
+ name++;
+ }
+}
+
+static inline void str_lower(char *name)
+{
+ while (*name) {
+ if (*name >= 'A' && *name <= 'Z') {
+ *name += ('a' - 'A');
+ }
+ name++;
+ }
+}
+
+static inline int ncp_namespace(struct inode *inode)
+{
+ struct ncp_server *server = NCP_SERVER(inode);
+ return server->name_space[NCP_FINFO(inode)->volNumber];
+}
+
+static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) {
+#if defined(CONFIG_NCPFS_NFS_NS) || defined(CONFIG_NCPFS_OS2_NS)
+ int ns = ncp_namespace(i);
+#endif
+#if defined(CONFIG_NCPFS_SMALLDOS) && defined(CONFIG_NCPFS_OS2_NS)
+ if ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
+ return 0;
+#endif
+ return
+#ifdef CONFIG_NCPFS_OS2_NS
+ (ns == NW_NS_OS2) ||
+#endif /* CONFIG_NCPFS_OS2_NS */
+#ifdef CONFIG_NCPFS_NFS_NS
+ (ns == NW_NS_NFS) ||
+#endif /* CONFIG_NCPFS_NFS_NS */
+ 0;
+}
+
+static inline int ncp_preserve_case(struct inode *i)
+{
+ return ncp_preserve_entry_case(i, NW_NS_OS2);
+}
+
+static inline int ncp_case_sensitive(struct inode *i)
+{
+#ifdef CONFIG_NCPFS_NFS_NS
+ return ncp_namespace(i) == NW_NS_NFS;
+#else
+ return 0;
+#endif /* CONFIG_NCPFS_NFS_NS */
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_NCP_FS_H */
diff --git a/pfinet/linux-src/include/linux/ncp_fs_i.h b/pfinet/linux-src/include/linux/ncp_fs_i.h
new file mode 100644
index 00000000..3df38b28
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ncp_fs_i.h
@@ -0,0 +1,36 @@
+/*
+ * ncp_fs_i.h
+ *
+ * Copyright (C) 1995 Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_NCP_FS_I
+#define _LINUX_NCP_FS_I
+
+#include <linux/ncp.h>
+
+#ifdef __KERNEL__
+
+enum ncp_inode_state {
+ NCP_INODE_VALID = 19, /* Inode currently in use */
+ NCP_INODE_LOOKED_UP, /* directly before iget */
+ NCP_INODE_CACHED, /* in a path to an inode which is in use */
+ NCP_INODE_INVALID
+};
+
+/*
+ * ncp fs inode data (in memory only)
+ */
+struct ncp_inode_info {
+ enum ncp_inode_state state;
+ int nused; /* for directories:
+ number of references in memory */
+ struct ncp_inode_info *dir;
+ struct ncp_inode_info *next, *prev;
+ struct inode *inode;
+ struct nw_file_info finfo;
+};
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/ncp_fs_sb.h b/pfinet/linux-src/include/linux/ncp_fs_sb.h
new file mode 100644
index 00000000..43f902be
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ncp_fs_sb.h
@@ -0,0 +1,96 @@
+/*
+ * ncp_fs_sb.h
+ *
+ * Copyright (C) 1995, 1996 by Volker Lendecke
+ *
+ */
+
+#ifndef _NCP_FS_SB
+#define _NCP_FS_SB
+
+#include <asm/semaphore.h>
+#include <linux/ncp_mount.h>
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+
+#define NCP_DEFAULT_BUFSIZE 1024
+#define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */
+
+struct ncp_server {
+
+ struct ncp_mount_data m; /* Nearly all of the mount data is of
+ interest for us later, so we store
+ it completely. */
+
+ __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2];
+
+ struct file *ncp_filp; /* File pointer to ncp socket */
+
+ u8 sequence;
+ u8 task;
+ u16 connection; /* Remote connection number */
+
+ u8 completion; /* Status message from server */
+ u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
+ requests allowed anymore.
+ Bit 0 = 1 ==> Server is down. */
+
+ int buffer_size; /* Negotiated bufsize */
+
+ int reply_size; /* Size of last reply */
+
+ int packet_size;
+ unsigned char *packet; /* Here we prepare requests and
+ receive replies */
+
+ int lock; /* To prevent mismatch in protocols. */
+ struct semaphore sem;
+
+ int current_size; /* for packet preparation */
+ int has_subfunction;
+ int ncp_reply_size;
+
+ struct ncp_inode_info root;
+ struct dentry* root_dentry;
+
+ int root_setuped;
+
+/* info for packet signing */
+ int sign_wanted; /* 1=Server needs signed packets */
+ int sign_active; /* 0=don't do signing, 1=do */
+ char sign_root[8]; /* generated from password and encr. key */
+ char sign_last[16];
+
+ /* Authentication info: NDS or BINDERY, username */
+ struct {
+ int auth_type;
+ size_t object_name_len;
+ void* object_name;
+ int object_type;
+ } auth;
+ /* Password info */
+ struct {
+ size_t len;
+ void* data;
+ } priv;
+
+ struct ncp_nls_ioctl nls_charsets; /* NLS user data */
+ struct nls_table *nls_vol; /* codepage used on volume */
+ struct nls_table *nls_io; /* charset used for input and display */
+};
+
+static inline int ncp_conn_valid(struct ncp_server *server)
+{
+ return ((server->conn_status & 0x11) == 0);
+}
+
+static inline void ncp_invalidate_conn(struct ncp_server *server)
+{
+ server->conn_status |= 0x01;
+}
+
+#endif /* __KERNEL__ */
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/ncp_mount.h b/pfinet/linux-src/include/linux/ncp_mount.h
new file mode 100644
index 00000000..a214372a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ncp_mount.h
@@ -0,0 +1,45 @@
+/*
+ * ncp_mount.h
+ *
+ * Copyright (C) 1995, 1996 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_NCP_MOUNT_H
+#define _LINUX_NCP_MOUNT_H
+
+#include <linux/types.h>
+#include <linux/ipx.h>
+#include <linux/ncp.h>
+#include <linux/ncp_fs_i.h>
+
+#define NCP_MOUNT_VERSION 3
+
+/* Values for flags */
+#define NCP_MOUNT_SOFT 0x0001
+#define NCP_MOUNT_INTR 0x0002
+#define NCP_MOUNT_STRONG 0x0004 /* enable delete/rename of r/o files */
+#define NCP_MOUNT_NO_OS2 0x0008 /* do not use OS/2 (LONG) namespace */
+#define NCP_MOUNT_NO_NFS 0x0010 /* do not use NFS namespace */
+#define NCP_MOUNT_EXTRAS 0x0020
+#define NCP_MOUNT_SYMLINKS 0x0040 /* enable symlinks */
+
+struct ncp_mount_data {
+ int version;
+ unsigned int ncp_fd; /* The socket to the ncp port */
+ __kernel_uid_t mounted_uid; /* Who may umount() this filesystem? */
+ __kernel_pid_t wdog_pid; /* Who cares for our watchdog packets? */
+
+ unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
+ unsigned int time_out; /* How long should I wait after
+ sending a NCP request? */
+ unsigned int retry_count; /* And how often should I retry? */
+ unsigned int flags;
+
+ __kernel_uid_t uid;
+ __kernel_gid_t gid;
+ __kernel_mode_t file_mode;
+ __kernel_mode_t dir_mode;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/net.h b/pfinet/linux-src/include/linux/net.h
new file mode 100644
index 00000000..63e996f9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/net.h
@@ -0,0 +1,145 @@
+/*
+ * NET An implementation of the SOCKET network access protocol.
+ * This is the master header file for the Linux NET layer,
+ * or, in plain English: the networking handling part of the
+ * kernel.
+ *
+ * Version: @(#)net.h 1.0.3 05/25/93
+ *
+ * Authors: Orest Zborowski, <obz@Kodak.COM>
+ * Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_NET_H
+#define _LINUX_NET_H
+
+#include <linux/socket.h>
+
+struct poll_table_struct;
+
+#define NPROTO 32 /* should be enough for now.. */
+
+
+#define SYS_SOCKET 1 /* sys_socket(2) */
+#define SYS_BIND 2 /* sys_bind(2) */
+#define SYS_CONNECT 3 /* sys_connect(2) */
+#define SYS_LISTEN 4 /* sys_listen(2) */
+#define SYS_ACCEPT 5 /* sys_accept(2) */
+#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
+#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
+#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */
+#define SYS_SEND 9 /* sys_send(2) */
+#define SYS_RECV 10 /* sys_recv(2) */
+#define SYS_SENDTO 11 /* sys_sendto(2) */
+#define SYS_RECVFROM 12 /* sys_recvfrom(2) */
+#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */
+#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */
+#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
+#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
+#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
+
+
+typedef enum {
+ SS_FREE = 0, /* not allocated */
+ SS_UNCONNECTED, /* unconnected to any socket */
+ SS_CONNECTING, /* in process of connecting */
+ SS_CONNECTED, /* connected to socket */
+ SS_DISCONNECTING /* in process of disconnecting */
+} socket_state;
+
+#define SO_ACCEPTCON (1<<16) /* performed a listen */
+#define SO_WAITDATA (1<<17) /* wait data to read */
+#define SO_NOSPACE (1<<18) /* no space to write */
+
+#ifdef __KERNEL__
+
+struct socket
+{
+ socket_state state;
+
+ unsigned long flags;
+ struct proto_ops *ops;
+ struct inode *inode;
+ struct fasync_struct *fasync_list; /* Asynchronous wake up list */
+ struct file *file; /* File back pointer for gc */
+ struct sock *sk;
+ struct wait_queue *wait;
+
+ short type;
+ unsigned char passcred;
+ unsigned char tli;
+};
+
+#define SOCK_INODE(S) ((S)->inode)
+
+struct scm_cookie;
+
+struct proto_ops {
+ int family;
+
+ int (*dup) (struct socket *newsock, struct socket *oldsock);
+ int (*release) (struct socket *sock, struct socket *peer);
+ int (*bind) (struct socket *sock, struct sockaddr *umyaddr,
+ int sockaddr_len);
+ int (*connect) (struct socket *sock, struct sockaddr *uservaddr,
+ int sockaddr_len, int flags);
+ int (*socketpair) (struct socket *sock1, struct socket *sock2);
+ int (*accept) (struct socket *sock, struct socket *newsock,
+ int flags);
+ int (*getname) (struct socket *sock, struct sockaddr *uaddr,
+ int *usockaddr_len, int peer);
+ unsigned int (*poll) (struct file *file, struct socket *sock, struct poll_table_struct *wait);
+ int (*ioctl) (struct socket *sock, unsigned int cmd,
+ unsigned long arg);
+ int (*listen) (struct socket *sock, int len);
+ int (*shutdown) (struct socket *sock, int flags);
+ int (*setsockopt) (struct socket *sock, int level, int optname,
+ char *optval, int optlen);
+ int (*getsockopt) (struct socket *sock, int level, int optname,
+ char *optval, int *optlen);
+ int (*fcntl) (struct socket *sock, unsigned int cmd,
+ unsigned long arg);
+ int (*sendmsg) (struct socket *sock, struct msghdr *m, int total_len, struct scm_cookie *scm);
+ int (*recvmsg) (struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm);
+};
+
+struct net_proto_family
+{
+ int family;
+ int (*create)(struct socket *sock, int protocol);
+ /* These are counters for the number of different methods of
+ each we support */
+ short authentication;
+ short encryption;
+ short encrypt_net;
+};
+
+struct net_proto
+{
+ const char *name; /* Protocol name */
+ void (*init_func)(struct net_proto *); /* Bootstrap */
+};
+
+extern struct net_proto_family *net_families[];
+extern int sock_wake_async(struct socket *sk, int how);
+extern int sock_register(struct net_proto_family *fam);
+extern int sock_unregister(int family);
+extern struct socket *sock_alloc(void);
+extern int sock_create(int family, int type, int proto, struct socket **);
+extern void sock_release(struct socket *);
+extern int sock_sendmsg(struct socket *, struct msghdr *m, int len);
+extern int sock_recvmsg(struct socket *, struct msghdr *m, int len, int flags);
+extern int sock_readv_writev(int type, struct inode * inode, struct file * file,
+ const struct iovec * iov, long count, long size);
+
+extern int net_ratelimit(void);
+extern unsigned long net_random(void);
+extern void net_srandom(unsigned long);
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_NET_H */
diff --git a/pfinet/linux-src/include/linux/netbeui.h b/pfinet/linux-src/include/linux/netbeui.h
new file mode 100644
index 00000000..2fb2f71b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/netbeui.h
@@ -0,0 +1,16 @@
+#ifndef _LINUX_NETBEUI_H
+#define _LINUX_NETBEUI_H
+
+#include <linux/if.h>
+
+#define NB_NAME_LEN 20 /* Set this properly from the full docs when
+ I get them */
+
+struct sockaddr_netbeui
+{
+ sa_family snb_family;
+ char snb_name[NB_NAME_LEN];
+ char snb_devhint[IFNAMSIZ];
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/netdevice.h b/pfinet/linux-src/include/linux/netdevice.h
new file mode 100644
index 00000000..6d43f98d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/netdevice.h
@@ -0,0 +1,461 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the Interfaces handler.
+ *
+ * Version: @(#)dev.h 1.0.10 08/12/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Donald J. Becker, <becker@cesdis.gsfc.nasa.gov>
+ * Alan Cox, <Alan.Cox@linux.org>
+ * Bjorn Ekwall. <bj0rn@blox.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Moved to /usr/include/linux for NET3
+ */
+#ifndef _LINUX_NETDEVICE_H
+#define _LINUX_NETDEVICE_H
+
+#include <linux/config.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+#include <asm/atomic.h>
+
+#ifdef __KERNEL__
+#ifdef CONFIG_NET_PROFILE
+#include <net/profile.h>
+#endif
+#endif
+
+/*
+ * For future expansion when we will have different priorities.
+ */
+
+#define MAX_ADDR_LEN 7 /* Largest hardware address length */
+
+/*
+ * Compute the worst case header length according to the protocols
+ * used.
+ */
+
+#if !defined(CONFIG_AX25) && !defined(CONFIG_AX25_MODULE) && !defined(CONFIG_TR)
+#define LL_MAX_HEADER 32
+#else
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+#define LL_MAX_HEADER 96
+#else
+#define LL_MAX_HEADER 48
+#endif
+#endif
+
+#if !defined(CONFIG_NET_IPIP) && \
+ !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE)
+#define MAX_HEADER LL_MAX_HEADER
+#else
+#define MAX_HEADER (LL_MAX_HEADER + 48)
+#endif
+
+/*
+ * Network device statistics. Akin to the 2.0 ether stats but
+ * with byte counters.
+ */
+
+struct net_device_stats
+{
+ unsigned long rx_packets; /* total packets received */
+ unsigned long tx_packets; /* total packets transmitted */
+ unsigned long rx_bytes; /* total bytes received */
+ unsigned long tx_bytes; /* total bytes transmitted */
+ unsigned long rx_errors; /* bad packets received */
+ unsigned long tx_errors; /* packet transmit problems */
+ unsigned long rx_dropped; /* no space in linux buffers */
+ unsigned long tx_dropped; /* no space available in linux */
+ unsigned long multicast; /* multicast packets received */
+ unsigned long collisions;
+
+ /* detailed rx_errors: */
+ unsigned long rx_length_errors;
+ unsigned long rx_over_errors; /* receiver ring buff overflow */
+ unsigned long rx_crc_errors; /* recved pkt with crc error */
+ unsigned long rx_frame_errors; /* recv'd frame alignment error */
+ unsigned long rx_fifo_errors; /* recv'r fifo overrun */
+ unsigned long rx_missed_errors; /* receiver missed packet */
+
+ /* detailed tx_errors */
+ unsigned long tx_aborted_errors;
+ unsigned long tx_carrier_errors;
+ unsigned long tx_fifo_errors;
+ unsigned long tx_heartbeat_errors;
+ unsigned long tx_window_errors;
+
+ /* for cslip etc */
+ unsigned long rx_compressed;
+ unsigned long tx_compressed;
+};
+
+#ifdef CONFIG_NET_FASTROUTE
+struct net_fastroute_stats
+{
+ int hits;
+ int succeed;
+ int deferred;
+ int latency_reduction;
+};
+#endif
+
+/* Media selection options. */
+enum {
+ IF_PORT_UNKNOWN = 0,
+ IF_PORT_10BASE2,
+ IF_PORT_10BASET,
+ IF_PORT_AUI,
+ IF_PORT_100BASET,
+ IF_PORT_100BASETX,
+ IF_PORT_100BASEFX
+};
+
+#ifdef __KERNEL__
+
+extern const char *if_port_text[];
+
+#include <linux/skbuff.h>
+
+struct neighbour;
+struct neigh_parms;
+struct sk_buff;
+
+/*
+ * We tag multicasts with these structures.
+ */
+
+struct dev_mc_list
+{
+ struct dev_mc_list *next;
+ __u8 dmi_addr[MAX_ADDR_LEN];
+ unsigned char dmi_addrlen;
+ int dmi_users;
+ int dmi_gusers;
+};
+
+struct hh_cache
+{
+ struct hh_cache *hh_next; /* Next entry */
+ atomic_t hh_refcnt; /* number of users */
+ unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP */
+ int (*hh_output)(struct sk_buff *skb);
+ rwlock_t hh_lock;
+ /* cached hardware header; allow for machine alignment needs. */
+ unsigned long hh_data[16/sizeof(unsigned long)];
+};
+
+
+/*
+ * The DEVICE structure.
+ * Actually, this whole structure is a big mistake. It mixes I/O
+ * data with strictly "high-level" data, and it has to know about
+ * almost every data structure used in the INET module.
+ *
+ * FIXME: cleanup struct device such that network protocol info
+ * moves out.
+ */
+
+struct device
+{
+
+ /*
+ * This is the first field of the "visible" part of this structure
+ * (i.e. as seen by users in the "Space.c" file). It is the name
+ * the interface.
+ */
+ char *name;
+
+ /*
+ * I/O specific fields
+ * FIXME: Merge these and struct ifmap into one
+ */
+ unsigned long rmem_end; /* shmem "recv" end */
+ unsigned long rmem_start; /* shmem "recv" start */
+ unsigned long mem_end; /* shared mem end */
+ unsigned long mem_start; /* shared mem start */
+ unsigned long base_addr; /* device I/O address */
+ unsigned int irq; /* device IRQ number */
+
+ /* Low-level status flags. */
+ volatile unsigned char start; /* start an operation */
+ /*
+ * These two are just single-bit flags, but due to atomicity
+ * reasons they have to be inside a "unsigned long". However,
+ * they should be inside the SAME unsigned long instead of
+ * this wasteful use of memory..
+ */
+ unsigned long interrupt; /* bitops.. */
+ unsigned long tbusy; /* transmitter busy */
+
+ struct device *next;
+
+ /* The device initialization function. Called only once. */
+ int (*init)(struct device *dev);
+ void (*destructor)(struct device *dev);
+
+ /* Interface index. Unique device identifier */
+ int ifindex;
+ int iflink;
+
+ /*
+ * Some hardware also needs these fields, but they are not
+ * part of the usual set specified in Space.c.
+ */
+
+ unsigned char if_port; /* Selectable AUI, TP,..*/
+ unsigned char dma; /* DMA channel */
+
+ struct net_device_stats* (*get_stats)(struct device *dev);
+ struct iw_statistics* (*get_wireless_stats)(struct device *dev);
+
+ /*
+ * This marks the end of the "visible" part of the structure. All
+ * fields hereafter are internal to the system, and may change at
+ * will (read: may be cleaned up at will).
+ */
+
+ /* These may be needed for future network-power-down code. */
+ unsigned long trans_start; /* Time (in jiffies) of last Tx */
+ unsigned long last_rx; /* Time of last Rx */
+
+ unsigned short flags; /* interface flags (a la BSD) */
+ unsigned short gflags;
+ unsigned mtu; /* interface MTU value */
+ unsigned short type; /* interface hardware type */
+ unsigned short hard_header_len; /* hardware hdr length */
+ void *priv; /* pointer to private data */
+
+ /* Interface address info. */
+ unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
+ unsigned char pad; /* make dev_addr aligned to 8 bytes */
+ unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */
+ unsigned char addr_len; /* hardware address length */
+
+ struct dev_mc_list *mc_list; /* Multicast mac addresses */
+ int mc_count; /* Number of installed mcasts */
+ int promiscuity;
+ int allmulti;
+
+ /* For load balancing driver pair support */
+
+ unsigned long pkt_queue; /* Packets queued */
+ struct device *slave; /* Slave device */
+
+ /* Protocol specific pointers */
+
+ void *atalk_ptr; /* AppleTalk link */
+ void *ip_ptr; /* IPv4 specific data */
+ void *dn_ptr; /* DECnet specific data */
+
+ struct Qdisc *qdisc;
+ struct Qdisc *qdisc_sleeping;
+ struct Qdisc *qdisc_list;
+ unsigned long tx_queue_len; /* Max frames per queue allowed */
+
+ /* Pointers to interface service routines. */
+ int (*open)(struct device *dev);
+ int (*stop)(struct device *dev);
+ int (*hard_start_xmit) (struct sk_buff *skb,
+ struct device *dev);
+ int (*hard_header) (struct sk_buff *skb,
+ struct device *dev,
+ unsigned short type,
+ void *daddr,
+ void *saddr,
+ unsigned len);
+ int (*rebuild_header)(struct sk_buff *skb);
+#define HAVE_MULTICAST
+ void (*set_multicast_list)(struct device *dev);
+#define HAVE_SET_MAC_ADDR
+ int (*set_mac_address)(struct device *dev,
+ void *addr);
+#define HAVE_PRIVATE_IOCTL
+ int (*do_ioctl)(struct device *dev,
+ struct ifreq *ifr, int cmd);
+#define HAVE_SET_CONFIG
+ int (*set_config)(struct device *dev,
+ struct ifmap *map);
+#define HAVE_HEADER_CACHE
+ int (*hard_header_cache)(struct neighbour *neigh,
+ struct hh_cache *hh);
+ void (*header_cache_update)(struct hh_cache *hh,
+ struct device *dev,
+ unsigned char * haddr);
+#define HAVE_CHANGE_MTU
+ int (*change_mtu)(struct device *dev, int new_mtu);
+
+ int (*hard_header_parse)(struct sk_buff *skb,
+ unsigned char *haddr);
+ int (*neigh_setup)(struct device *dev, struct neigh_parms *);
+ int (*accept_fastpath)(struct device *, struct dst_entry*);
+
+#ifdef CONFIG_NET_FASTROUTE
+ /* Really, this semaphore may be necessary and for not fastroute code;
+ f.e. SMP??
+ */
+ int tx_semaphore;
+#define NETDEV_FASTROUTE_HMASK 0xF
+ /* Semi-private data. Keep it at the end of device struct. */
+ struct dst_entry *fastpath[NETDEV_FASTROUTE_HMASK+1];
+#endif
+};
+
+
+struct packet_type
+{
+ unsigned short type; /* This is really htons(ether_type). */
+ struct device *dev; /* NULL is wildcarded here */
+ int (*func) (struct sk_buff *, struct device *,
+ struct packet_type *);
+ void *data; /* Private to the packet type */
+ struct packet_type *next;
+};
+
+
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+
+extern struct device loopback_dev; /* The loopback */
+extern struct device *dev_base; /* All devices */
+extern struct packet_type *ptype_base[16]; /* Hashed types */
+extern int netdev_dropping;
+extern int net_cpu_congestion;
+
+extern struct device *dev_getbyhwaddr(unsigned short type, char *hwaddr);
+extern void dev_add_pack(struct packet_type *pt);
+extern void dev_remove_pack(struct packet_type *pt);
+extern struct device *dev_get(const char *name);
+extern struct device *dev_alloc(const char *name, int *err);
+extern int dev_alloc_name(struct device *dev, const char *name);
+extern int dev_open(struct device *dev);
+extern int dev_close(struct device *dev);
+extern int dev_queue_xmit(struct sk_buff *skb);
+extern void dev_loopback_xmit(struct sk_buff *skb);
+extern int register_netdevice(struct device *dev);
+extern int unregister_netdevice(struct device *dev);
+extern int register_netdevice_notifier(struct notifier_block *nb);
+extern int unregister_netdevice_notifier(struct notifier_block *nb);
+extern int dev_new_index(void);
+extern struct device *dev_get_by_index(int ifindex);
+extern int dev_restart(struct device *dev);
+
+typedef int gifconf_func_t(struct device * dev, char * bufptr, int len);
+extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf);
+extern __inline__ int unregister_gifconf(unsigned int family)
+{
+ return register_gifconf(family, 0);
+}
+
+#define HAVE_NETIF_RX 1
+extern void netif_rx(struct sk_buff *skb);
+extern void net_bh(void);
+extern int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
+extern int dev_ioctl(unsigned int cmd, void *);
+extern int dev_change_flags(struct device *, unsigned);
+extern void dev_queue_xmit_nit(struct sk_buff *skb, struct device *dev);
+
+extern void dev_init(void);
+
+extern int netdev_nit;
+
+/* Locking protection for page faults during outputs to devices unloaded during the fault */
+
+extern atomic_t dev_lockct;
+
+/*
+ * These two don't currently need to be atomic
+ * but they may do soon. Do it properly anyway.
+ */
+
+extern __inline__ void dev_lock_list(void)
+{
+ atomic_inc(&dev_lockct);
+}
+
+extern __inline__ void dev_unlock_list(void)
+{
+ atomic_dec(&dev_lockct);
+}
+
+/*
+ * This almost never occurs, isn't in performance critical paths
+ * and we can thus be relaxed about it.
+ *
+ * FIXME: What if this is being run as a real time process ??
+ * Linus: We need a way to force a yield here ?
+ *
+ * FIXME: Though dev_lockct is atomic varible, locking procedure
+ * is not atomic.
+ */
+
+extern __inline__ void dev_lock_wait(void)
+{
+ while (atomic_read(&dev_lockct)) {
+ current->policy |= SCHED_YIELD;
+ schedule();
+ }
+}
+
+extern __inline__ void dev_init_buffers(struct device *dev)
+{
+ /* DO NOTHING */
+}
+
+/* These functions live elsewhere (drivers/net/net_init.c, but related) */
+
+extern void ether_setup(struct device *dev);
+extern void fddi_setup(struct device *dev);
+extern void tr_setup(struct device *dev);
+extern void fc_setup(struct device *dev);
+extern void tr_freedev(struct device *dev);
+extern void fc_freedev(struct device *dev);
+extern int ether_config(struct device *dev, struct ifmap *map);
+/* Support for loadable net-drivers */
+extern int register_netdev(struct device *dev);
+extern void unregister_netdev(struct device *dev);
+extern int register_trdev(struct device *dev);
+extern void unregister_trdev(struct device *dev);
+extern int register_fcdev(struct device *dev);
+extern void unregister_fcdev(struct device *dev);
+/* Functions used for multicast support */
+extern void dev_mc_upload(struct device *dev);
+extern int dev_mc_delete(struct device *dev, void *addr, int alen, int all);
+extern int dev_mc_add(struct device *dev, void *addr, int alen, int newonly);
+extern void dev_mc_discard(struct device *dev);
+extern void dev_set_promiscuity(struct device *dev, int inc);
+extern void dev_set_allmulti(struct device *dev, int inc);
+extern void netdev_state_change(struct device *dev);
+/* Load a device via the kmod */
+extern void dev_load(const char *name);
+extern void dev_mcast_init(void);
+extern int netdev_register_fc(struct device *dev, void (*stimul)(struct device *dev));
+extern void netdev_unregister_fc(int bit);
+extern int netdev_dropping;
+extern int netdev_max_backlog;
+extern atomic_t netdev_rx_dropped;
+extern unsigned long netdev_fc_xoff;
+#ifdef CONFIG_NET_FASTROUTE
+extern int netdev_fastroute;
+extern int netdev_fastroute_obstacles;
+extern void dev_clear_fastroute(struct device *dev);
+extern struct net_fastroute_stats dev_fastroute_stat;
+#endif
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_DEV_H */
diff --git a/pfinet/linux-src/include/linux/netlink.h b/pfinet/linux-src/include/linux/netlink.h
new file mode 100644
index 00000000..59075b07
--- /dev/null
+++ b/pfinet/linux-src/include/linux/netlink.h
@@ -0,0 +1,158 @@
+#ifndef __LINUX_NETLINK_H
+#define __LINUX_NETLINK_H
+
+#define NETLINK_ROUTE 0 /* Routing/device hook */
+#define NETLINK_SKIP 1 /* Reserved for ENskip */
+#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
+#define NETLINK_FIREWALL 3 /* Firewalling hook */
+#define NETLINK_ARPD 8
+#define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */
+#define NETLINK_IP6_FW 13
+#define NETLINK_TAPBASE 16 /* 16 to 31 are ethertap */
+
+#define MAX_LINKS 32
+
+struct sockaddr_nl
+{
+ sa_family_t nl_family; /* AF_NETLINK */
+ unsigned short nl_pad; /* zero */
+ __u32 nl_pid; /* process pid */
+ __u32 nl_groups; /* multicast groups mask */
+};
+
+struct nlmsghdr
+{
+ __u32 nlmsg_len; /* Length of message including header */
+ __u16 nlmsg_type; /* Message content */
+ __u16 nlmsg_flags; /* Additional flags */
+ __u32 nlmsg_seq; /* Sequence number */
+ __u32 nlmsg_pid; /* Sending process PID */
+};
+
+/* Flags values */
+
+#define NLM_F_REQUEST 1 /* It is request message. */
+#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
+#define NLM_F_ACK 4 /* If succeed, reply with ack */
+#define NLM_F_ECHO 8 /* Echo this request */
+
+/* Modifiers to GET request */
+#define NLM_F_ROOT 0x100 /* specify tree root */
+#define NLM_F_MATCH 0x200 /* return all matching */
+#define NLM_F_ATOMIC 0x400 /* atomic GET */
+#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
+
+/* Modifiers to NEW request */
+#define NLM_F_REPLACE 0x100 /* Override existing */
+#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
+#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
+#define NLM_F_APPEND 0x800 /* Add to end of list */
+
+/*
+ 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
+ 4.4BSD CHANGE NLM_F_REPLACE
+
+ True CHANGE NLM_F_CREATE|NLM_F_REPLACE
+ Append NLM_F_CREATE
+ Check NLM_F_EXCL
+ */
+
+#define NLMSG_ALIGNTO 4
+#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
+#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
+#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
+#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
+ (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
+#define NLMSG_OK(nlh,len) ((len) > 0 && (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
+ (nlh)->nlmsg_len <= (len))
+#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
+
+#define NLMSG_NOOP 0x1 /* Nothing. */
+#define NLMSG_ERROR 0x2 /* Error */
+#define NLMSG_DONE 0x3 /* End of a dump */
+#define NLMSG_OVERRUN 0x4 /* Data lost */
+
+struct nlmsgerr
+{
+ int error;
+ struct nlmsghdr msg;
+};
+
+#define NET_MAJOR 36 /* Major 36 is reserved for networking */
+
+#ifdef __KERNEL__
+
+struct netlink_skb_parms
+{
+ struct ucred creds; /* Skb credentials */
+ __u32 pid;
+ __u32 groups;
+ __u32 dst_pid;
+ __u32 dst_groups;
+ kernel_cap_t eff_cap;
+};
+
+#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))
+#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds)
+
+
+extern int netlink_attach(int unit, int (*function)(int,struct sk_buff *skb));
+extern void netlink_detach(int unit);
+extern int netlink_post(int unit, struct sk_buff *skb);
+extern int init_netlink(void);
+extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len));
+extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
+extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
+extern void netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
+ __u32 group, int allocation);
+extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
+
+/*
+ * skb should fit one page. This choice is good for headerless malloc.
+ *
+ * FIXME: What is the best size for SLAB???? --ANK
+ */
+#define NLMSG_GOODSIZE (PAGE_SIZE - ((sizeof(struct sk_buff)+0xF)&~0xF))
+
+
+struct netlink_callback
+{
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ int (*dump)(struct sk_buff * skb, struct netlink_callback *cb);
+ int (*done)(struct netlink_callback *cb);
+ int family;
+ long args[4];
+};
+
+extern __inline__ struct nlmsghdr *
+__nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len)
+{
+ struct nlmsghdr *nlh;
+ int size = NLMSG_LENGTH(len);
+
+ nlh = (struct nlmsghdr*)skb_put(skb, NLMSG_ALIGN(size));
+ nlh->nlmsg_type = type;
+ nlh->nlmsg_len = size;
+ nlh->nlmsg_flags = 0;
+ nlh->nlmsg_pid = pid;
+ nlh->nlmsg_seq = seq;
+ return nlh;
+}
+
+#define NLMSG_PUT(skb, pid, seq, type, len) \
+({ if (skb_tailroom(skb) < (int)NLMSG_SPACE(len)) goto nlmsg_failure; \
+ __nlmsg_put(skb, pid, seq, type, len); })
+
+extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+ struct nlmsghdr *nlh,
+ int (*dump)(struct sk_buff *skb, struct netlink_callback*),
+ int (*done)(struct netlink_callback*));
+
+
+extern void netlink_proto_init(struct net_proto *pro);
+
+#endif /* __KERNEL__ */
+
+#endif /* __LINUX_NETLINK_H */
diff --git a/pfinet/linux-src/include/linux/netrom.h b/pfinet/linux-src/include/linux/netrom.h
new file mode 100644
index 00000000..6939b32f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/netrom.h
@@ -0,0 +1,34 @@
+/*
+ * These are the public elements of the Linux kernel NET/ROM implementation.
+ * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the
+ * definition of the ax25_address structure.
+ */
+
+#ifndef NETROM_KERNEL_H
+#define NETROM_KERNEL_H
+
+#define NETROM_MTU 236
+
+#define NETROM_T1 1
+#define NETROM_T2 2
+#define NETROM_N2 3
+#define NETROM_T4 6
+#define NETROM_IDLE 7
+
+#define SIOCNRDECOBS (SIOCPROTOPRIVATE+2)
+
+struct nr_route_struct {
+#define NETROM_NEIGH 0
+#define NETROM_NODE 1
+ int type;
+ ax25_address callsign;
+ char device[16];
+ unsigned int quality;
+ char mnemonic[7];
+ ax25_address neighbour;
+ unsigned int obs_count;
+ unsigned int ndigis;
+ ax25_address digipeaters[AX25_MAX_DIGIS];
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/nfs.h b/pfinet/linux-src/include/linux/nfs.h
new file mode 100644
index 00000000..7936d5a7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nfs.h
@@ -0,0 +1,226 @@
+/*
+ * NFS protocol definitions
+ */
+#ifndef _LINUX_NFS_H
+#define _LINUX_NFS_H
+
+#include <linux/sunrpc/msg_prot.h>
+
+#define NFS_PORT 2049
+#define NFS_MAXDATA 8192
+#define NFS_MAXPATHLEN 1024
+#define NFS_MAXNAMLEN 255
+#define NFS_MAXGROUPS 16
+#define NFS_FHSIZE 32
+#define NFS_COOKIESIZE 4
+#define NFS_FIFO_DEV (-1)
+#define NFSMODE_FMT 0170000
+#define NFSMODE_DIR 0040000
+#define NFSMODE_CHR 0020000
+#define NFSMODE_BLK 0060000
+#define NFSMODE_REG 0100000
+#define NFSMODE_LNK 0120000
+#define NFSMODE_SOCK 0140000
+#define NFSMODE_FIFO 0010000
+
+
+enum nfs_stat {
+ NFS_OK = 0,
+ NFSERR_PERM = 1,
+ NFSERR_NOENT = 2,
+ NFSERR_IO = 5,
+ NFSERR_NXIO = 6,
+ NFSERR_EAGAIN = 11,
+ NFSERR_ACCES = 13,
+ NFSERR_EXIST = 17,
+ NFSERR_XDEV = 18,
+ NFSERR_NODEV = 19,
+ NFSERR_NOTDIR = 20,
+ NFSERR_ISDIR = 21,
+ NFSERR_INVAL = 22, /* that Sun forgot */
+ NFSERR_FBIG = 27,
+ NFSERR_NOSPC = 28,
+ NFSERR_ROFS = 30,
+ NFSERR_OPNOTSUPP = 45,
+ NFSERR_NAMETOOLONG = 63,
+ NFSERR_NOTEMPTY = 66,
+ NFSERR_DQUOT = 69,
+ NFSERR_STALE = 70,
+ NFSERR_WFLUSH = 99
+};
+
+enum nfs_ftype {
+ NFNON = 0,
+ NFREG = 1,
+ NFDIR = 2,
+ NFBLK = 3,
+ NFCHR = 4,
+ NFLNK = 5,
+ NFSOCK = 6,
+ NFBAD = 7,
+ NFFIFO = 8
+};
+
+struct nfs_fh {
+ char data[NFS_FHSIZE];
+};
+
+#define NFS_PROGRAM 100003
+#define NFS_VERSION 2
+#define NFSPROC_NULL 0
+#define NFSPROC_GETATTR 1
+#define NFSPROC_SETATTR 2
+#define NFSPROC_ROOT 3
+#define NFSPROC_LOOKUP 4
+#define NFSPROC_READLINK 5
+#define NFSPROC_READ 6
+#define NFSPROC_WRITECACHE 7
+#define NFSPROC_WRITE 8
+#define NFSPROC_CREATE 9
+#define NFSPROC_REMOVE 10
+#define NFSPROC_RENAME 11
+#define NFSPROC_LINK 12
+#define NFSPROC_SYMLINK 13
+#define NFSPROC_MKDIR 14
+#define NFSPROC_RMDIR 15
+#define NFSPROC_READDIR 16
+#define NFSPROC_STATFS 17
+
+/* Mount support for NFSroot */
+#ifdef __KERNEL__
+#define NFS_MNT_PROGRAM 100005
+#define NFS_MNT_VERSION 1
+#define NFS_MNT_PORT 627
+#define NFS_MNTPROC_MNT 1
+#define NFS_MNTPROC_UMNT 3
+#endif
+
+#if defined(__KERNEL__) || defined(NFS_NEED_KERNEL_TYPES)
+
+extern struct rpc_program nfs_program;
+extern struct rpc_stat nfs_rpcstat;
+
+struct nfs_time {
+ __u32 seconds;
+ __u32 useconds;
+};
+
+struct nfs_fattr {
+ enum nfs_ftype type;
+ __u32 mode;
+ __u32 nlink;
+ __u32 uid;
+ __u32 gid;
+ __u32 size;
+ __u32 blocksize;
+ __u32 rdev;
+ __u32 blocks;
+ __u32 fsid;
+ __u32 fileid;
+ struct nfs_time atime;
+ struct nfs_time mtime;
+ struct nfs_time ctime;
+};
+
+struct nfs_sattr {
+ __u32 mode;
+ __u32 uid;
+ __u32 gid;
+ __u32 size;
+ struct nfs_time atime;
+ struct nfs_time mtime;
+};
+
+struct nfs_fsinfo {
+ __u32 tsize;
+ __u32 bsize;
+ __u32 blocks;
+ __u32 bfree;
+ __u32 bavail;
+};
+
+struct nfs_writeargs {
+ struct nfs_fh * fh;
+ __u32 offset;
+ __u32 count;
+ const void * buffer;
+};
+
+#ifdef NFS_NEED_XDR_TYPES
+
+struct nfs_sattrargs {
+ struct nfs_fh * fh;
+ struct nfs_sattr * sattr;
+};
+
+struct nfs_diropargs {
+ struct nfs_fh * fh;
+ const char * name;
+};
+
+struct nfs_readargs {
+ struct nfs_fh * fh;
+ __u32 offset;
+ __u32 count;
+ void * buffer;
+};
+
+struct nfs_createargs {
+ struct nfs_fh * fh;
+ const char * name;
+ struct nfs_sattr * sattr;
+};
+
+struct nfs_renameargs {
+ struct nfs_fh * fromfh;
+ const char * fromname;
+ struct nfs_fh * tofh;
+ const char * toname;
+};
+
+struct nfs_linkargs {
+ struct nfs_fh * fromfh;
+ struct nfs_fh * tofh;
+ const char * toname;
+};
+
+struct nfs_symlinkargs {
+ struct nfs_fh * fromfh;
+ const char * fromname;
+ const char * topath;
+ struct nfs_sattr * sattr;
+};
+
+struct nfs_readdirargs {
+ struct nfs_fh * fh;
+ __u32 cookie;
+ void * buffer;
+ unsigned int bufsiz;
+};
+
+struct nfs_diropok {
+ struct nfs_fh * fh;
+ struct nfs_fattr * fattr;
+};
+
+struct nfs_readres {
+ struct nfs_fattr * fattr;
+ unsigned int count;
+};
+
+struct nfs_readlinkres {
+ char ** string;
+ unsigned int * lenp;
+ unsigned int maxlen;
+ void * buffer;
+};
+
+struct nfs_readdirres {
+ void * buffer;
+ unsigned int bufsiz;
+};
+
+#endif /* NFS_NEED_XDR_TYPES */
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/nfs3.h b/pfinet/linux-src/include/linux/nfs3.h
new file mode 100644
index 00000000..94ec44b6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nfs3.h
@@ -0,0 +1,252 @@
+/*
+ * NFSv3 protocol definitions
+ */
+#ifndef _LINUX_NFS3_H
+#define _LINUX_NFS3_H
+
+#include <linux/sunrpc/msg_prot.h>
+#include <linux/nfs.h>
+
+#define NFS3_PORT 2049
+#define NFS3_MAXDATA 8192
+#define NFS3_MAXPATHLEN PATH_MAX
+#define NFS3_MAXNAMLEN NAME_MAX
+#define NFS3_MAXGROUPS 16
+#define NFS3_FHSIZE NFS_FHSIZE
+#define NFS3_COOKIESIZE 4
+#define NFS3_FIFO_DEV (-1)
+#define NFS3MODE_FMT 0170000
+#define NFS3MODE_DIR 0040000
+#define NFS3MODE_CHR 0020000
+#define NFS3MODE_BLK 0060000
+#define NFS3MODE_REG 0100000
+#define NFS3MODE_LNK 0120000
+#define NFS3MODE_SOCK 0140000
+#define NFS3MODE_FIFO 0010000
+
+
+enum nfs3_stat {
+ NFS3_OK = 0,
+ NFS3ERR_PERM = 1,
+ NFS3ERR_NOENT = 2,
+ NFS3ERR_IO = 5,
+ NFS3ERR_NXIO = 6,
+ NFS3ERR_EAGAIN = 11,
+ NFS3ERR_ACCES = 13,
+ NFS3ERR_EXIST = 17,
+ NFS3ERR_XDEV = 18, /* new in NFSv3 */
+ NFS3ERR_NODEV = 19,
+ NFS3ERR_NOTDIR = 20,
+ NFS3ERR_ISDIR = 21,
+ NFS3ERR_INVAL = 22, /* new in NFSv3 */
+ NFS3ERR_FBIG = 27,
+ NFS3ERR_NOSPC = 28,
+ NFS3ERR_ROFS = 30,
+ NFS3ERR_MLINK = 31, /* new in NFSv3 */
+ NFS3ERR_NAMETOOLONG = 63,
+ NFS3ERR_NOTEMPTY = 66,
+ NFS3ERR_DQUOT = 69,
+ NFS3ERR_STALE = 70,
+ NFS3ERR_REMOTE = 71, /* new in NFSv3 */
+ NFS3ERR_BADHANDLE = 10001,/* ditto */
+ NFS3ERR_NOT_SYNC = 10002,/* ditto */
+ NFS3ERR_BAD_COOKIE = 10003,/* ditto */
+ NFS3ERR_NOTSUPP = 10004,/* ditto */
+ NFS3ERR_TOOSMALL = 10005,/* ditto */
+ NFS3ERR_SERVERFAULT = 10006,/* ditto */
+ NFS3ERR_BADTYPE = 10007,/* ditto */
+ NFS3ERR_JUKEBOX = 10008,/* ditto */
+};
+
+enum nfs3_ftype {
+ NF3NON = 0,
+ NF3REG = 1,
+ NF3DIR = 2,
+ NF3BLK = 3,
+ NF3CHR = 4,
+ NF3LNK = 5,
+ NF3SOCK = 6,
+ NF3FIFO = 7, /* changed from NFSv2 (was 8) */
+ NF3BAD = 8
+};
+
+#define NFS3_VERSION 3
+#define NFSPROC_NULL 0
+#define NFSPROC_GETATTR 1
+#define NFSPROC_SETATTR 2
+#define NFSPROC_ROOT 3
+#define NFSPROC_LOOKUP 4
+#define NFSPROC_READLINK 5
+#define NFSPROC_READ 6
+#define NFSPROC_WRITECACHE 7
+#define NFSPROC_WRITE 8
+#define NFSPROC_CREATE 9
+#define NFSPROC_REMOVE 10
+#define NFSPROC_RENAME 11
+#define NFSPROC_LINK 12
+#define NFSPROC_SYMLINK 13
+#define NFSPROC_MKDIR 14
+#define NFSPROC_RMDIR 15
+#define NFSPROC_READDIR 16
+#define NFSPROC_STATFS 17
+
+#if defined(__KERNEL__) || defined(NFS_NEED_KERNEL_TYPES)
+
+struct nfs3_fh {
+ __u32 size;
+ __u8 data[NFS3_FHSIZE];
+};
+
+struct nfs3_fattr {
+ enum nfs3_ftype type;
+ __u32 mode;
+ __u32 nlink;
+ __u32 uid;
+ __u32 gid;
+ __u64 size;
+ __u64 used;
+ __u32 rdev_maj;
+ __u32 rdev_min;
+ __u32 fsid;
+ __u32 fileid;
+ struct nfs_time atime;
+ struct nfs_time mtime;
+ struct nfs_time ctime;
+};
+
+struct nfs3_wcc_attr {
+ __u64 size;
+ struct nfs_time mtime;
+ struct nfs_time ctime;
+};
+
+struct nfs3_wcc_data {
+ struct nfs3_wcc_attr before;
+ struct nfs3_wcc_attr after;
+};
+
+struct nfs3_sattr {
+ __u32 valid;
+ __u32 mode;
+ __u32 uid;
+ __u32 gid;
+ __u64 size;
+ struct nfs_time atime;
+ struct nfs_time mtime;
+};
+
+struct nfs3_entry {
+ __u32 fileid;
+ char * name;
+ unsigned int length;
+ __u32 cookie;
+ __u32 eof;
+};
+
+struct nfs3_fsinfo {
+ __u32 tsize;
+ __u32 bsize;
+ __u32 blocks;
+ __u32 bfree;
+ __u32 bavail;
+};
+
+#ifdef NFS_NEED_XDR_TYPES
+
+struct nfs3_sattrargs {
+ struct nfs_fh * fh;
+ struct nfs_sattr * sattr;
+};
+
+struct nfs3_diropargs {
+ struct nfs_fh * fh;
+ const char * name;
+};
+
+struct nfs3_readargs {
+ struct nfs_fh * fh;
+ __u32 offset;
+ __u32 count;
+ void * buffer;
+};
+
+struct nfs3_writeargs {
+ struct nfs_fh * fh;
+ __u32 offset;
+ __u32 count;
+ const void * buffer;
+};
+
+struct nfs3_createargs {
+ struct nfs_fh * fh;
+ const char * name;
+ struct nfs_sattr * sattr;
+};
+
+struct nfs3_renameargs {
+ struct nfs_fh * fromfh;
+ const char * fromname;
+ struct nfs_fh * tofh;
+ const char * toname;
+};
+
+struct nfs3_linkargs {
+ struct nfs_fh * fromfh;
+ struct nfs_fh * tofh;
+ const char * toname;
+};
+
+struct nfs3_symlinkargs {
+ struct nfs_fh * fromfh;
+ const char * fromname;
+ const char * topath;
+ struct nfs_sattr * sattr;
+};
+
+struct nfs3_readdirargs {
+ struct nfs_fh * fh;
+ __u32 cookie;
+ void * buffer;
+ unsigned int bufsiz;
+};
+
+struct nfs3_diropok {
+ struct nfs_fh * fh;
+ struct nfs_fattr * fattr;
+};
+
+struct nfs3_readres {
+ struct nfs_fattr * fattr;
+ unsigned int count;
+};
+
+struct nfs3_readlinkres {
+ char ** string;
+ unsigned int * lenp;
+ unsigned int maxlen;
+ void * buffer;
+};
+
+struct nfs3_readdirres {
+ void * buffer;
+ unsigned int bufsiz;
+};
+
+/*
+ * The following are for NFSv3
+ */
+struct nfs3_fh {
+ __u32 size;
+ __u8 data[NFS3_FHSIZE]
+};
+
+struct nfs3_wcc_attr {
+ __u64 size;
+ struct nfs_time mtime;
+ struct nfs_time ctime;
+};
+
+#endif /* NFS_NEED_XDR_TYPES */
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/nfs_fs.h b/pfinet/linux-src/include/linux/nfs_fs.h
new file mode 100644
index 00000000..af961506
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nfs_fs.h
@@ -0,0 +1,284 @@
+/*
+ * linux/include/linux/nfs_fs.h
+ *
+ * Copyright (C) 1992 Rick Sladkey
+ *
+ * OS-specific nfs filesystem definitions and declarations
+ */
+
+#ifndef _LINUX_NFS_FS_H
+#define _LINUX_NFS_FS_H
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/in.h>
+
+#include <linux/sunrpc/sched.h>
+#include <linux/nfs.h>
+#include <linux/nfs_mount.h>
+
+/*
+ * Enable debugging support for nfs client.
+ * Requires RPC_DEBUG.
+ */
+#ifdef RPC_DEBUG
+# define NFS_DEBUG
+#endif
+
+/*
+ * NFS_MAX_DIRCACHE controls the number of simultaneously cached
+ * directory chunks. Each chunk holds the list of nfs_entry's returned
+ * in a single readdir call in a memory region of size PAGE_SIZE.
+ *
+ * Note that at most server->rsize bytes of the cache memory are used.
+ */
+#define NFS_MAX_DIRCACHE 16
+
+#define NFS_MAX_FILE_IO_BUFFER_SIZE 16384
+#define NFS_DEF_FILE_IO_BUFFER_SIZE 4096
+
+/*
+ * The upper limit on timeouts for the exponential backoff algorithm.
+ */
+#define NFS_MAX_RPC_TIMEOUT (6*HZ)
+
+/*
+ * Size of the lookup cache in units of number of entries cached.
+ * It is better not to make this too large although the optimum
+ * depends on a usage and environment.
+ */
+#define NFS_LOOKUP_CACHE_SIZE 64
+
+/*
+ * superblock magic number for NFS
+ */
+#define NFS_SUPER_MAGIC 0x6969
+
+#define NFS_FH(dentry) ((struct nfs_fh *) ((dentry)->d_fsdata))
+#define NFS_DSERVER(dentry) (&(dentry)->d_sb->u.nfs_sb.s_server)
+#define NFS_SERVER(inode) (&(inode)->i_sb->u.nfs_sb.s_server)
+#define NFS_CLIENT(inode) (NFS_SERVER(inode)->client)
+#define NFS_ADDR(inode) (RPC_PEERADDR(NFS_CLIENT(inode)))
+#define NFS_CONGESTED(inode) (RPC_CONGESTED(NFS_CLIENT(inode)))
+
+#define NFS_READTIME(inode) ((inode)->u.nfs_i.read_cache_jiffies)
+#define NFS_OLDMTIME(inode) ((inode)->u.nfs_i.read_cache_mtime)
+#define NFS_CACHEINV(inode) \
+do { \
+ NFS_READTIME(inode) = jiffies - 1000000; \
+ NFS_OLDMTIME(inode) = 0; \
+} while (0)
+#define NFS_ATTRTIMEO(inode) ((inode)->u.nfs_i.attrtimeo)
+#define NFS_MINATTRTIMEO(inode) \
+ (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmin \
+ : NFS_SERVER(inode)->acregmin)
+#define NFS_MAXATTRTIMEO(inode) \
+ (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmax \
+ : NFS_SERVER(inode)->acregmax)
+
+#define NFS_FLAGS(inode) ((inode)->u.nfs_i.flags)
+#define NFS_REVALIDATING(inode) (NFS_FLAGS(inode) & NFS_INO_REVALIDATE)
+#define NFS_WRITEBACK(inode) ((inode)->u.nfs_i.writeback)
+
+/*
+ * These are the default flags for swap requests
+ */
+#define NFS_RPC_SWAPFLAGS (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS)
+
+/* Flags in the RPC client structure */
+#define NFS_CLNTF_BUFSIZE 0x0001 /* readdir buffer in longwords */
+
+#ifdef __KERNEL__
+
+/*
+ * This struct describes a file region to be written.
+ * It's kind of a pity we have to keep all these lists ourselves, rather
+ * than sticking an extra pointer into struct page.
+ */
+struct nfs_wreq {
+ struct rpc_listitem wb_list; /* linked list of req's */
+ struct rpc_task wb_task; /* RPC task */
+ struct file * wb_file; /* dentry referenced */
+ struct page * wb_page; /* page to be written */
+ struct wait_queue * wb_wait; /* wait for completion */
+ unsigned int wb_offset; /* offset within page */
+ unsigned int wb_bytes; /* dirty range */
+ unsigned int wb_count; /* user count */
+ int wb_status;
+ pid_t wb_pid; /* owner process */
+ unsigned short wb_flags; /* status flags */
+
+ struct nfs_writeargs wb_args; /* NFS RPC stuff */
+ struct nfs_fattr wb_fattr; /* file attributes */
+};
+
+#define WB_NEXT(req) ((struct nfs_wreq *) ((req)->wb_list.next))
+
+/*
+ * Various flags for wb_flags
+ */
+#define NFS_WRITE_CANCELLED 0x0004 /* has been cancelled */
+#define NFS_WRITE_UNCOMMITTED 0x0008 /* written but uncommitted (NFSv3) */
+#define NFS_WRITE_INVALIDATE 0x0010 /* invalidate after write */
+#define NFS_WRITE_INPROGRESS 0x0100 /* RPC call in progress */
+#define NFS_WRITE_COMPLETE 0x0200 /* RPC call completed */
+
+#define WB_CANCELLED(req) ((req)->wb_flags & NFS_WRITE_CANCELLED)
+#define WB_UNCOMMITTED(req) ((req)->wb_flags & NFS_WRITE_UNCOMMITTED)
+#define WB_INVALIDATE(req) ((req)->wb_flags & NFS_WRITE_INVALIDATE)
+#define WB_INPROGRESS(req) ((req)->wb_flags & NFS_WRITE_INPROGRESS)
+#define WB_COMPLETE(req) ((req)->wb_flags & NFS_WRITE_COMPLETE)
+
+/*
+ * linux/fs/nfs/proc.c
+ */
+extern int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+ struct nfs_fattr *fattr);
+extern int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
+ struct nfs_sattr *sattr, struct nfs_fattr *fattr);
+extern int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir,
+ const char *name, struct nfs_fh *fhandle,
+ struct nfs_fattr *fattr);
+extern int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
+ void **p0, char **string, unsigned int *len,
+ unsigned int maxlen);
+extern int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
+ int swap, unsigned long offset, unsigned int count,
+ void *buffer, struct nfs_fattr *fattr);
+extern int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
+ int swap, unsigned long offset, unsigned int count,
+ const void *buffer, struct nfs_fattr *fattr);
+extern int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
+ const char *name, struct nfs_sattr *sattr,
+ struct nfs_fh *fhandle, struct nfs_fattr *fattr);
+extern int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir,
+ const char *name);
+extern int nfs_proc_rename(struct nfs_server *server,
+ struct nfs_fh *old_dir, const char *old_name,
+ struct nfs_fh *new_dir, const char *new_name);
+extern int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
+ struct nfs_fh *dir, const char *name);
+extern int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
+ const char *name, const char *path,
+ struct nfs_sattr *sattr);
+extern int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
+ const char *name, struct nfs_sattr *sattr,
+ struct nfs_fh *fhandle, struct nfs_fattr *fattr);
+extern int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir,
+ const char *name);
+extern int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
+ u32 cookie, unsigned int size, __u32 *entry);
+extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
+ struct nfs_fsinfo *res);
+
+
+/*
+ * linux/fs/nfs/inode.c
+ */
+extern struct super_block *nfs_read_super(struct super_block *, void *, int);
+extern int init_nfs_fs(void);
+extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
+ struct nfs_fattr *);
+extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
+extern int nfs_revalidate(struct dentry *);
+extern int nfs_open(struct inode *, struct file *);
+extern int nfs_release(struct inode *, struct file *);
+extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *);
+
+/*
+ * linux/fs/nfs/file.c
+ */
+extern struct inode_operations nfs_file_inode_operations;
+
+/*
+ * linux/fs/nfs/dir.c
+ */
+extern struct inode_operations nfs_dir_inode_operations;
+extern struct dentry_operations nfs_dentry_operations;
+extern void nfs_free_dircache(void);
+extern void nfs_invalidate_dircache(struct inode *);
+extern void nfs_invalidate_dircache_sb(struct super_block *);
+
+/*
+ * linux/fs/nfs/symlink.c
+ */
+extern struct inode_operations nfs_symlink_inode_operations;
+
+/*
+ * linux/fs/nfs/locks.c
+ */
+extern int nfs_lock(struct file *, int, struct file_lock *);
+
+/*
+ * linux/fs/nfs/write.c
+ */
+extern int nfs_writepage(struct file *, struct page *);
+extern int nfs_check_failed_request(struct inode *);
+
+/*
+ * Try to write back everything synchronously (but check the
+ * return value!)
+ */
+extern int nfs_wb_all(struct inode *);
+extern int nfs_wb_page(struct inode *, struct page *);
+extern int nfs_wb_file(struct inode *, struct file *);
+
+/*
+ * Invalidate write-backs, possibly trying to write them
+ * back first..
+ */
+extern void nfs_inval(struct inode *);
+extern int nfs_updatepage(struct file *, struct page *, unsigned long, unsigned int, int);
+
+/*
+ * linux/fs/nfs/read.c
+ */
+extern int nfs_readpage(struct file *, struct page *);
+
+/*
+ * linux/fs/mount_clnt.c
+ * (Used only by nfsroot module)
+ */
+extern int nfs_mount(struct sockaddr_in *, char *, struct nfs_fh *);
+
+/*
+ * inline functions
+ */
+static inline int
+nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+ if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
+ return 0;
+ return _nfs_revalidate_inode(server, dentry);
+}
+
+/* NFS root */
+
+extern int nfs_root_mount(struct super_block *sb);
+
+#endif /* __KERNEL__ */
+
+/*
+ * NFS debug flags
+ */
+#define NFSDBG_VFS 0x0001
+#define NFSDBG_DIRCACHE 0x0002
+#define NFSDBG_LOOKUPCACHE 0x0004
+#define NFSDBG_PAGECACHE 0x0008
+#define NFSDBG_PROC 0x0010
+#define NFSDBG_XDR 0x0020
+#define NFSDBG_FILE 0x0040
+#define NFSDBG_ROOT 0x0080
+#define NFSDBG_ALL 0xFFFF
+
+#ifdef __KERNEL__
+# undef ifdebug
+# ifdef NFS_DEBUG
+# define ifdebug(fac) if (nfs_debug & NFSDBG_##fac)
+# else
+# define ifdebug(fac) if (0)
+# endif
+#endif /* __KERNEL */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/nfs_fs_i.h b/pfinet/linux-src/include/linux/nfs_fs_i.h
new file mode 100644
index 00000000..885f21f0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nfs_fs_i.h
@@ -0,0 +1,71 @@
+#ifndef _NFS_FS_I
+#define _NFS_FS_I
+
+#include <linux/nfs.h>
+#include <linux/pipe_fs_i.h>
+
+/*
+ * nfs fs inode data in memory
+ */
+struct nfs_inode_info {
+ /*
+ * This is a place holder so named pipes on NFS filesystems
+ * work (more or less correctly). This must be first in the
+ * struct because the data is really accessed via inode->u.pipe_i.
+ */
+ struct pipe_inode_info pipeinfo;
+
+ /*
+ * Various flags
+ */
+ unsigned short flags;
+
+ /*
+ * read_cache_jiffies is when we started read-caching this inode,
+ * and read_cache_mtime is the mtime of the inode at that time.
+ * attrtimeo is for how long the cached information is assumed
+ * to be valid. A successful attribute revalidation doubles
+ * attrtimeo (up to acregmax/acdirmax), a failure resets it to
+ * acregmin/acdirmin.
+ *
+ * We need to revalidate the cached attrs for this inode if
+ *
+ * jiffies - read_cache_jiffies > attrtimeo
+ *
+ * and invalidate any cached data/flush out any dirty pages if
+ * we find that
+ *
+ * mtime != read_cache_mtime
+ */
+ unsigned long read_cache_jiffies;
+ unsigned long read_cache_mtime;
+ unsigned long attrtimeo;
+
+ /*
+ * This is the list of dirty unwritten pages.
+ * NFSv3 will want to add a list for written but uncommitted
+ * pages.
+ */
+ struct nfs_wreq * writeback;
+};
+
+/*
+ * Legal inode flag values
+ */
+#define NFS_INO_REVALIDATE 0x0001 /* revalidating attrs */
+#define NFS_IS_SNAPSHOT 0x0010 /* a snapshot file */
+
+/*
+ * NFS lock info
+ */
+struct nfs_lock_info {
+ u32 state;
+ u32 flags;
+};
+
+/*
+ * Lock flag values
+ */
+#define NFS_LCK_GRANTED 0x0001 /* lock has been granted */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/nfs_fs_sb.h b/pfinet/linux-src/include/linux/nfs_fs_sb.h
new file mode 100644
index 00000000..343455ec
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nfs_fs_sb.h
@@ -0,0 +1,31 @@
+#ifndef _NFS_FS_SB
+#define _NFS_FS_SB
+
+#include <linux/nfs.h>
+#include <linux/in.h>
+
+/*
+ * NFS client parameters stored in the superblock.
+ */
+struct nfs_server {
+ struct rpc_clnt * client; /* RPC client handle */
+ int flags; /* various flags */
+ int rsize; /* read size */
+ int wsize; /* write size */
+ unsigned int bsize; /* server block size */
+ unsigned int acregmin; /* attr cache timeouts */
+ unsigned int acregmax;
+ unsigned int acdirmin;
+ unsigned int acdirmax;
+ char * hostname; /* remote hostname */
+};
+
+/*
+ * nfs super-block data in memory
+ */
+struct nfs_sb_info {
+ struct nfs_server s_server;
+ struct nfs_fh s_root;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/nfs_mount.h b/pfinet/linux-src/include/linux/nfs_mount.h
new file mode 100644
index 00000000..60493b15
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nfs_mount.h
@@ -0,0 +1,53 @@
+#ifndef _LINUX_NFS_MOUNT_H
+#define _LINUX_NFS_MOUNT_H
+
+/*
+ * linux/include/linux/nfs_mount.h
+ *
+ * Copyright (C) 1992 Rick Sladkey
+ *
+ * structure passed from user-space to kernel-space during an nfs mount
+ */
+
+/*
+ * WARNING! Do not delete or change the order of these fields. If
+ * a new field is required then add it to the end. The version field
+ * tracks which fields are present. This will ensure some measure of
+ * mount-to-kernel version compatibility. Some of these aren't used yet
+ * but here they are anyway.
+ */
+#define NFS_MOUNT_VERSION 3
+
+struct nfs_mount_data {
+ int version; /* 1 */
+ int fd; /* 1 */
+ struct nfs_fh root; /* 1 */
+ int flags; /* 1 */
+ int rsize; /* 1 */
+ int wsize; /* 1 */
+ int timeo; /* 1 */
+ int retrans; /* 1 */
+ int acregmin; /* 1 */
+ int acregmax; /* 1 */
+ int acdirmin; /* 1 */
+ int acdirmax; /* 1 */
+ struct sockaddr_in addr; /* 1 */
+ char hostname[256]; /* 1 */
+ int namlen; /* 2 */
+ unsigned int bsize; /* 3 */
+};
+
+/* bits in the flags field */
+
+#define NFS_MOUNT_SOFT 0x0001 /* 1 */
+#define NFS_MOUNT_INTR 0x0002 /* 1 */
+#define NFS_MOUNT_SECURE 0x0004 /* 1 */
+#define NFS_MOUNT_POSIX 0x0008 /* 1 */
+#define NFS_MOUNT_NOCTO 0x0010 /* 1 */
+#define NFS_MOUNT_NOAC 0x0020 /* 1 */
+#define NFS_MOUNT_TCP 0x0040 /* 2 */
+#define NFS_MOUNT_VER3 0x0080 /* 3 */
+#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
+#define NFS_MOUNT_NONLM 0x0200 /* 3 */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/nfsiod.h b/pfinet/linux-src/include/linux/nfsiod.h
new file mode 100644
index 00000000..fdd07a2d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nfsiod.h
@@ -0,0 +1,52 @@
+/*
+ * linux/include/linux/nfsiod.h
+ *
+ * Declarations for asynchronous NFS RPC calls.
+ *
+ */
+
+#ifndef _LINUX_NFSIOD_H
+#define _LINUX_NFSIOD_H
+
+#include <linux/rpcsock.h>
+#include <linux/nfs_fs.h>
+
+#ifdef __KERNEL__
+
+/*
+ * This is the callback handler for nfsiod requests.
+ * Note that the callback procedure must NOT sleep.
+ */
+struct nfsiod_req;
+typedef int (*nfsiod_callback_t)(int result, struct nfsiod_req *);
+
+/*
+ * This is the nfsiod request struct.
+ */
+struct nfsiod_req {
+ struct nfsiod_req * rq_next;
+ struct nfsiod_req * rq_prev;
+ struct wait_queue * rq_wait;
+ struct rpc_ioreq rq_rpcreq;
+ nfsiod_callback_t rq_callback;
+ struct nfs_server * rq_server;
+ struct inode * rq_inode;
+ struct page * rq_page;
+
+ /* user creds */
+ uid_t rq_fsuid;
+ gid_t rq_fsgid;
+ int rq_groups[NGROUPS];
+
+ /* retry handling */
+ int rq_retries;
+};
+
+struct nfsiod_req * nfsiod_reserve(struct nfs_server *);
+void nfsiod_release(struct nfsiod_req *);
+void nfsiod_enqueue(struct nfsiod_req *);
+int nfsiod(void);
+
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_NFSIOD_H */
diff --git a/pfinet/linux-src/include/linux/nls.h b/pfinet/linux-src/include/linux/nls.h
new file mode 100644
index 00000000..efcd5892
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nls.h
@@ -0,0 +1,56 @@
+struct nls_unicode {
+ unsigned char uni1;
+ unsigned char uni2;
+};
+
+struct nls_table {
+ char *charset;
+ unsigned char **page_uni2charset;
+ struct nls_unicode *charset2uni;
+
+ void (*inc_use_count) (void);
+ void (*dec_use_count) (void);
+ struct nls_table *next;
+};
+
+/* nls.c */
+extern int init_nls(void);
+extern int register_nls(struct nls_table *);
+extern int unregister_nls(struct nls_table *);
+extern struct nls_table *find_nls(char *);
+extern struct nls_table *load_nls(char *);
+extern void unload_nls(struct nls_table *);
+extern struct nls_table *load_nls_default(void);
+
+extern int utf8_mbtowc(__u16 *, const __u8 *, int);
+extern int utf8_mbstowcs(__u16 *, const __u8 *, int);
+extern int utf8_wctomb(__u8 *, __u16, int);
+extern int utf8_wcstombs(__u8 *, const __u16 *, int);
+
+extern int init_nls_iso8859_1(void);
+extern int init_nls_iso8859_2(void);
+extern int init_nls_iso8859_3(void);
+extern int init_nls_iso8859_4(void);
+extern int init_nls_iso8859_5(void);
+extern int init_nls_iso8859_6(void);
+extern int init_nls_iso8859_7(void);
+extern int init_nls_iso8859_8(void);
+extern int init_nls_iso8859_9(void);
+extern int init_nls_iso8859_15(void);
+extern int init_nls_cp437(void);
+extern int init_nls_cp737(void);
+extern int init_nls_cp775(void);
+extern int init_nls_cp850(void);
+extern int init_nls_cp852(void);
+extern int init_nls_cp855(void);
+extern int init_nls_cp857(void);
+extern int init_nls_cp860(void);
+extern int init_nls_cp861(void);
+extern int init_nls_cp862(void);
+extern int init_nls_cp863(void);
+extern int init_nls_cp864(void);
+extern int init_nls_cp865(void);
+extern int init_nls_cp866(void);
+extern int init_nls_cp869(void);
+extern int init_nls_cp874(void);
+extern int init_nls_koi8_r(void);
diff --git a/pfinet/linux-src/include/linux/notifier.h b/pfinet/linux-src/include/linux/notifier.h
new file mode 100644
index 00000000..42faceaa
--- /dev/null
+++ b/pfinet/linux-src/include/linux/notifier.h
@@ -0,0 +1,115 @@
+/*
+ * Routines to manage notifier chains for passing status changes to any
+ * interested routines. We need this instead of hard coded call lists so
+ * that modules can poke their nose into the innards. The network devices
+ * needed them so here they are for the rest of you.
+ *
+ * Alan Cox <Alan.Cox@linux.org>
+ */
+
+#ifndef _LINUX_NOTIFIER_H
+#define _LINUX_NOTIFIER_H
+#include <linux/errno.h>
+
+struct notifier_block
+{
+ int (*notifier_call)(struct notifier_block *self, unsigned long, void *);
+ struct notifier_block *next;
+ int priority;
+};
+
+
+#ifdef __KERNEL__
+
+#define NOTIFY_DONE 0x0000 /* Don't care */
+#define NOTIFY_OK 0x0001 /* Suits me */
+#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
+#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */
+
+extern __inline__ int notifier_chain_register(struct notifier_block **list, struct notifier_block *n)
+{
+ while(*list)
+ {
+ if(n->priority > (*list)->priority)
+ break;
+ list= &((*list)->next);
+ }
+ n->next = *list;
+ *list=n;
+ return 0;
+}
+
+/*
+ * Warning to any non GPL module writers out there.. these functions are
+ * GPL'd
+ */
+
+extern __inline__ int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n)
+{
+ while((*nl)!=NULL)
+ {
+ if((*nl)==n)
+ {
+ *nl=n->next;
+ return 0;
+ }
+ nl=&((*nl)->next);
+ }
+ return -ENOENT;
+}
+
+/*
+ * This is one of these things that is generally shorter inline
+ */
+
+extern __inline__ int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
+{
+ int ret=NOTIFY_DONE;
+ struct notifier_block *nb = *n;
+ while(nb)
+ {
+ ret=nb->notifier_call(nb,val,v);
+ if(ret&NOTIFY_STOP_MASK)
+ return ret;
+ nb=nb->next;
+ }
+ return ret;
+}
+
+
+/*
+ * Declared notifiers so far. I can imagine quite a few more chains
+ * over time (eg laptop power reset chains, reboot chain (to clean
+ * device units up), device [un]mount chain, module load/unload chain,
+ * low memory chain, screenblank chain (for plug in modular screenblankers)
+ * VC switch chains (for loadable kernel svgalib VC switch helpers) etc...
+ */
+
+/* netdevice notifier chain */
+#define NETDEV_UP 0x0001 /* For now you can't veto a device up/down */
+#define NETDEV_DOWN 0x0002
+#define NETDEV_REBOOT 0x0003 /* Tell a protocol stack a network interface
+ detected a hardware crash and restarted
+ - we can use this eg to kick tcp sessions
+ once done */
+#define NETDEV_CHANGE 0x0004 /* Notify device state change */
+#define NETDEV_REGISTER 0x0005
+#define NETDEV_UNREGISTER 0x0006
+#define NETDEV_CHANGEMTU 0x0007
+#define NETDEV_CHANGEADDR 0x0008
+#define NETDEV_GOING_DOWN 0x0009
+#define NETDEV_CHANGENAME 0x000A
+
+#define SYS_DOWN 0x0001 /* Notify of system down */
+#define SYS_RESTART SYS_DOWN
+#define SYS_HALT 0x0002 /* Notify of system halt */
+#define SYS_POWER_OFF 0x0003 /* Notify of system power off */
+
+/*
+ * Publically visible notifier objects
+ */
+
+extern struct notifier_block *boot_notifier_list;
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/ntfs_fs.h b/pfinet/linux-src/include/linux/ntfs_fs.h
new file mode 100644
index 00000000..acbfc293
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ntfs_fs.h
@@ -0,0 +1,7 @@
+#ifndef _LINUX_NTFS_FS_H
+#define _LINUX_NTFS_FS_H
+
+int init_ntfs_fs(void);
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/ntfs_fs_i.h b/pfinet/linux-src/include/linux/ntfs_fs_i.h
new file mode 100644
index 00000000..cab27748
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ntfs_fs_i.h
@@ -0,0 +1,83 @@
+#ifndef _LINUX_NTFS_FS_I_H
+#define _LINUX_NTFS_FS_I_H
+
+/* Forward declarations, to keep number of mutual includes low */
+struct ntfs_attribute;
+struct ntfs_sb_info;
+
+/* Duplicate definitions from ntfs/ntfstypes.h */
+#ifndef NTFS_INTEGRAL_TYPES
+#define NTFS_INTEGRAL_TYPES
+typedef u8 ntfs_u8;
+typedef u16 ntfs_u16;
+typedef u32 ntfs_u32;
+typedef u64 ntfs_u64;
+typedef s8 ntfs_s8;
+typedef s16 ntfs_s16;
+typedef s32 ntfs_s32;
+typedef s64 ntfs_s64;
+#endif
+
+#ifndef NTMODE_T
+#define NTMODE_T
+typedef __kernel_mode_t ntmode_t;
+#endif
+#ifndef NTFS_UID_T
+#define NTFS_UID_T
+typedef __kernel_uid_t ntfs_uid_t;
+#endif
+#ifndef NTFS_GID_T
+#define NTFS_GID_T
+typedef __kernel_gid_t ntfs_gid_t;
+#endif
+#ifndef NTFS_SIZE_T
+#define NTFS_SIZE_T
+typedef __kernel_size_t ntfs_size_t;
+#endif
+#ifndef NTFS_TIME_T
+#define NTFS_TIME_T
+typedef __kernel_time_t ntfs_time_t;
+#endif
+
+/* unicode character type */
+#ifndef NTFS_WCHAR_T
+#define NTFS_WCHAR_T
+typedef unsigned short ntfs_wchar_t;
+#endif
+/* file offset */
+#ifndef NTFS_OFFSET_T
+#define NTFS_OFFSET_T
+typedef unsigned long long ntfs_offset_t;
+#endif
+/* UTC */
+#ifndef NTFS_TIME64_T
+#define NTFS_TIME64_T
+typedef unsigned long long ntfs_time64_t;
+#endif
+/* This is really unsigned long long. So we support only volumes up to 2 TB */
+#ifndef NTFS_CLUSTER_T
+#define NTFS_CLUSTER_T
+typedef unsigned int ntfs_cluster_t;
+#endif
+
+/* Definition of NTFS in-memory inode structure */
+struct ntfs_inode_info{
+ struct ntfs_sb_info *vol;
+ int i_number; /* should be really 48 bits */
+ unsigned sequence_number;
+ unsigned char* attr; /* array of the attributes */
+ int attr_count; /* size of attrs[] */
+ struct ntfs_attribute *attrs;
+ int record_count; /* size of records[] */
+ /* array of the record numbers of the MFT
+ whose attributes have been inserted in the inode */
+ int *records;
+ union{
+ struct{
+ int recordsize;
+ int clusters_per_record;
+ }index;
+ } u;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/ntfs_fs_sb.h b/pfinet/linux-src/include/linux/ntfs_fs_sb.h
new file mode 100644
index 00000000..898ef710
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ntfs_fs_sb.h
@@ -0,0 +1,44 @@
+#ifndef _LINUX_NTFS_FS_SB_H
+#define _LINUX_NTFS_FS_SB_H
+
+struct ntfs_sb_info{
+ /* Configuration provided by user at mount time */
+ ntfs_uid_t uid;
+ ntfs_gid_t gid;
+ ntmode_t umask;
+ unsigned int nct;
+ void *nls_map;
+ unsigned int ngt;
+ /* Configuration provided by user with ntfstools */
+ ntfs_size_t partition_bias; /* for access to underlying device */
+ /* Attribute definitions */
+ ntfs_u32 at_standard_information;
+ ntfs_u32 at_attribute_list;
+ ntfs_u32 at_file_name;
+ ntfs_u32 at_security_descriptor;
+ ntfs_u32 at_data;
+ ntfs_u32 at_index_root;
+ ntfs_u32 at_index_allocation;
+ ntfs_u32 at_bitmap;
+ ntfs_u32 at_symlink; /* aka SYMBOLIC_LINK or REPARSE_POINT */
+ /* Data read from the boot file */
+ int blocksize;
+ int clusterfactor;
+ int clustersize;
+ int mft_recordsize;
+ int mft_clusters_per_record;
+ int index_recordsize;
+ int index_clusters_per_record;
+ int mft_cluster;
+ /* data read from special files */
+ unsigned char *mft;
+ unsigned short *upcase;
+ unsigned int upcase_length;
+ /* inodes we always hold onto */
+ struct ntfs_inode_info *mft_ino;
+ struct ntfs_inode_info *mftmirr;
+ struct ntfs_inode_info *bitmap;
+ struct super_block *sb;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/nubus.h b/pfinet/linux-src/include/linux/nubus.h
new file mode 100644
index 00000000..c09b95a9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nubus.h
@@ -0,0 +1,96 @@
+
+struct nubus_slot
+{
+ int slot_flags;
+#define NUBUS_DEVICE_PRESENT 1
+#define NUBUS_DEVICE_ACTIVE 2
+#define NUBUS_DEVICE_IRQ 4
+ __u32 slot_directory;
+ __u32 slot_dlength;
+ __u32 slot_crc;
+ __u8 slot_rev;
+ __u8 slot_format;
+ __u8 slot_lanes;
+ /*
+ * Stuff we pulled from the directory
+ */
+ __u32 slot_dirbase;
+ __u32 slot_thisdir;
+ char slot_vendor[64];
+ char slot_cardname[64];
+};
+
+struct nbnamevec
+{
+ char *name;
+ int id;
+};
+
+struct nubus_dir
+{
+ unsigned char *base;
+ int length;
+ int count;
+ int mask;
+};
+
+struct nubus_dirent
+{
+ unsigned char type;
+ int value; /* Actually 24bits used */
+ int mask;
+ int base; /* For dirptr function */
+};
+
+struct nubus_type
+{
+ __u16 category;
+ __u16 type;
+ __u16 DrHW;
+ __u16 DrSW;
+};
+
+#define NUBUS_CAT_BOARD 0x0001
+#define NUBUS_CAT_DISPLAY 0x0003
+#define NUBUS_CAT_NETWORK 0x0004
+#define NUBUS_CAT_COMMUNICATIONS 0x0006
+#define NUBUS_CAT_FONT 0x0009
+#define NUBUS_CAT_CPU 0x000A
+
+#define RES_ID_TYPE 0x0001
+#define RES_ID_NAME 0x0002
+#define RES_ID_BOARD_DIR 0x0001
+#define RES_ID_FLAGS 0x0007
+
+struct nubus_device_specifier
+{
+ int (*setup)(struct nubus_device_specifier *, int slot, struct nubus_type *);
+ struct nubus_device_specifier *next;
+};
+
+
+extern void register_nubus_device(struct nubus_device_specifier *nb);
+extern void unregister_nubus_device(struct nubus_device_specifier *nb);
+
+extern struct nubus_dir *nubus_openrootdir(int slot);
+extern struct nubus_dir *nubus_opensubdir(struct nubus_dirent *d);
+extern void nubus_closedir(struct nubus_dir *);
+extern struct nubus_dirent *nubus_readdir(struct nubus_dir *);
+extern unsigned char *nubus_dirptr(struct nubus_dirent *d);
+extern void nubus_strncpy(int slot, void *to, unsigned char *p, int len);
+extern void nubus_memcpy(int slot, void *to, unsigned char *p, int len);
+extern void nubus_init(void);
+extern void nubus_sweep_video(void);
+extern int nubus_ethernet_addr(int slot, unsigned char *addr);
+
+extern __inline void *nubus_slot_addr(int slot)
+{
+ return (void *)(0xF0000000|(slot<<24));
+}
+
+extern int nubus_hwreg_present(volatile void *ptr);
+
+extern void nubus_init_via(void);
+extern int nubus_free_irq(int slot);
+extern int nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct pt_regs *));
+
diff --git a/pfinet/linux-src/include/linux/nvram.h b/pfinet/linux-src/include/linux/nvram.h
new file mode 100644
index 00000000..9e05db19
--- /dev/null
+++ b/pfinet/linux-src/include/linux/nvram.h
@@ -0,0 +1,18 @@
+#ifndef _LINUX_NVRAM_H
+#define _LINUX_NVRAM_H
+
+#include <linux/ioctl.h>
+
+/* /dev/nvram ioctls */
+#define NVRAM_INIT _IO('p', 0x40) /* initialize NVRAM and set checksum */
+#define NVRAM_SETCKS _IO('p', 0x41) /* recalculate checksum */
+
+#ifdef __KERNEL__
+extern unsigned char nvram_read_byte( int i );
+extern void nvram_write_byte( unsigned char c, int i );
+extern int nvram_check_checksum( void );
+extern void nvram_set_checksum( void );
+extern int nvram_init( void );
+#endif
+
+#endif /* _LINUX_NVRAM_H */
diff --git a/pfinet/linux-src/include/linux/openpic.h b/pfinet/linux-src/include/linux/openpic.h
new file mode 100644
index 00000000..9cf18c5d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/openpic.h
@@ -0,0 +1,363 @@
+/*
+ * linux/openpic.h -- OpenPIC definitions
+ *
+ * Copyright (C) 1997 Geert Uytterhoeven
+ *
+ * This file is based on the following documentation:
+ *
+ * The Open Programmable Interrupt Controller (PIC)
+ * Register Interface Specification Revision 1.2
+ *
+ * Issue Date: October 1995
+ *
+ * Issued jointly by Advanced Micro Devices and Cyrix Corporation
+ *
+ * AMD is a registered trademark of Advanced Micro Devices, Inc.
+ * Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
+ * All Rights Reserved.
+ *
+ * To receive a copy of this documentation, send an email to openpic@amd.com.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _LINUX_OPENPIC_H
+#define _LINUX_OPENPIC_H
+
+#if !defined(__powerpc__) && !defined(__i386__)
+#error Unsupported OpenPIC platform
+#endif
+
+
+#ifdef __KERNEL__
+
+ /*
+ * OpenPIC supports up to 2048 interrupt sources and up to 32 processors
+ */
+
+#define OPENPIC_MAX_SOURCES 2048
+#define OPENPIC_MAX_PROCESSORS 32
+
+#define OPENPIC_NUM_TIMERS 4
+#define OPENPIC_NUM_IPI 4
+#define OPENPIC_NUM_PRI 16
+#define OPENPIC_NUM_VECTORS 256
+
+
+ /*
+ * Vector numbers
+ */
+
+#define OPENPIC_VEC_SOURCE 0x10 /* and up */
+#define OPENPIC_VEC_TIMER 0x40 /* and up */
+#define OPENPIC_VEC_IPI 0x50 /* and up */
+#define OPENPIC_VEC_SPURIOUS 99
+
+
+ /*
+ * OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
+ */
+
+typedef struct _OpenPIC_Reg {
+ u_int Reg; /* Little endian! */
+ char Pad[0xc];
+} OpenPIC_Reg;
+
+
+ /*
+ * Per Processor Registers
+ */
+
+typedef struct _OpenPIC_Processor {
+ /*
+ * Private Shadow Registers (for SLiC backwards compatibility)
+ */
+ u_int IPI0_Dispatch_Shadow; /* Write Only */
+ char Pad1[0x4];
+ u_int IPI0_Vector_Priority_Shadow; /* Read/Write */
+ char Pad2[0x34];
+ /*
+ * Interprocessor Interrupt Command Ports
+ */
+ OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI]; /* Write Only */
+ /*
+ * Current Task Priority Register
+ */
+ OpenPIC_Reg _Current_Task_Priority; /* Read/Write */
+#ifndef __powerpc__
+ /*
+ * Who Am I Register
+ */
+ OpenPIC_Reg _Who_Am_I; /* Read Only */
+#else
+ char Pad3[0x10];
+#endif
+#ifndef __i386__
+ /*
+ * Interrupt Acknowledge Register
+ */
+ OpenPIC_Reg _Interrupt_Acknowledge; /* Read Only */
+#else
+ char Pad4[0x10];
+#endif
+ /*
+ * End of Interrupt (EOI) Register
+ */
+ OpenPIC_Reg _EOI; /* Read/Write */
+ char Pad5[0xf40];
+} OpenPIC_Processor;
+
+
+ /*
+ * Timer Registers
+ */
+
+typedef struct _OpenPIC_Timer {
+ OpenPIC_Reg _Current_Count; /* Read Only */
+ OpenPIC_Reg _Base_Count; /* Read/Write */
+ OpenPIC_Reg _Vector_Priority; /* Read/Write */
+ OpenPIC_Reg _Destination; /* Read/Write */
+} OpenPIC_Timer;
+
+
+ /*
+ * Global Registers
+ */
+
+typedef struct _OpenPIC_Global {
+ /*
+ * Feature Reporting Registers
+ */
+ OpenPIC_Reg _Feature_Reporting0; /* Read Only */
+ OpenPIC_Reg _Feature_Reporting1; /* Future Expansion */
+ /*
+ * Global Configuration Registers
+ */
+ OpenPIC_Reg _Global_Configuration0; /* Read/Write */
+ OpenPIC_Reg _Global_Configuration1; /* Future Expansion */
+ /*
+ * Vendor Specific Registers
+ */
+ OpenPIC_Reg _Vendor_Specific[4];
+ /*
+ * Vendor Identification Register
+ */
+ OpenPIC_Reg _Vendor_Identification; /* Read Only */
+ /*
+ * Processor Initialization Register
+ */
+ OpenPIC_Reg _Processor_Initialization; /* Read/Write */
+ /*
+ * IPI Vector/Priority Registers
+ */
+ OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */
+ /*
+ * Spurious Vector Register
+ */
+ OpenPIC_Reg _Spurious_Vector; /* Read/Write */
+ /*
+ * Global Timer Registers
+ */
+ OpenPIC_Reg _Timer_Frequency; /* Read/Write */
+ OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
+ char Pad1[0xee00];
+} OpenPIC_Global;
+
+
+ /*
+ * Interrupt Source Registers
+ */
+
+typedef struct _OpenPIC_Source {
+ OpenPIC_Reg _Vector_Priority; /* Read/Write */
+ OpenPIC_Reg _Destination; /* Read/Write */
+} OpenPIC_Source;
+
+
+ /*
+ * OpenPIC Register Map
+ */
+
+struct OpenPIC {
+#ifndef __powerpc__
+ /*
+ * Per Processor Registers --- Private Access
+ */
+ OpenPIC_Processor Private;
+#else
+ char Pad1[0x1000];
+#endif
+ /*
+ * Global Registers
+ */
+ OpenPIC_Global Global;
+ /*
+ * Interrupt Source Configuration Registers
+ */
+ OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
+ /*
+ * Per Processor Registers
+ */
+ OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
+};
+
+extern volatile struct OpenPIC *OpenPIC;
+extern u_int OpenPIC_NumInitSenses;
+extern u_char *OpenPIC_InitSenses;
+
+
+ /*
+ * Current Task Priority Register
+ */
+
+#define OPENPIC_CURRENT_TASK_PRIORITY_MASK 0x0000000f
+
+ /*
+ * Who Am I Register
+ */
+
+#define OPENPIC_WHO_AM_I_ID_MASK 0x0000001f
+
+ /*
+ * Feature Reporting Register 0
+ */
+
+#define OPENPIC_FEATURE_LAST_SOURCE_MASK 0x07ff0000
+#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT 16
+#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK 0x00001f00
+#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT 8
+#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff
+
+ /*
+ * Global Configuration Register 0
+ */
+
+#define OPENPIC_CONFIG_RESET 0x80000000
+#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE 0x20000000
+#define OPENPIC_CONFIG_BASE_MASK 0x000fffff
+
+ /*
+ * Vendor Identification Register
+ */
+
+#define OPENPIC_VENDOR_ID_STEPPING_MASK 0x00ff0000
+#define OPENPIC_VENDOR_ID_STEPPING_SHIFT 16
+#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
+#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT 8
+#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
+
+ /*
+ * Vector/Priority Registers
+ */
+
+#define OPENPIC_MASK 0x80000000
+#define OPENPIC_ACTIVITY 0x40000000 /* Read Only */
+#define OPENPIC_PRIORITY_MASK 0x000f0000
+#define OPENPIC_PRIORITY_SHIFT 16
+#define OPENPIC_VECTOR_MASK 0x000000ff
+
+
+ /*
+ * Interrupt Source Registers
+ */
+
+#define OPENPIC_SENSE_POLARITY 0x00800000 /* Undoc'd */
+#define OPENPIC_SENSE_LEVEL 0x00400000
+
+
+ /*
+ * Timer Registers
+ */
+
+#define OPENPIC_COUNT_MASK 0x7fffffff
+#define OPENPIC_TIMER_TOGGLE 0x80000000
+#define OPENPIC_TIMER_COUNT_INHIBIT 0x80000000
+
+
+ /*
+ * Aliases to make life simpler
+ */
+
+/* Per Processor Registers */
+#define IPI_Dispatch(i) _IPI_Dispatch[i].Reg
+#define Current_Task_Priority _Current_Task_Priority.Reg
+#ifndef __powerpc__
+#define Who_Am_I _Who_Am_I.Reg
+#endif
+#ifndef __i386__
+#define Interrupt_Acknowledge _Interrupt_Acknowledge.Reg
+#endif
+#define EOI _EOI.Reg
+
+/* Global Registers */
+#define Feature_Reporting0 _Feature_Reporting0.Reg
+#define Feature_Reporting1 _Feature_Reporting1.Reg
+#define Global_Configuration0 _Global_Configuration0.Reg
+#define Global_Configuration1 _Global_Configuration1.Reg
+#define Vendor_Specific(i) _Vendor_Specific[i].Reg
+#define Vendor_Identification _Vendor_Identification.Reg
+#define Processor_Initialization _Processor_Initialization.Reg
+#define IPI_Vector_Priority(i) _IPI_Vector_Priority[i].Reg
+#define Spurious_Vector _Spurious_Vector.Reg
+#define Timer_Frequency _Timer_Frequency.Reg
+
+/* Timer Registers */
+#define Current_Count _Current_Count.Reg
+#define Base_Count _Base_Count.Reg
+#define Vector_Priority _Vector_Priority.Reg
+#define Destination _Destination.Reg
+
+/* Interrupt Source Registers */
+#define Vector_Priority _Vector_Priority.Reg
+#define Destination _Destination.Reg
+
+ /*
+ * OpenPIC Operations
+ */
+
+/* Global Operations */
+extern void openpic_init(int);
+extern void openpic_reset(void);
+extern void openpic_enable_8259_pass_through(void);
+extern void openpic_disable_8259_pass_through(void);
+#ifndef __i386__
+extern u_int openpic_irq(u_int cpu);
+#endif
+#ifndef __powerpc__
+extern void openpic_eoi(void);
+extern u_int openpic_get_priority(void);
+extern void openpic_set_priority(u_int pri);
+#else
+extern void openpic_eoi(u_int cpu);
+extern u_int openpic_get_priority(u_int cpu);
+extern void openpic_set_priority(u_int cpu, u_int pri);
+#endif
+extern u_int openpic_get_spurious(void);
+extern void openpic_set_spurious(u_int vector);
+extern void openpic_init_processor(u_int cpumask);
+
+/* Interprocessor Interrupts */
+extern void openpic_initipi(u_int ipi, u_int pri, u_int vector);
+#ifndef __powerpc__
+extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
+#else
+extern void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask);
+#endif
+
+/* Timer Interrupts */
+extern void openpic_inittimer(u_int timer, u_int pri, u_int vector);
+extern void openpic_maptimer(u_int timer, u_int cpumask);
+
+/* Interrupt Sources */
+extern void openpic_enable_irq(u_int irq);
+extern void openpic_disable_irq(u_int irq);
+extern void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
+ int is_level);
+extern void openpic_mapirq(u_int irq, u_int cpumask);
+extern void openpic_set_sense(u_int irq, int sense);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_OPENPIC_H */
diff --git a/pfinet/linux-src/include/linux/pagemap.h b/pfinet/linux-src/include/linux/pagemap.h
new file mode 100644
index 00000000..3e1e89b4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/pagemap.h
@@ -0,0 +1,153 @@
+#ifndef _LINUX_PAGEMAP_H
+#define _LINUX_PAGEMAP_H
+
+#include <asm/system.h>
+
+/*
+ * Page-mapping primitive inline functions
+ *
+ * Copyright 1995 Linus Torvalds
+ */
+
+#include <linux/mm.h>
+#include <linux/fs.h>
+
+static inline unsigned long page_address(struct page * page)
+{
+ return PAGE_OFFSET + PAGE_SIZE * (page - mem_map);
+}
+
+/*
+ * The page cache can done in larger chunks than
+ * one page, because it allows for more efficient
+ * throughput (it can then be mapped into user
+ * space in smaller chunks for same flexibility).
+ *
+ * Or rather, it _will_ be done in larger chunks.
+ */
+#define PAGE_CACHE_SHIFT PAGE_SHIFT
+#define PAGE_CACHE_SIZE PAGE_SIZE
+#define PAGE_CACHE_MASK PAGE_MASK
+
+#define page_cache_alloc() __get_free_page(GFP_USER)
+#define page_cache_free(x) free_page(x)
+#define page_cache_release(x) __free_page(x)
+
+/*
+ * From a kernel address, get the "struct page *"
+ */
+#define page_cache_entry(x) (mem_map + MAP_NR(x))
+
+#define PAGE_HASH_BITS 12
+#define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS)
+
+extern unsigned long page_cache_size; /* # of pages currently in the hash table */
+extern struct page * page_hash_table[PAGE_HASH_SIZE];
+
+/*
+ * We use a power-of-two hash table to avoid a modulus,
+ * and get a reasonable hash by knowing roughly how the
+ * inode pointer and offsets are distributed (ie, we
+ * roughly know which bits are "significant")
+ */
+static inline unsigned long _page_hashfn(struct inode * inode, unsigned long offset)
+{
+#define i (((unsigned long) inode)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))
+#define o (offset >> PAGE_SHIFT)
+#define s(x) ((x)+((x)>>PAGE_HASH_BITS))
+ return s(i+o) & (PAGE_HASH_SIZE-1);
+#undef i
+#undef o
+#undef s
+}
+
+#define page_hash(inode,offset) (page_hash_table+_page_hashfn(inode,offset))
+
+static inline struct page * __find_page(struct inode * inode, unsigned long offset, struct page *page)
+{
+ goto inside;
+ for (;;) {
+ page = page->next_hash;
+inside:
+ if (!page)
+ goto not_found;
+ if (page->inode != inode)
+ continue;
+ if (page->offset == offset)
+ break;
+ }
+ /* Found the page. */
+ atomic_inc(&page->count);
+ set_bit(PG_referenced, &page->flags);
+not_found:
+ return page;
+}
+
+static inline struct page *find_page(struct inode * inode, unsigned long offset)
+{
+ return __find_page(inode, offset, *page_hash(inode, offset));
+}
+
+static inline void remove_page_from_hash_queue(struct page * page)
+{
+ if(page->pprev_hash) {
+ if(page->next_hash)
+ page->next_hash->pprev_hash = page->pprev_hash;
+ *page->pprev_hash = page->next_hash;
+ page->pprev_hash = NULL;
+ }
+ page_cache_size--;
+}
+
+static inline void __add_page_to_hash_queue(struct page * page, struct page **p)
+{
+ page_cache_size++;
+ if((page->next_hash = *p) != NULL)
+ (*p)->pprev_hash = &page->next_hash;
+ *p = page;
+ page->pprev_hash = p;
+}
+
+static inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long offset)
+{
+ __add_page_to_hash_queue(page, page_hash(inode,offset));
+}
+
+static inline void remove_page_from_inode_queue(struct page * page)
+{
+ struct inode * inode = page->inode;
+
+ page->inode = NULL;
+ inode->i_nrpages--;
+ if (inode->i_pages == page)
+ inode->i_pages = page->next;
+ if (page->next)
+ page->next->prev = page->prev;
+ if (page->prev)
+ page->prev->next = page->next;
+ page->next = NULL;
+ page->prev = NULL;
+}
+
+static inline void add_page_to_inode_queue(struct inode * inode, struct page * page)
+{
+ struct page **p = &inode->i_pages;
+
+ inode->i_nrpages++;
+ page->inode = inode;
+ page->prev = NULL;
+ if ((page->next = *p) != NULL)
+ page->next->prev = page;
+ *p = page;
+}
+
+extern void __wait_on_page(struct page *);
+static inline void wait_on_page(struct page * page)
+{
+ if (PageLocked(page))
+ __wait_on_page(page);
+}
+
+extern void update_vm_cache(struct inode *, unsigned long, const char *, int);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/param.h b/pfinet/linux-src/include/linux/param.h
new file mode 100644
index 00000000..092e92f6
--- /dev/null
+++ b/pfinet/linux-src/include/linux/param.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_PARAM_H
+#define _LINUX_PARAM_H
+
+#include <asm/param.h>
+
+#endif
diff --git a/pfinet/linux-src/include/linux/parport.h b/pfinet/linux-src/include/linux/parport.h
new file mode 100644
index 00000000..3adbc5ab
--- /dev/null
+++ b/pfinet/linux-src/include/linux/parport.h
@@ -0,0 +1,393 @@
+/* $Id: parport.h,v 1.1 1998/05/17 10:57:52 andrea Exp andrea $ */
+
+#ifndef _PARPORT_H_
+#define _PARPORT_H_
+
+/* Start off with user-visible constants */
+
+/* Maximum of 8 ports per machine */
+#define PARPORT_MAX 8
+
+/* Magic numbers */
+#define PARPORT_IRQ_NONE -1
+#define PARPORT_DMA_NONE -1
+#define PARPORT_IRQ_AUTO -2
+#define PARPORT_DMA_AUTO -2
+#define PARPORT_DISABLE -2
+#define PARPORT_IRQ_PROBEONLY -3
+
+#define PARPORT_CONTROL_STROBE 0x1
+#define PARPORT_CONTROL_AUTOFD 0x2
+#define PARPORT_CONTROL_INIT 0x4
+#define PARPORT_CONTROL_SELECT 0x8
+#define PARPORT_CONTROL_INTEN 0x10
+#define PARPORT_CONTROL_DIRECTION 0x20
+
+#define PARPORT_STATUS_ERROR 0x8
+#define PARPORT_STATUS_SELECT 0x10
+#define PARPORT_STATUS_PAPEROUT 0x20
+#define PARPORT_STATUS_ACK 0x40
+#define PARPORT_STATUS_BUSY 0x80
+
+/* Type classes for Plug-and-Play probe. */
+typedef enum {
+ PARPORT_CLASS_LEGACY = 0, /* Non-IEEE1284 device */
+ PARPORT_CLASS_PRINTER,
+ PARPORT_CLASS_MODEM,
+ PARPORT_CLASS_NET,
+ PARPORT_CLASS_HDC, /* Hard disk controller */
+ PARPORT_CLASS_PCMCIA,
+ PARPORT_CLASS_MEDIA, /* Multimedia device */
+ PARPORT_CLASS_FDC, /* Floppy disk controller */
+ PARPORT_CLASS_PORTS,
+ PARPORT_CLASS_SCANNER,
+ PARPORT_CLASS_DIGCAM,
+ PARPORT_CLASS_OTHER, /* Anything else */
+ PARPORT_CLASS_UNSPEC /* No CLS field in ID */
+} parport_device_class;
+
+/* The "modes" entry in parport is a bit field representing the following
+ * modes.
+ * Note that PARPORT_MODE_PCECPEPP is for the SMC EPP+ECP mode which is NOT
+ * 100% compatible with EPP.
+ */
+#define PARPORT_MODE_PCSPP 0x0001
+#define PARPORT_MODE_PCPS2 0x0002
+#define PARPORT_MODE_PCEPP 0x0004
+#define PARPORT_MODE_PCECP 0x0008
+#define PARPORT_MODE_PCECPEPP 0x0010
+#define PARPORT_MODE_PCECR 0x0020 /* ECR Register Exists */
+#define PARPORT_MODE_PCECPPS2 0x0040
+
+/* The rest is for the kernel only */
+#ifdef __KERNEL__
+
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/spinlock.h>
+#include <linux/proc_fs.h>
+#include <linux/config.h>
+
+#define PARPORT_NEED_GENERIC_OPS
+
+/* Define this later. */
+struct parport;
+
+struct pc_parport_state {
+ unsigned int ctr;
+ unsigned int ecr;
+};
+
+struct parport_state {
+ union {
+ struct pc_parport_state pc;
+ /* ARC has no state. */
+ /* AX uses same state information as PC */
+ void *misc;
+ } u;
+};
+
+struct parport_operations {
+ void (*write_data)(struct parport *, unsigned char);
+ unsigned char (*read_data)(struct parport *);
+ void (*write_control)(struct parport *, unsigned char);
+ unsigned char (*read_control)(struct parport *);
+ unsigned char (*frob_control)(struct parport *, unsigned char mask, unsigned char val);
+ void (*write_econtrol)(struct parport *, unsigned char);
+ unsigned char (*read_econtrol)(struct parport *);
+ unsigned char (*frob_econtrol)(struct parport *, unsigned char mask, unsigned char val);
+ void (*write_status)(struct parport *, unsigned char);
+ unsigned char (*read_status)(struct parport *);
+ void (*write_fifo)(struct parport *, unsigned char);
+ unsigned char (*read_fifo)(struct parport *);
+
+ void (*change_mode)(struct parport *, int);
+
+ void (*release_resources)(struct parport *);
+ int (*claim_resources)(struct parport *);
+
+ void (*epp_write_data)(struct parport *, unsigned char);
+ unsigned char (*epp_read_data)(struct parport *);
+ void (*epp_write_addr)(struct parport *, unsigned char);
+ unsigned char (*epp_read_addr)(struct parport *);
+ int (*epp_check_timeout)(struct parport *);
+ size_t (*epp_write_block)(struct parport *, void *, size_t);
+ size_t (*epp_read_block)(struct parport *, void *, size_t);
+
+ int (*ecp_write_block)(struct parport *, void *, size_t, void (*fn)(struct parport *, void *, size_t), void *);
+ int (*ecp_read_block)(struct parport *, void *, size_t, void (*fn)(struct parport *, void *, size_t), void *);
+
+ void (*init_state)(struct parport_state *);
+ void (*save_state)(struct parport *, struct parport_state *);
+ void (*restore_state)(struct parport *, struct parport_state *);
+
+ void (*enable_irq)(struct parport *);
+ void (*disable_irq)(struct parport *);
+ void (*interrupt)(int, void *, struct pt_regs *);
+
+ void (*inc_use_count)(void);
+ void (*dec_use_count)(void);
+ void (*fill_inode)(struct inode *inode, int fill);
+};
+
+struct parport_device_info {
+ parport_device_class class;
+ const char *class_name;
+ const char *mfr;
+ const char *model;
+ const char *cmdset;
+ const char *description;
+};
+
+/* Each device can have two callback functions:
+ * 1) a preemption function, called by the resource manager to request
+ * that the driver relinquish control of the port. The driver should
+ * return zero if it agrees to release the port, and nonzero if it
+ * refuses. Do not call parport_release() - the kernel will do this
+ * implicitly.
+ *
+ * 2) a wake-up function, called by the resource manager to tell drivers
+ * that the port is available to be claimed. If a driver wants to use
+ * the port, it should call parport_claim() here.
+ */
+
+/* A parallel port device */
+struct pardevice {
+ const char *name;
+ struct parport *port;
+ int (*preempt)(void *);
+ void (*wakeup)(void *);
+ void *private;
+ void (*irq_func)(int, void *, struct pt_regs *);
+ unsigned int flags;
+ struct pardevice *next;
+ struct pardevice *prev;
+ struct parport_state *state; /* saved status over preemption */
+ struct wait_queue *wait_q;
+ unsigned long int time;
+ unsigned long int timeslice;
+ unsigned int waiting;
+ struct pardevice *waitprev;
+ struct pardevice *waitnext;
+};
+
+/* Directory information for the /proc interface */
+struct parport_dir {
+ struct proc_dir_entry *entry; /* Directory /proc/parport/X */
+ struct proc_dir_entry *irq; /* .../irq */
+ struct proc_dir_entry *devices; /* .../devices */
+ struct proc_dir_entry *hardware; /* .../hardware */
+ struct proc_dir_entry *probe; /* .../autoprobe */
+ char name[4];
+};
+
+/* A parallel port */
+struct parport {
+ unsigned long base; /* base address */
+ unsigned int size; /* IO extent */
+ const char *name;
+ int irq; /* interrupt (or -1 for none) */
+ int dma;
+ unsigned int modes;
+
+ struct pardevice *devices;
+ struct pardevice *cad; /* port owner */
+
+ struct pardevice *waithead;
+ struct pardevice *waittail;
+
+ struct parport *next;
+ unsigned int flags;
+
+ struct parport_dir pdir;
+ struct parport_device_info probe_info;
+
+ struct parport_operations *ops;
+ void *private_data; /* for lowlevel driver */
+
+ int number; /* port index - the `n' in `parportn' */
+ spinlock_t pardevice_lock;
+ spinlock_t waitlist_lock;
+ rwlock_t cad_lock;
+};
+
+/* parport_register_port registers a new parallel port at the given address (if
+ * one does not already exist) and returns a pointer to it. This entails
+ * claiming the I/O region, IRQ and DMA.
+ * NULL is returned if initialisation fails.
+ */
+struct parport *parport_register_port(unsigned long base, int irq, int dma,
+ struct parport_operations *ops);
+
+/* Unregister a port. */
+extern void parport_unregister_port(struct parport *port);
+
+/* parport_in_use returns nonzero if there are devices attached to a port. */
+#define parport_in_use(x) ((x)->devices != NULL)
+
+/* Put a parallel port to sleep; release its hardware resources. Only possible
+ * if no devices are registered. */
+extern void parport_quiesce(struct parport *);
+
+/* parport_enumerate returns a pointer to the linked list of all the ports
+ * in this machine.
+ */
+struct parport *parport_enumerate(void);
+
+/* parport_register_device declares that a device is connected to a port, and
+ * tells the kernel all it needs to know.
+ * pf is the preemption function (may be NULL for no callback)
+ * kf is the wake-up function (may be NULL for no callback)
+ * irq_func is the interrupt handler (may be NULL for no interrupts)
+ * handle is a user pointer that gets handed to callback functions.
+ */
+struct pardevice *parport_register_device(struct parport *port,
+ const char *name,
+ int (*pf)(void *), void (*kf)(void *),
+ void (*irq_func)(int, void *, struct pt_regs *),
+ int flags, void *handle);
+
+/* parport_unregister unlinks a device from the chain. */
+extern void parport_unregister_device(struct pardevice *dev);
+
+/* parport_claim tries to gain ownership of the port for a particular driver.
+ * This may fail (return non-zero) if another driver is busy. If this
+ * driver has registered an interrupt handler, it will be enabled.
+ */
+extern int parport_claim(struct pardevice *dev);
+
+/* parport_claim_or_block is the same, but sleeps if the port cannot be
+ claimed. Return value is 1 if it slept, 0 normally and -errno on error. */
+extern int parport_claim_or_block(struct pardevice *dev);
+
+/* parport_release reverses a previous parport_claim. This can never fail,
+ * though the effects are undefined (except that they are bad) if you didn't
+ * previously own the port. Once you have released the port you should make
+ * sure that neither your code nor the hardware on the port tries to initiate
+ * any communication without first re-claiming the port.
+ * If you mess with the port state (enabling ECP for example) you should
+ * clean up before releasing the port.
+ */
+
+extern void parport_release(struct pardevice *dev);
+
+/* parport_yield relinquishes the port if it would be helpful to other
+ * drivers. The return value is the same as for parport_claim.
+ */
+extern __inline__ int parport_yield(struct pardevice *dev)
+{
+ unsigned long int timeslip = (jiffies - dev->time);
+ if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice))
+ return 0;
+ parport_release(dev);
+ return parport_claim(dev);
+}
+
+/* parport_yield_blocking is the same but uses parport_claim_or_block
+ * instead of parport_claim.
+ */
+extern __inline__ int parport_yield_blocking(struct pardevice *dev)
+{
+ unsigned long int timeslip = (jiffies - dev->time);
+ if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice))
+ return 0;
+ parport_release(dev);
+ return parport_claim_or_block(dev);
+}
+
+/*
+ * Lowlevel drivers _can_ call this support function to handle irqs.
+ */
+extern __inline__ void parport_generic_irq(int irq, struct parport *port,
+ struct pt_regs *regs)
+{
+ read_lock(&port->cad_lock);
+ if (!port->cad)
+ goto out_unlock;
+ if (port->cad->irq_func)
+ port->cad->irq_func(irq, port->cad->private, regs);
+ else
+ printk(KERN_ERR "%s: irq%d happened with irq_func NULL "
+ "with %s as cad!\n", port->name, irq, port->cad->name);
+ out_unlock:
+ read_unlock(&port->cad_lock);
+}
+
+/* Flags used to identify what a device does. */
+#define PARPORT_DEV_TRAN 0 /* WARNING !! DEPRECATED !! */
+#define PARPORT_DEV_LURK (1<<0) /* WARNING !! DEPRECATED !! */
+#define PARPORT_DEV_EXCL (1<<1) /* Need exclusive access. */
+
+#define PARPORT_FLAG_COMA (1<<0)
+#define PARPORT_FLAG_EXCL (1<<1) /* EXCL driver registered. */
+
+extern void parport_parse_irqs(int, const char *[], int irqval[]);
+extern int parport_ieee1284_nibble_mode_ok(struct parport *, unsigned char);
+extern int parport_wait_peripheral(struct parport *, unsigned char, unsigned
+ char);
+
+/* Prototypes from parport_procfs */
+extern int parport_proc_init(void);
+extern void parport_proc_cleanup(void);
+extern int parport_proc_register(struct parport *pp);
+extern int parport_proc_unregister(struct parport *pp);
+
+extern void dec_parport_count(void);
+extern void inc_parport_count(void);
+
+extern int parport_probe(struct parport *port, char *buffer, int len);
+extern void parport_probe_one(struct parport *port);
+extern void (*parport_probe_hook)(struct parport *port);
+
+/* If PC hardware is the only type supported, we can optimise a bit. */
+#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_AX) || defined(CONFIG_PARPORT_AX_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !defined(CONFIG_PARPORT_OTHER)
+#undef PARPORT_NEED_GENERIC_OPS
+#include <linux/parport_pc.h>
+#define parport_write_data(p,x) parport_pc_write_data(p,x)
+#define parport_read_data(p) parport_pc_read_data(p)
+#define parport_write_control(p,x) parport_pc_write_control(p,x)
+#define parport_read_control(p) parport_pc_read_control(p)
+#define parport_frob_control(p,m,v) parport_pc_frob_control(p,m,v)
+#define parport_write_econtrol(p,x) parport_pc_write_econtrol(p,x)
+#define parport_read_econtrol(p) parport_pc_read_econtrol(p)
+#define parport_frob_econtrol(p,m,v) parport_pc_frob_econtrol(p,m,v)
+#define parport_write_status(p,v) parport_pc_write_status(p,v)
+#define parport_read_status(p) parport_pc_read_status(p)
+#define parport_write_fifo(p,v) parport_pc_write_fifo(p,v)
+#define parport_read_fifo(p) parport_pc_read_fifo(p)
+#define parport_change_mode(p,m) parport_pc_change_mode(p,m)
+#define parport_release_resources(p) parport_pc_release_resources(p)
+#define parport_claim_resources(p) parport_pc_claim_resources(p)
+#define parport_epp_write_data(p,x) parport_pc_write_epp(p,x)
+#define parport_epp_read_data(p) parport_pc_read_epp(p)
+#define parport_epp_write_addr(p,x) parport_pc_write_epp_addr(p,x)
+#define parport_epp_read_addr(p) parport_pc_read_epp_addr(p)
+#define parport_epp_check_timeout(p) parport_pc_check_epp_timeout(p)
+#endif
+
+#ifdef PARPORT_NEED_GENERIC_OPS
+/* Generic operations vector through the dispatch table. */
+#define parport_write_data(p,x) (p)->ops->write_data(p,x)
+#define parport_read_data(p) (p)->ops->read_data(p)
+#define parport_write_control(p,x) (p)->ops->write_control(p,x)
+#define parport_read_control(p) (p)->ops->read_control(p)
+#define parport_frob_control(p,m,v) (p)->ops->frob_control(p,m,v)
+#define parport_write_econtrol(p,x) (p)->ops->write_econtrol(p,x)
+#define parport_read_econtrol(p) (p)->ops->read_econtrol(p)
+#define parport_frob_econtrol(p,m,v) (p)->ops->frob_econtrol(p,m,v)
+#define parport_write_status(p,v) (p)->ops->write_status(p,v)
+#define parport_read_status(p) (p)->ops->read_status(p)
+#define parport_write_fifo(p,v) (p)->ops->write_fifo(p,v)
+#define parport_read_fifo(p) (p)->ops->read_fifo(p)
+#define parport_change_mode(p,m) (p)->ops->change_mode(p,m)
+#define parport_release_resources(p) (p)->ops->release_resources(p)
+#define parport_claim_resources(p) (p)->ops->claim_resources(p)
+#define parport_epp_write_data(p,x) (p)->ops->epp_write_data(p,x)
+#define parport_epp_read_data(p) (p)->ops->epp_read_data(p)
+#define parport_epp_write_addr(p,x) (p)->ops->epp_write_addr(p,x)
+#define parport_epp_read_addr(p) (p)->ops->epp_read_addr(p)
+#define parport_epp_check_timeout(p) (p)->ops->epp_check_timeout(p)
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* _PARPORT_H_ */
diff --git a/pfinet/linux-src/include/linux/parport_pc.h b/pfinet/linux-src/include/linux/parport_pc.h
new file mode 100644
index 00000000..a74c7a12
--- /dev/null
+++ b/pfinet/linux-src/include/linux/parport_pc.h
@@ -0,0 +1,151 @@
+#ifndef __LINUX_PARPORT_PC_H
+#define __LINUX_PARPORT_PC_H
+
+#include <asm/io.h>
+
+/* --- register definitions ------------------------------- */
+
+#define ECONTROL 0x402
+#define CONFIGB 0x401
+#define CONFIGA 0x400
+#define EPPDATA 0x4
+#define EPPADDR 0x3
+#define CONTROL 0x2
+#define STATUS 0x1
+#define DATA 0
+
+/* Private data for PC low-level driver. */
+struct parport_pc_private {
+ /* Contents of CTR. */
+ unsigned char ctr;
+};
+
+extern int parport_pc_epp_clear_timeout(struct parport *pb);
+
+extern volatile unsigned char parport_pc_ctr;
+
+extern __inline__ void parport_pc_write_epp(struct parport *p, unsigned char d)
+{
+ outb(d, p->base+EPPDATA);
+}
+
+extern __inline__ unsigned char parport_pc_read_epp(struct parport *p)
+{
+ return inb(p->base+EPPDATA);
+}
+
+extern __inline__ void parport_pc_write_epp_addr(struct parport *p, unsigned char d)
+{
+ outb(d, p->base+EPPADDR);
+}
+
+extern __inline__ unsigned char parport_pc_read_epp_addr(struct parport *p)
+{
+ return inb(p->base+EPPADDR);
+}
+
+extern __inline__ int parport_pc_check_epp_timeout(struct parport *p)
+{
+ if (!(inb(p->base+STATUS) & 1))
+ return 0;
+ parport_pc_epp_clear_timeout(p);
+ return 1;
+}
+
+extern __inline__ unsigned char parport_pc_read_configb(struct parport *p)
+{
+ return inb(p->base+CONFIGB);
+}
+
+extern __inline__ void parport_pc_write_data(struct parport *p, unsigned char d)
+{
+ outb(d, p->base+DATA);
+}
+
+extern __inline__ unsigned char parport_pc_read_data(struct parport *p)
+{
+ return inb(p->base+DATA);
+}
+
+extern __inline__ void parport_pc_write_control(struct parport *p, unsigned char d)
+{
+ struct parport_pc_private *priv = p->private_data;
+ priv->ctr = d;/* update soft copy */
+ outb(d, p->base+CONTROL);
+}
+
+extern __inline__ unsigned char parport_pc_read_control(struct parport *p)
+{
+ struct parport_pc_private *priv = p->private_data;
+ return priv->ctr;
+}
+
+extern __inline__ unsigned char parport_pc_frob_control(struct parport *p, unsigned char mask, unsigned char val)
+{
+ struct parport_pc_private *priv = p->private_data;
+ unsigned char ctr = priv->ctr;
+ ctr = (ctr & ~mask) ^ val;
+ outb (ctr, p->base+CONTROL);
+ return priv->ctr = ctr; /* update soft copy */
+}
+
+extern __inline__ void parport_pc_write_status(struct parport *p, unsigned char d)
+{
+ outb(d, p->base+STATUS);
+}
+
+extern __inline__ unsigned char parport_pc_read_status(struct parport *p)
+{
+ return inb(p->base+STATUS);
+}
+
+extern __inline__ void parport_pc_write_econtrol(struct parport *p, unsigned char d)
+{
+ outb(d, p->base+ECONTROL);
+}
+
+extern __inline__ unsigned char parport_pc_read_econtrol(struct parport *p)
+{
+ return inb(p->base+ECONTROL);
+}
+
+extern __inline__ unsigned char parport_pc_frob_econtrol(struct parport *p, unsigned char mask, unsigned char val)
+{
+ unsigned char old = inb(p->base+ECONTROL);
+ outb(((old & ~mask) ^ val), p->base+ECONTROL);
+ return old;
+}
+
+extern void parport_pc_change_mode(struct parport *p, int m);
+
+extern void parport_pc_write_fifo(struct parport *p, unsigned char v);
+
+extern unsigned char parport_pc_read_fifo(struct parport *p);
+
+extern void parport_pc_disable_irq(struct parport *p);
+
+extern void parport_pc_enable_irq(struct parport *p);
+
+extern void parport_pc_release_resources(struct parport *p);
+
+extern int parport_pc_claim_resources(struct parport *p);
+
+extern void parport_pc_init_state(struct parport_state *s);
+
+extern void parport_pc_save_state(struct parport *p, struct parport_state *s);
+
+extern void parport_pc_restore_state(struct parport *p, struct parport_state *s);
+
+extern size_t parport_pc_epp_read_block(struct parport *p, void *buf, size_t length);
+
+extern size_t parport_pc_epp_write_block(struct parport *p, void *buf, size_t length);
+
+extern int parport_pc_ecp_read_block(struct parport *p, void *buf, size_t length, void (*fn)(struct parport *, void *, size_t), void *handle);
+
+extern int parport_pc_ecp_write_block(struct parport *p, void *buf, size_t length, void (*fn)(struct parport *, void *, size_t), void *handle);
+
+extern void parport_pc_inc_use_count(void);
+
+extern void parport_pc_dec_use_count(void);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/pc_keyb.h b/pfinet/linux-src/include/linux/pc_keyb.h
new file mode 100644
index 00000000..29ccd395
--- /dev/null
+++ b/pfinet/linux-src/include/linux/pc_keyb.h
@@ -0,0 +1,130 @@
+/*
+ * include/linux/pc_keyb.h
+ *
+ * PC Keyboard And Keyboard Controller
+ *
+ * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+/*
+ * Configuration Switches
+ */
+
+#undef KBD_REPORT_ERR /* Report keyboard errors */
+#define KBD_REPORT_UNKN /* Report unknown scan codes */
+#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */
+#undef KBD_IS_FOCUS_9000 /* We have the brain-damaged FOCUS-9000 keyboard */
+#undef INITIALIZE_MOUSE /* Define if your PS/2 mouse needs initialization. */
+
+
+
+#define KBD_INIT_TIMEOUT 1000 /* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 1000 /* Timeout in ms for keyboard command acknowledge */
+
+/*
+ * Internal variables of the driver
+ */
+
+extern unsigned char pckbd_read_mask;
+extern unsigned char aux_device_present;
+
+/*
+ * Keyboard Controller Registers on normal PCs.
+ */
+
+#define KBD_STATUS_REG 0x64 /* Status register (R) */
+#define KBD_CNTL_REG 0x64 /* Controller command register (W) */
+#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
+
+/*
+ * Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
+#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
+#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
+#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
+#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
+ initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
+
+/*
+ * Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
+#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
+#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
+#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */
+#define KBD_CMD_RESET 0xFF /* Reset */
+
+/*
+ * Keyboard Replies
+ */
+
+#define KBD_REPLY_POR 0xAA /* Power on reset */
+#define KBD_REPLY_ACK 0xFA /* Command ACK */
+#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
+
+/*
+ * Status Register Bits
+ */
+
+#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
+#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
+#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
+#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
+#define KBD_STAT_PERR 0x80 /* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ * Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS 0x04 /* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
+#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
+#define KBD_MODE_RFU 0x80
+
+/*
+ * Mouse Commands
+ */
+
+#define AUX_SET_RES 0xE8 /* Set resolution */
+#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
+#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
+#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
+#define AUX_SET_STREAM 0xEA /* Set stream mode */
+#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
+#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
+#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
+#define AUX_RESET 0xFF /* Reset aux device */
+#define AUX_ACK 0xFA /* Command byte ACK. */
+
+#define AUX_BUF_SIZE 2048 /* This might be better divisible by
+ three to make overruns stay in sync
+ but then the read function would need
+ a lock etc - ick */
+
+struct aux_queue {
+ unsigned long head;
+ unsigned long tail;
+ struct wait_queue *proc_list;
+ struct fasync_struct *fasync;
+ unsigned char buf[AUX_BUF_SIZE];
+};
diff --git a/pfinet/linux-src/include/linux/pci.h b/pfinet/linux-src/include/linux/pci.h
new file mode 100644
index 00000000..505bb16f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/pci.h
@@ -0,0 +1,1320 @@
+/*
+ * $Id: pci.h,v 1.87 1998/10/11 15:13:12 mj Exp $
+ *
+ * PCI defines and function prototypes
+ * Copyright 1994, Drew Eckhardt
+ * Copyright 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * For more information, please consult the following manuals (look at
+ * http://www.pcisig.com/ for how to get them):
+ *
+ * PCI BIOS Specification
+ * PCI Local Bus Specification
+ * PCI to PCI Bridge Specification
+ * PCI System Design Guide
+ */
+
+#ifndef LINUX_PCI_H
+#define LINUX_PCI_H
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID 0x00 /* 16 bits */
+#define PCI_DEVICE_ID 0x02 /* 16 bits */
+#define PCI_COMMAND 0x04 /* 16 bits */
+#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
+#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
+#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+
+#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features */
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8
+ revision */
+#define PCI_REVISION_ID 0x08 /* Revision ID */
+#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE 0x0a /* Device class */
+
+#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
+#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
+#define PCI_HEADER_TYPE 0x0e /* 8 bits */
+#define PCI_HEADER_TYPE_NORMAL 0
+#define PCI_HEADER_TYPE_BRIDGE 1
+#define PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST 0x0f /* 8 bits */
+#define PCI_BIST_CODE_MASK 0x0f /* Return result */
+#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back. Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
+#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
+#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
+#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS 0x28
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID 0x2e
+#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
+#define PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
+
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
+#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
+#define PCI_MIN_GNT 0x3e /* 8 bits */
+#define PCI_MAX_LAT 0x3f /* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
+#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
+#define PCI_IO_LIMIT 0x1d
+#define PCI_IO_RANGE_TYPE_MASK 0x0f /* I/O bridging type */
+#define PCI_IO_RANGE_TYPE_16 0x00
+#define PCI_IO_RANGE_TYPE_32 0x01
+#define PCI_IO_RANGE_MASK ~0x0f
+#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
+#define PCI_MEMORY_LIMIT 0x22
+#define PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define PCI_MEMORY_RANGE_MASK ~0x0f
+#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT 0x26
+#define PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define PCI_PREF_RANGE_TYPE_32 0x00
+#define PCI_PREF_RANGE_TYPE_64 0x01
+#define PCI_PREF_RANGE_MASK ~0x0f
+#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16 0x32
+/* 0x34-0x3b is reserved */
+#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL 0x3e
+#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
+#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
+#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
+#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
+#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
+#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+/* 0x14-0x15 reserved */
+#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */
+#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */
+#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0 0x1c
+#define PCI_CB_MEMORY_LIMIT_0 0x20
+#define PCI_CB_MEMORY_BASE_1 0x24
+#define PCI_CB_MEMORY_LIMIT_1 0x28
+#define PCI_CB_IO_BASE_0 0x2c
+#define PCI_CB_IO_BASE_0_HI 0x2e
+#define PCI_CB_IO_LIMIT_0 0x30
+#define PCI_CB_IO_LIMIT_0_HI 0x32
+#define PCI_CB_IO_BASE_1 0x34
+#define PCI_CB_IO_BASE_1_HI 0x36
+#define PCI_CB_IO_LIMIT_1 0x38
+#define PCI_CB_IO_LIMIT_1_HI 0x3a
+#define PCI_CB_IO_RANGE_MASK ~0x03
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL 0x3e
+#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */
+#define PCI_CB_BRIDGE_CTL_SERR 0x02
+#define PCI_CB_BRIDGE_CTL_ISA 0x04
+#define PCI_CB_BRIDGE_CTL_VGA 0x08
+#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
+#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */
+#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID 0x42
+#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+#define PCI_CAP_LIST_ID 0 /* Capability ID */
+#define PCI_CAP_ID_PM 0x01 /* Power Management */
+#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
+#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED 0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA 0x0001
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_CLASS_STORAGE_SCSI 0x0100
+#define PCI_CLASS_STORAGE_IDE 0x0101
+#define PCI_CLASS_STORAGE_FLOPPY 0x0102
+#define PCI_CLASS_STORAGE_IPI 0x0103
+#define PCI_CLASS_STORAGE_RAID 0x0104
+#define PCI_CLASS_STORAGE_OTHER 0x0180
+
+#define PCI_BASE_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201
+#define PCI_CLASS_NETWORK_FDDI 0x0202
+#define PCI_CLASS_NETWORK_ATM 0x0203
+#define PCI_CLASS_NETWORK_OTHER 0x0280
+
+#define PCI_BASE_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_DISPLAY_XGA 0x0301
+#define PCI_CLASS_DISPLAY_OTHER 0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
+#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
+
+#define PCI_BASE_CLASS_MEMORY 0x05
+#define PCI_CLASS_MEMORY_RAM 0x0500
+#define PCI_CLASS_MEMORY_FLASH 0x0501
+#define PCI_CLASS_MEMORY_OTHER 0x0580
+
+#define PCI_BASE_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x0600
+#define PCI_CLASS_BRIDGE_ISA 0x0601
+#define PCI_CLASS_BRIDGE_EISA 0x0602
+#define PCI_CLASS_BRIDGE_MC 0x0603
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#define PCI_CLASS_BRIDGE_PCMCIA 0x0605
+#define PCI_CLASS_BRIDGE_NUBUS 0x0606
+#define PCI_CLASS_BRIDGE_CARDBUS 0x0607
+#define PCI_CLASS_BRIDGE_OTHER 0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION 0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
+
+#define PCI_BASE_CLASS_SYSTEM 0x08
+#define PCI_CLASS_SYSTEM_PIC 0x0800
+#define PCI_CLASS_SYSTEM_DMA 0x0801
+#define PCI_CLASS_SYSTEM_TIMER 0x0802
+#define PCI_CLASS_SYSTEM_RTC 0x0803
+#define PCI_CLASS_SYSTEM_OTHER 0x0880
+
+#define PCI_BASE_CLASS_INPUT 0x09
+#define PCI_CLASS_INPUT_KEYBOARD 0x0900
+#define PCI_CLASS_INPUT_PEN 0x0901
+#define PCI_CLASS_INPUT_MOUSE 0x0902
+#define PCI_CLASS_INPUT_OTHER 0x0980
+
+#define PCI_BASE_CLASS_DOCKING 0x0a
+#define PCI_CLASS_DOCKING_GENERIC 0x0a00
+#define PCI_CLASS_DOCKING_OTHER 0x0a01
+
+#define PCI_BASE_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_PROCESSOR_386 0x0b00
+#define PCI_CLASS_PROCESSOR_486 0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20
+#define PCI_CLASS_PROCESSOR_CO 0x0b40
+
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
+#define PCI_CLASS_SERIAL_ACCESS 0x0c01
+#define PCI_CLASS_SERIAL_SSA 0x0c02
+#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_FIBER 0x0c04
+
+#define PCI_CLASS_HOT_SWAP_CONTROLLER 0xff00
+
+#define PCI_CLASS_OTHERS 0xff
+
+/*
+ * Vendor and card ID's: sort these numerically according to vendor
+ * (and according to card ID within vendor). Send all updates to
+ * <linux-pcisupport@cck.uni-kl.de>.
+ */
+#define PCI_VENDOR_ID_COMPAQ 0x0e11
+#define PCI_DEVICE_ID_COMPAQ_1280 0x3033
+#define PCI_DEVICE_ID_COMPAQ_TRIFLEX 0x4000
+#define PCI_DEVICE_ID_COMPAQ_SMART2P 0xae10
+#define PCI_DEVICE_ID_COMPAQ_NETEL100 0xae32
+#define PCI_DEVICE_ID_COMPAQ_NETEL10 0xae34
+#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I 0xae35
+#define PCI_DEVICE_ID_COMPAQ_NETEL100D 0xae40
+#define PCI_DEVICE_ID_COMPAQ_NETEL100PI 0xae43
+#define PCI_DEVICE_ID_COMPAQ_NETEL100I 0xb011
+#define PCI_DEVICE_ID_COMPAQ_THUNDER 0xf130
+#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B 0xf150
+
+#define PCI_VENDOR_ID_NCR 0x1000
+#define PCI_DEVICE_ID_NCR_53C810 0x0001
+#define PCI_DEVICE_ID_NCR_53C820 0x0002
+#define PCI_DEVICE_ID_NCR_53C825 0x0003
+#define PCI_DEVICE_ID_NCR_53C815 0x0004
+#define PCI_DEVICE_ID_NCR_53C860 0x0006
+#define PCI_DEVICE_ID_NCR_53C896 0x000b
+#define PCI_DEVICE_ID_NCR_53C895 0x000c
+#define PCI_DEVICE_ID_NCR_53C885 0x000d
+#define PCI_DEVICE_ID_NCR_53C875 0x000f
+#define PCI_DEVICE_ID_NCR_53C1510 0x0010
+#define PCI_DEVICE_ID_NCR_53C875J 0x008f
+
+#define PCI_VENDOR_ID_ATI 0x1002
+#define PCI_DEVICE_ID_ATI_68800 0x4158
+#define PCI_DEVICE_ID_ATI_215CT222 0x4354
+#define PCI_DEVICE_ID_ATI_210888CX 0x4358
+#define PCI_DEVICE_ID_ATI_215GB 0x4742
+#define PCI_DEVICE_ID_ATI_215GD 0x4744
+#define PCI_DEVICE_ID_ATI_215GI 0x4749
+#define PCI_DEVICE_ID_ATI_215GP 0x4750
+#define PCI_DEVICE_ID_ATI_215GQ 0x4751
+#define PCI_DEVICE_ID_ATI_215GT 0x4754
+#define PCI_DEVICE_ID_ATI_215GTB 0x4755
+#define PCI_DEVICE_ID_ATI_210888GX 0x4758
+#define PCI_DEVICE_ID_ATI_215LG 0x4c47
+#define PCI_DEVICE_ID_ATI_264LT 0x4c54
+#define PCI_DEVICE_ID_ATI_264VT 0x5654
+
+#define PCI_VENDOR_ID_VLSI 0x1004
+#define PCI_DEVICE_ID_VLSI_82C592 0x0005
+#define PCI_DEVICE_ID_VLSI_82C593 0x0006
+#define PCI_DEVICE_ID_VLSI_82C594 0x0007
+#define PCI_DEVICE_ID_VLSI_82C597 0x0009
+#define PCI_DEVICE_ID_VLSI_82C541 0x000c
+#define PCI_DEVICE_ID_VLSI_82C543 0x000d
+#define PCI_DEVICE_ID_VLSI_82C532 0x0101
+#define PCI_DEVICE_ID_VLSI_82C534 0x0102
+#define PCI_DEVICE_ID_VLSI_82C535 0x0104
+#define PCI_DEVICE_ID_VLSI_82C147 0x0105
+#define PCI_DEVICE_ID_VLSI_VAS96011 0x0702
+
+#define PCI_VENDOR_ID_ADL 0x1005
+#define PCI_DEVICE_ID_ADL_2301 0x2301
+
+#define PCI_VENDOR_ID_NS 0x100b
+#define PCI_DEVICE_ID_NS_87415 0x0002
+#define PCI_DEVICE_ID_NS_87410 0xd001
+
+#define PCI_VENDOR_ID_TSENG 0x100c
+#define PCI_DEVICE_ID_TSENG_W32P_2 0x3202
+#define PCI_DEVICE_ID_TSENG_W32P_b 0x3205
+#define PCI_DEVICE_ID_TSENG_W32P_c 0x3206
+#define PCI_DEVICE_ID_TSENG_W32P_d 0x3207
+#define PCI_DEVICE_ID_TSENG_ET6000 0x3208
+
+#define PCI_VENDOR_ID_WEITEK 0x100e
+#define PCI_DEVICE_ID_WEITEK_P9000 0x9001
+#define PCI_DEVICE_ID_WEITEK_P9100 0x9100
+
+#define PCI_VENDOR_ID_DEC 0x1011
+#define PCI_DEVICE_ID_DEC_BRD 0x0001
+#define PCI_DEVICE_ID_DEC_TULIP 0x0002
+#define PCI_DEVICE_ID_DEC_TGA 0x0004
+#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009
+#define PCI_DEVICE_ID_DEC_TGA2 0x000D
+#define PCI_DEVICE_ID_DEC_FDDI 0x000F
+#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014
+#define PCI_DEVICE_ID_DEC_21142 0x0019
+#define PCI_DEVICE_ID_DEC_21052 0x0021
+#define PCI_DEVICE_ID_DEC_21150 0x0022
+#define PCI_DEVICE_ID_DEC_21152 0x0024
+#define PCI_DEVICE_ID_DEC_21153 0x0025
+#define PCI_DEVICE_ID_DEC_21154 0x0026
+#define PCI_DEVICE_ID_DEC_21285 0x1065
+#define PCI_DEVICE_ID_COMPAQ_42XX 0x0046
+
+#define PCI_VENDOR_ID_CIRRUS 0x1013
+#define PCI_DEVICE_ID_CIRRUS_7548 0x0038
+#define PCI_DEVICE_ID_CIRRUS_5430 0x00a0
+#define PCI_DEVICE_ID_CIRRUS_5434_4 0x00a4
+#define PCI_DEVICE_ID_CIRRUS_5434_8 0x00a8
+#define PCI_DEVICE_ID_CIRRUS_5436 0x00ac
+#define PCI_DEVICE_ID_CIRRUS_5446 0x00b8
+#define PCI_DEVICE_ID_CIRRUS_5480 0x00bc
+#define PCI_DEVICE_ID_CIRRUS_5464 0x00d4
+#define PCI_DEVICE_ID_CIRRUS_5465 0x00d6
+#define PCI_DEVICE_ID_CIRRUS_6729 0x1100
+#define PCI_DEVICE_ID_CIRRUS_6832 0x1110
+#define PCI_DEVICE_ID_CIRRUS_7542 0x1200
+#define PCI_DEVICE_ID_CIRRUS_7543 0x1202
+#define PCI_DEVICE_ID_CIRRUS_7541 0x1204
+
+#define PCI_VENDOR_ID_IBM 0x1014
+#define PCI_DEVICE_ID_IBM_FIRE_CORAL 0x000a
+#define PCI_DEVICE_ID_IBM_TR 0x0018
+#define PCI_DEVICE_ID_IBM_82G2675 0x001d
+#define PCI_DEVICE_ID_IBM_MCA 0x0020
+#define PCI_DEVICE_ID_IBM_82351 0x0022
+#define PCI_DEVICE_ID_IBM_PYTHON 0x002d
+#define PCI_DEVICE_ID_IBM_SERVERAID 0x002e
+#define PCI_DEVICE_ID_IBM_TR_WAKE 0x003e
+#define PCI_DEVICE_ID_IBM_MPIC 0x0046
+#define PCI_DEVICE_ID_IBM_3780IDSP 0x007d
+#define PCI_DEVICE_ID_IBM_MPIC_2 0xffff
+
+#define PCI_VENDOR_ID_WD 0x101c
+#define PCI_DEVICE_ID_WD_7197 0x3296
+
+#define PCI_VENDOR_ID_AMD 0x1022
+#define PCI_DEVICE_ID_AMD_LANCE 0x2000
+#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001
+#define PCI_DEVICE_ID_AMD_SCSI 0x2020
+
+#define PCI_VENDOR_ID_TRIDENT 0x1023
+#define PCI_DEVICE_ID_TRIDENT_9397 0x9397
+#define PCI_DEVICE_ID_TRIDENT_9420 0x9420
+#define PCI_DEVICE_ID_TRIDENT_9440 0x9440
+#define PCI_DEVICE_ID_TRIDENT_9660 0x9660
+#define PCI_DEVICE_ID_TRIDENT_9750 0x9750
+
+#define PCI_VENDOR_ID_AI 0x1025
+#define PCI_DEVICE_ID_AI_M1435 0x1435
+
+#define PCI_VENDOR_ID_MATROX 0x102B
+#define PCI_DEVICE_ID_MATROX_MGA_2 0x0518
+#define PCI_DEVICE_ID_MATROX_MIL 0x0519
+#define PCI_DEVICE_ID_MATROX_MYS 0x051A
+#define PCI_DEVICE_ID_MATROX_MIL_2 0x051b
+#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f
+#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520
+#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
+#define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10
+#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000
+#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001
+
+#define PCI_VENDOR_ID_CT 0x102c
+#define PCI_DEVICE_ID_CT_65545 0x00d8
+#define PCI_DEVICE_ID_CT_65548 0x00dc
+#define PCI_DEVICE_ID_CT_65550 0x00e0
+#define PCI_DEVICE_ID_CT_65554 0x00e4
+#define PCI_DEVICE_ID_CT_65555 0x00e5
+
+#define PCI_VENDOR_ID_MIRO 0x1031
+#define PCI_DEVICE_ID_MIRO_36050 0x5601
+
+#define PCI_VENDOR_ID_NEC 0x1033
+#define PCI_DEVICE_ID_NEC_PCX2 0x0046
+
+#define PCI_VENDOR_ID_FD 0x1036
+#define PCI_DEVICE_ID_FD_36C70 0x0000
+
+#define PCI_VENDOR_ID_SI 0x1039
+#define PCI_DEVICE_ID_SI_5591_AGP 0x0001
+#define PCI_DEVICE_ID_SI_6202 0x0002
+#define PCI_DEVICE_ID_SI_503 0x0008
+#define PCI_DEVICE_ID_SI_ACPI 0x0009
+#define PCI_DEVICE_ID_SI_5597_VGA 0x0200
+#define PCI_DEVICE_ID_SI_6205 0x0205
+#define PCI_DEVICE_ID_SI_501 0x0406
+#define PCI_DEVICE_ID_SI_496 0x0496
+#define PCI_DEVICE_ID_SI_601 0x0601
+#define PCI_DEVICE_ID_SI_5107 0x5107
+#define PCI_DEVICE_ID_SI_5511 0x5511
+#define PCI_DEVICE_ID_SI_5513 0x5513
+#define PCI_DEVICE_ID_SI_5571 0x5571
+#define PCI_DEVICE_ID_SI_5591 0x5591
+#define PCI_DEVICE_ID_SI_5597 0x5597
+#define PCI_DEVICE_ID_SI_7001 0x7001
+
+#define PCI_VENDOR_ID_HP 0x103c
+#define PCI_DEVICE_ID_HP_J2585A 0x1030
+#define PCI_DEVICE_ID_HP_J2585B 0x1031
+
+#define PCI_VENDOR_ID_PCTECH 0x1042
+#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000
+#define PCI_DEVICE_ID_PCTECH_RZ1001 0x1001
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_0 0x3000
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_1 0x3010
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
+
+#define PCI_VENDOR_ID_DPT 0x1044
+#define PCI_DEVICE_ID_DPT 0xa400
+
+#define PCI_VENDOR_ID_OPTI 0x1045
+#define PCI_DEVICE_ID_OPTI_92C178 0xc178
+#define PCI_DEVICE_ID_OPTI_82C557 0xc557
+#define PCI_DEVICE_ID_OPTI_82C558 0xc558
+#define PCI_DEVICE_ID_OPTI_82C621 0xc621
+#define PCI_DEVICE_ID_OPTI_82C700 0xc700
+#define PCI_DEVICE_ID_OPTI_82C701 0xc701
+#define PCI_DEVICE_ID_OPTI_82C814 0xc814
+#define PCI_DEVICE_ID_OPTI_82C822 0xc822
+#define PCI_DEVICE_ID_OPTI_82C861 0xc861
+#define PCI_DEVICE_ID_OPTI_82C825 0xd568
+
+#define PCI_VENDOR_ID_SGS 0x104a
+#define PCI_DEVICE_ID_SGS_2000 0x0008
+#define PCI_DEVICE_ID_SGS_1764 0x0009
+
+#define PCI_VENDOR_ID_BUSLOGIC 0x104B
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040
+#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130
+
+#define PCI_VENDOR_ID_TI 0x104c
+#define PCI_DEVICE_ID_TI_TVP4010 0x3d04
+#define PCI_DEVICE_ID_TI_TVP4020 0x3d07
+#define PCI_DEVICE_ID_TI_PCI1130 0xac12
+#define PCI_DEVICE_ID_TI_PCI1031 0xac13
+#define PCI_DEVICE_ID_TI_PCI1131 0xac15
+#define PCI_DEVICE_ID_TI_PCI1250 0xac16
+#define PCI_DEVICE_ID_TI_PCI1220 0xac17
+
+#define PCI_VENDOR_ID_OAK 0x104e
+#define PCI_DEVICE_ID_OAK_OTI107 0x0107
+
+/* Winbond have two vendor IDs! See 0x10ad as well */
+#define PCI_VENDOR_ID_WINBOND2 0x1050
+#define PCI_DEVICE_ID_WINBOND2_89C940 0x0940
+
+#define PCI_VENDOR_ID_MOTOROLA 0x1057
+#define PCI_VENDOR_ID_MOTOROLA_OOPS 0x1507
+#define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001
+#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002
+#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801
+#define PCI_DEVICE_ID_MOTOROLA_FALCON 0x4802
+#define PCI_DEVICE_ID_MOTOROLA_CPX8216 0x4806
+
+#define PCI_VENDOR_ID_PROMISE 0x105a
+#define PCI_DEVICE_ID_PROMISE_20246 0x4d33
+#define PCI_DEVICE_ID_PROMISE_5300 0x5300
+
+#define PCI_VENDOR_ID_N9 0x105d
+#define PCI_DEVICE_ID_N9_I128 0x2309
+#define PCI_DEVICE_ID_N9_I128_2 0x2339
+#define PCI_DEVICE_ID_N9_I128_T2R 0x493d
+
+#define PCI_VENDOR_ID_UMC 0x1060
+#define PCI_DEVICE_ID_UMC_UM8673F 0x0101
+#define PCI_DEVICE_ID_UMC_UM8891A 0x0891
+#define PCI_DEVICE_ID_UMC_UM8886BF 0x673a
+#define PCI_DEVICE_ID_UMC_UM8886A 0x886a
+#define PCI_DEVICE_ID_UMC_UM8881F 0x8881
+#define PCI_DEVICE_ID_UMC_UM8886F 0x8886
+#define PCI_DEVICE_ID_UMC_UM9017F 0x9017
+#define PCI_DEVICE_ID_UMC_UM8886N 0xe886
+#define PCI_DEVICE_ID_UMC_UM8891N 0xe891
+
+#define PCI_VENDOR_ID_X 0x1061
+#define PCI_DEVICE_ID_X_AGX016 0x0001
+
+#define PCI_VENDOR_ID_PICOP 0x1066
+#define PCI_DEVICE_ID_PICOP_PT86C52X 0x0001
+#define PCI_DEVICE_ID_PICOP_PT80C524 0x8002
+
+#define PCI_VENDOR_ID_MYLEX 0x1069
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V2 0x0001
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V3 0x0002
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V4 0x0010
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V5 0x0020
+
+#define PCI_VENDOR_ID_APPLE 0x106b
+#define PCI_DEVICE_ID_APPLE_BANDIT 0x0001
+#define PCI_DEVICE_ID_APPLE_GC 0x0002
+#define PCI_DEVICE_ID_APPLE_HYDRA 0x000e
+
+#define PCI_VENDOR_ID_NEXGEN 0x1074
+#define PCI_DEVICE_ID_NEXGEN_82C501 0x4e78
+
+#define PCI_VENDOR_ID_QLOGIC 0x1077
+#define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020
+#define PCI_DEVICE_ID_QLOGIC_ISP1022 0x1022
+#define PCI_DEVICE_ID_QLOGIC_ISP2100 0x2100
+#define PCI_DEVICE_ID_QLOGIC_ISP2200 0x2200
+
+#define PCI_VENDOR_ID_CYRIX 0x1078
+#define PCI_DEVICE_ID_CYRIX_5510 0x0000
+#define PCI_DEVICE_ID_CYRIX_PCI_MASTER 0x0001
+#define PCI_DEVICE_ID_CYRIX_5520 0x0002
+#define PCI_DEVICE_ID_CYRIX_5530_LEGACY 0x0100
+#define PCI_DEVICE_ID_CYRIX_5530_SMI 0x0101
+#define PCI_DEVICE_ID_CYRIX_5530_IDE 0x0102
+#define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103
+#define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104
+
+#define PCI_VENDOR_ID_LEADTEK 0x107d
+#define PCI_DEVICE_ID_LEADTEK_805 0x0000
+
+#define PCI_VENDOR_ID_CONTAQ 0x1080
+#define PCI_DEVICE_ID_CONTAQ_82C599 0x0600
+#define PCI_DEVICE_ID_CONTAQ_82C693 0xc693
+
+#define PCI_VENDOR_ID_FOREX 0x1083
+
+#define PCI_VENDOR_ID_OLICOM 0x108d
+#define PCI_DEVICE_ID_OLICOM_OC3136 0x0001
+#define PCI_DEVICE_ID_OLICOM_OC2315 0x0011
+#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012
+#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013
+#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014
+#define PCI_DEVICE_ID_OLICOM_OC6151 0x0021
+
+#define PCI_VENDOR_ID_SUN 0x108e
+#define PCI_DEVICE_ID_SUN_EBUS 0x1000
+#define PCI_DEVICE_ID_SUN_HAPPYMEAL 0x1001
+#define PCI_DEVICE_ID_SUN_SIMBA 0x5000
+#define PCI_DEVICE_ID_SUN_PBM 0x8000
+#define PCI_DEVICE_ID_SUN_SABRE 0xa000
+
+#define PCI_VENDOR_ID_CMD 0x1095
+#define PCI_DEVICE_ID_CMD_640 0x0640
+#define PCI_DEVICE_ID_CMD_643 0x0643
+#define PCI_DEVICE_ID_CMD_646 0x0646
+#define PCI_DEVICE_ID_CMD_647 0x0647
+#define PCI_DEVICE_ID_CMD_670 0x0670
+
+#define PCI_VENDOR_ID_VISION 0x1098
+#define PCI_DEVICE_ID_VISION_QD8500 0x0001
+#define PCI_DEVICE_ID_VISION_QD8580 0x0002
+
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#define PCI_DEVICE_ID_BROOKTREE_848 0x0350
+#define PCI_DEVICE_ID_BROOKTREE_849A 0x0351
+#define PCI_DEVICE_ID_BROOKTREE_878_1 0x036e
+#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
+#define PCI_DEVICE_ID_BROOKTREE_8474 0x8474
+
+#define PCI_VENDOR_ID_SIERRA 0x10a8
+#define PCI_DEVICE_ID_SIERRA_STB 0x0000
+
+#define PCI_VENDOR_ID_ACC 0x10aa
+#define PCI_DEVICE_ID_ACC_2056 0x0000
+
+#define PCI_VENDOR_ID_WINBOND 0x10ad
+#define PCI_DEVICE_ID_WINBOND_83769 0x0001
+#define PCI_DEVICE_ID_WINBOND_82C105 0x0105
+#define PCI_DEVICE_ID_WINBOND_83C553 0x0565
+
+#define PCI_VENDOR_ID_DATABOOK 0x10b3
+#define PCI_DEVICE_ID_DATABOOK_87144 0xb106
+
+#define PCI_VENDOR_ID_PLX 0x10b5
+#define PCI_DEVICE_ID_PLX_9050 0x9050
+#define PCI_DEVICE_ID_PLX_9060 0x9060
+#define PCI_DEVICE_ID_PLX_9060ES 0x906E
+#define PCI_DEVICE_ID_PLX_9060SD 0x906D
+#define PCI_DEVICE_ID_PLX_9080 0x9080
+
+#define PCI_VENDOR_ID_MADGE 0x10b6
+#define PCI_DEVICE_ID_MADGE_MK2 0x0002
+#define PCI_DEVICE_ID_MADGE_C155S 0x1001
+
+#define PCI_VENDOR_ID_3COM 0x10b7
+#define PCI_DEVICE_ID_3COM_3C985 0x0001
+#define PCI_DEVICE_ID_3COM_3C339 0x3390
+#define PCI_DEVICE_ID_3COM_3C590 0x5900
+#define PCI_DEVICE_ID_3COM_3C595TX 0x5950
+#define PCI_DEVICE_ID_3COM_3C595T4 0x5951
+#define PCI_DEVICE_ID_3COM_3C595MII 0x5952
+#define PCI_DEVICE_ID_3COM_3C900TPO 0x9000
+#define PCI_DEVICE_ID_3COM_3C900COMBO 0x9001
+#define PCI_DEVICE_ID_3COM_3C905TX 0x9050
+#define PCI_DEVICE_ID_3COM_3C905T4 0x9051
+#define PCI_DEVICE_ID_3COM_3C905B_TX 0x9055
+
+#define PCI_VENDOR_ID_SMC 0x10b8
+#define PCI_DEVICE_ID_SMC_EPIC100 0x0005
+
+#define PCI_VENDOR_ID_AL 0x10b9
+#define PCI_DEVICE_ID_AL_M1445 0x1445
+#define PCI_DEVICE_ID_AL_M1449 0x1449
+#define PCI_DEVICE_ID_AL_M1451 0x1451
+#define PCI_DEVICE_ID_AL_M1461 0x1461
+#define PCI_DEVICE_ID_AL_M1489 0x1489
+#define PCI_DEVICE_ID_AL_M1511 0x1511
+#define PCI_DEVICE_ID_AL_M1513 0x1513
+#define PCI_DEVICE_ID_AL_M1521 0x1521
+#define PCI_DEVICE_ID_AL_M1523 0x1523
+#define PCI_DEVICE_ID_AL_M1531 0x1531
+#define PCI_DEVICE_ID_AL_M1533 0x1533
+#define PCI_DEVICE_ID_AL_M3307 0x3307
+#define PCI_DEVICE_ID_AL_M4803 0x5215
+#define PCI_DEVICE_ID_AL_M5219 0x5219
+#define PCI_DEVICE_ID_AL_M5229 0x5229
+#define PCI_DEVICE_ID_AL_M5237 0x5237
+#define PCI_DEVICE_ID_AL_M7101 0x7101
+
+#define PCI_VENDOR_ID_MITSUBISHI 0x10ba
+
+#define PCI_VENDOR_ID_SURECOM 0x10bd
+#define PCI_DEVICE_ID_SURECOM_NE34 0x0e34
+
+#define PCI_VENDOR_ID_NEOMAGIC 0x10c8
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2070 0x0001
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128V 0x0002
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZV 0x0003
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICMEDIA_256AV 0x0005
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZVPLUS 0x0083
+
+#define PCI_VENDOR_ID_ASP 0x10cd
+#define PCI_DEVICE_ID_ASP_ABP940 0x1200
+#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
+#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
+
+#define PCI_VENDOR_ID_MACRONIX 0x10d9
+#define PCI_DEVICE_ID_MACRONIX_MX98713 0x0512
+#define PCI_DEVICE_ID_MACRONIX_MX987x5 0x0531
+
+#define PCI_VENDOR_ID_CERN 0x10dc
+#define PCI_DEVICE_ID_CERN_SPSB_PMC 0x0001
+#define PCI_DEVICE_ID_CERN_SPSB_PCI 0x0002
+#define PCI_DEVICE_ID_CERN_HIPPI_DST 0x0021
+#define PCI_DEVICE_ID_CERN_HIPPI_SRC 0x0022
+
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+
+#define PCI_VENDOR_ID_IMS 0x10e0
+#define PCI_DEVICE_ID_IMS_8849 0x8849
+
+#define PCI_VENDOR_ID_TEKRAM2 0x10e1
+#define PCI_DEVICE_ID_TEKRAM2_690c 0x690c
+
+#define PCI_VENDOR_ID_TUNDRA 0x10e3
+#define PCI_DEVICE_ID_TUNDRA_CA91C042 0x0000
+
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#define PCI_DEVICE_ID_AMCC_MYRINET 0x8043
+#define PCI_DEVICE_ID_AMCC_PARASTATION 0x8062
+#define PCI_DEVICE_ID_AMCC_S5933 0x807d
+#define PCI_DEVICE_ID_AMCC_S5933_HEPC3 0x809c
+
+#define PCI_VENDOR_ID_INTERG 0x10ea
+#define PCI_DEVICE_ID_INTERG_1680 0x1680
+#define PCI_DEVICE_ID_INTERG_1682 0x1682
+
+#define PCI_VENDOR_ID_REALTEK 0x10ec
+#define PCI_DEVICE_ID_REALTEK_8029 0x8029
+#define PCI_DEVICE_ID_REALTEK_8129 0x8129
+#define PCI_DEVICE_ID_REALTEK_8139 0x8139
+
+#define PCI_VENDOR_ID_TRUEVISION 0x10fa
+#define PCI_DEVICE_ID_TRUEVISION_T1000 0x000c
+
+#define PCI_VENDOR_ID_INIT 0x1101
+#define PCI_DEVICE_ID_INIT_320P 0x9100
+#define PCI_DEVICE_ID_INIT_360P 0x9500
+
+#define PCI_VENDOR_ID_TTI 0x1103
+#define PCI_DEVICE_ID_TTI_HPT343 0x0003
+
+#define PCI_VENDOR_ID_VIA 0x1106
+#define PCI_DEVICE_ID_VIA_82C505 0x0505
+#define PCI_DEVICE_ID_VIA_82C561 0x0561
+#define PCI_DEVICE_ID_VIA_82C586_1 0x0571
+#define PCI_DEVICE_ID_VIA_82C576 0x0576
+#define PCI_DEVICE_ID_VIA_82C585 0x0585
+#define PCI_DEVICE_ID_VIA_82C586_0 0x0586
+#define PCI_DEVICE_ID_VIA_82C595 0x0595
+#define PCI_DEVICE_ID_VIA_82C597_0 0x0597
+#define PCI_DEVICE_ID_VIA_82C598_0 0x0598
+#define PCI_DEVICE_ID_VIA_82C926 0x0926
+#define PCI_DEVICE_ID_VIA_82C416 0x1571
+#define PCI_DEVICE_ID_VIA_82C595_97 0x1595
+#define PCI_DEVICE_ID_VIA_82C586_2 0x3038
+#define PCI_DEVICE_ID_VIA_82C586_3 0x3040
+#define PCI_DEVICE_ID_VIA_86C100A 0x6100
+#define PCI_DEVICE_ID_VIA_82C597_1 0x8597
+#define PCI_DEVICE_ID_VIA_82C598_1 0x8598
+
+#define PCI_VENDOR_ID_SMC2 0x1113
+#define PCI_DEVICE_ID_SMC2_1211TX 0x1211
+
+#define PCI_VENDOR_ID_VORTEX 0x1119
+#define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000
+#define PCI_DEVICE_ID_VORTEX_GDT6000B 0x0001
+#define PCI_DEVICE_ID_VORTEX_GDT6x10 0x0002
+#define PCI_DEVICE_ID_VORTEX_GDT6x20 0x0003
+#define PCI_DEVICE_ID_VORTEX_GDT6530 0x0004
+#define PCI_DEVICE_ID_VORTEX_GDT6550 0x0005
+#define PCI_DEVICE_ID_VORTEX_GDT6x17 0x0006
+#define PCI_DEVICE_ID_VORTEX_GDT6x27 0x0007
+#define PCI_DEVICE_ID_VORTEX_GDT6537 0x0008
+#define PCI_DEVICE_ID_VORTEX_GDT6557 0x0009
+#define PCI_DEVICE_ID_VORTEX_GDT6x15 0x000a
+#define PCI_DEVICE_ID_VORTEX_GDT6x25 0x000b
+#define PCI_DEVICE_ID_VORTEX_GDT6535 0x000c
+#define PCI_DEVICE_ID_VORTEX_GDT6555 0x000d
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP 0x0100
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP 0x0101
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP 0x0102
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP 0x0103
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x0104
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x0105
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP1 0x0110
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP1 0x0111
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP1 0x0112
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP1 0x0113
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP1 0x0114
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP1 0x0115
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP2 0x0120
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP2 0x0121
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP2 0x0122
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP2 0x0123
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP2 0x0124
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP2 0x0125
+
+#define PCI_VENDOR_ID_EF 0x111a
+#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000
+#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002
+
+#define PCI_VENDOR_ID_FORE 0x1127
+#define PCI_DEVICE_ID_FORE_PCA200PC 0x0210
+#define PCI_DEVICE_ID_FORE_PCA200E 0x0300
+
+#define PCI_VENDOR_ID_IMAGINGTECH 0x112f
+#define PCI_DEVICE_ID_IMAGINGTECH_ICPCI 0x0000
+
+#define PCI_VENDOR_ID_PHILIPS 0x1131
+#define PCI_DEVICE_ID_PHILIPS_SAA7145 0x7145
+#define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146
+
+#define PCI_VENDOR_ID_CYCLONE 0x113c
+#define PCI_DEVICE_ID_CYCLONE_SDK 0x0001
+
+#define PCI_VENDOR_ID_ALLIANCE 0x1142
+#define PCI_DEVICE_ID_ALLIANCE_PROMOTIO 0x3210
+#define PCI_DEVICE_ID_ALLIANCE_PROVIDEO 0x6422
+#define PCI_DEVICE_ID_ALLIANCE_AT24 0x6424
+#define PCI_DEVICE_ID_ALLIANCE_AT3D 0x643d
+
+#define PCI_VENDOR_ID_SK 0x1148
+#define PCI_DEVICE_ID_SK_FP 0x4000
+#define PCI_DEVICE_ID_SK_TR 0x4200
+#define PCI_DEVICE_ID_SK_GE 0x4300
+
+#define PCI_VENDOR_ID_VMIC 0x114a
+#define PCI_DEVICE_ID_VMIC_VME 0x7587
+
+#define PCI_VENDOR_ID_DIGI 0x114f
+#define PCI_DEVICE_ID_DIGI_EPC 0x0002
+#define PCI_DEVICE_ID_DIGI_RIGHTSWITCH 0x0003
+#define PCI_DEVICE_ID_DIGI_XEM 0x0004
+#define PCI_DEVICE_ID_DIGI_XR 0x0005
+#define PCI_DEVICE_ID_DIGI_CX 0x0006
+#define PCI_DEVICE_ID_DIGI_XRJ 0x0009
+#define PCI_DEVICE_ID_DIGI_EPCJ 0x000a
+#define PCI_DEVICE_ID_DIGI_XR_920 0x0027
+
+#define PCI_VENDOR_ID_MUTECH 0x1159
+#define PCI_DEVICE_ID_MUTECH_MV1000 0x0001
+
+#define PCI_VENDOR_ID_RENDITION 0x1163
+#define PCI_DEVICE_ID_RENDITION_VERITE 0x0001
+#define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
+
+#define PCI_VENDOR_ID_TOSHIBA 0x1179
+#define PCI_DEVICE_ID_TOSHIBA_601 0x0601
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC95 0x060a
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC97 0x060f
+
+#define PCI_VENDOR_ID_RICOH 0x1180
+#define PCI_DEVICE_ID_RICOH_RL5C465 0x0465
+#define PCI_DEVICE_ID_RICOH_RL5C466 0x0466
+#define PCI_DEVICE_ID_RICOH_RL5C475 0x0475
+#define PCI_DEVICE_ID_RICOH_RL5C478 0x0478
+
+#define PCI_VENDOR_ID_ARTOP 0x1191
+#define PCI_DEVICE_ID_ARTOP_ATP8400 0x0004
+#define PCI_DEVICE_ID_ARTOP_ATP850UF 0x0005
+
+#define PCI_VENDOR_ID_ZEITNET 0x1193
+#define PCI_DEVICE_ID_ZEITNET_1221 0x0001
+#define PCI_DEVICE_ID_ZEITNET_1225 0x0002
+
+#define PCI_VENDOR_ID_OMEGA 0x119b
+#define PCI_DEVICE_ID_OMEGA_82C092G 0x1221
+
+#define PCI_VENDOR_ID_GALILEO 0x11ab
+#define PCI_DEVICE_ID_GALILEO_GT64011 0x4146
+
+#define PCI_VENDOR_ID_LITEON 0x11ad
+#define PCI_DEVICE_ID_LITEON_LNE100TX 0x0002
+
+#define PCI_VENDOR_ID_NP 0x11bc
+#define PCI_DEVICE_ID_NP_PCI_FDDI 0x0001
+
+#define PCI_VENDOR_ID_ATT 0x11c1
+#define PCI_DEVICE_ID_ATT_L56XMF 0x0440
+
+#define PCI_VENDOR_ID_SPECIALIX 0x11cb
+#define PCI_DEVICE_ID_SPECIALIX_IO8 0x2000
+#define PCI_DEVICE_ID_SPECIALIX_XIO 0x4000
+#define PCI_DEVICE_ID_SPECIALIX_RIO 0x8000
+
+#define PCI_VENDOR_ID_AURAVISION 0x11d1
+#define PCI_DEVICE_ID_AURAVISION_VXP524 0x01f7
+
+#define PCI_VENDOR_ID_IKON 0x11d5
+#define PCI_DEVICE_ID_IKON_10115 0x0115
+#define PCI_DEVICE_ID_IKON_10117 0x0117
+
+#define PCI_VENDOR_ID_ZORAN 0x11de
+#define PCI_DEVICE_ID_ZORAN_36057 0x6057
+#define PCI_DEVICE_ID_ZORAN_36120 0x6120
+
+#define PCI_VENDOR_ID_KINETIC 0x11f4
+#define PCI_DEVICE_ID_KINETIC_2915 0x2915
+
+#define PCI_VENDOR_ID_COMPEX 0x11f6
+#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112
+#define PCI_DEVICE_ID_COMPEX_RL2000 0x1401
+
+#define PCI_VENDOR_ID_RP 0x11fe
+#define PCI_DEVICE_ID_RP32INTF 0x0001
+#define PCI_DEVICE_ID_RP8INTF 0x0002
+#define PCI_DEVICE_ID_RP16INTF 0x0003
+#define PCI_DEVICE_ID_RP4QUAD 0x0004
+#define PCI_DEVICE_ID_RP8OCTA 0x0005
+#define PCI_DEVICE_ID_RP8J 0x0006
+#define PCI_DEVICE_ID_RPP4 0x000A
+#define PCI_DEVICE_ID_RPP8 0x000B
+#define PCI_DEVICE_ID_RP8M 0x000C
+
+#define PCI_VENDOR_ID_CYCLADES 0x120e
+#define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100
+#define PCI_DEVICE_ID_CYCLOM_Y_Hi 0x0101
+#define PCI_DEVICE_ID_CYCLOM_4Y_Lo 0x0102
+#define PCI_DEVICE_ID_CYCLOM_4Y_Hi 0x0103
+#define PCI_DEVICE_ID_CYCLOM_8Y_Lo 0x0104
+#define PCI_DEVICE_ID_CYCLOM_8Y_Hi 0x0105
+#define PCI_DEVICE_ID_CYCLOM_Z_Lo 0x0200
+#define PCI_DEVICE_ID_CYCLOM_Z_Hi 0x0201
+
+#define PCI_VENDOR_ID_ESSENTIAL 0x120f
+#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001
+
+#define PCI_VENDOR_ID_O2 0x1217
+#define PCI_DEVICE_ID_O2_6729 0x6729
+#define PCI_DEVICE_ID_O2_6730 0x673a
+#define PCI_DEVICE_ID_O2_6832 0x6832
+#define PCI_DEVICE_ID_O2_6836 0x6836
+
+#define PCI_VENDOR_ID_3DFX 0x121a
+#define PCI_DEVICE_ID_3DFX_VOODOO 0x0001
+#define PCI_DEVICE_ID_3DFX_VOODOO2 0x0002
+#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003
+
+#define PCI_VENDOR_ID_SIGMADES 0x1236
+#define PCI_DEVICE_ID_SIGMADES_6425 0x6401
+
+#define PCI_VENDOR_ID_CCUBE 0x123f
+
+#define PCI_VENDOR_ID_AVM 0x1244
+#define PCI_DEVICE_ID_AVM_A1 0x0a00
+
+#define PCI_VENDOR_ID_DIPIX 0x1246
+
+#define PCI_VENDOR_ID_STALLION 0x124d
+#define PCI_DEVICE_ID_STALLION_ECHPCI832 0x0000
+#define PCI_DEVICE_ID_STALLION_ECHPCI864 0x0002
+#define PCI_DEVICE_ID_STALLION_EIOPCI 0x0003
+
+#define PCI_VENDOR_ID_OPTIBASE 0x1255
+#define PCI_DEVICE_ID_OPTIBASE_FORGE 0x1110
+#define PCI_DEVICE_ID_OPTIBASE_FUSION 0x1210
+#define PCI_DEVICE_ID_OPTIBASE_VPLEX 0x2110
+#define PCI_DEVICE_ID_OPTIBASE_VPLEXCC 0x2120
+#define PCI_DEVICE_ID_OPTIBASE_VQUEST 0x2130
+
+#define PCI_VENDOR_ID_SATSAGEM 0x1267
+#define PCI_DEVICE_ID_SATSAGEM_PCR2101 0x5352
+#define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
+
+#define PCI_VENDOR_ID_HUGHES 0x1273
+#define PCI_DEVICE_ID_HUGHES_DIRECPC 0x0002
+
+#define PCI_VENDOR_ID_ENSONIQ 0x1274
+#define PCI_DEVICE_ID_ENSONIQ_AUDIOPCI 0x5000
+#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
+
+#define PCI_VENDOR_ID_ALTEON 0x12ae
+#define PCI_DEVICE_ID_ALTEON_ACENIC 0x0001
+
+#define PCI_VENDOR_ID_PICTUREL 0x12c5
+#define PCI_DEVICE_ID_PICTUREL_PCIVST 0x0081
+
+#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
+#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
+
+#define PCI_VENDOR_ID_CBOARDS 0x1307
+#define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
+
+#define PCI_VENDOR_ID_NETGEAR 0x1385
+#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a
+
+#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
+#define PCI_DEVICE_ID_SYMPHONY_101 0x0001
+
+#define PCI_VENDOR_ID_TEKRAM 0x1de1
+#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
+
+#define PCI_VENDOR_ID_3DLABS 0x3d3d
+#define PCI_DEVICE_ID_3DLABS_300SX 0x0001
+#define PCI_DEVICE_ID_3DLABS_500TX 0x0002
+#define PCI_DEVICE_ID_3DLABS_DELTA 0x0003
+#define PCI_DEVICE_ID_3DLABS_PERMEDIA 0x0004
+#define PCI_DEVICE_ID_3DLABS_MX 0x0006
+
+#define PCI_VENDOR_ID_AVANCE 0x4005
+#define PCI_DEVICE_ID_AVANCE_ALG2064 0x2064
+#define PCI_DEVICE_ID_AVANCE_2302 0x2302
+
+#define PCI_VENDOR_ID_NETVIN 0x4a14
+#define PCI_DEVICE_ID_NETVIN_NV5000SC 0x5000
+
+#define PCI_VENDOR_ID_S3 0x5333
+#define PCI_DEVICE_ID_S3_PLATO_PXS 0x0551
+#define PCI_DEVICE_ID_S3_ViRGE 0x5631
+#define PCI_DEVICE_ID_S3_TRIO 0x8811
+#define PCI_DEVICE_ID_S3_AURORA64VP 0x8812
+#define PCI_DEVICE_ID_S3_TRIO64UVP 0x8814
+#define PCI_DEVICE_ID_S3_ViRGE_VX 0x883d
+#define PCI_DEVICE_ID_S3_868 0x8880
+#define PCI_DEVICE_ID_S3_928 0x88b0
+#define PCI_DEVICE_ID_S3_864_1 0x88c0
+#define PCI_DEVICE_ID_S3_864_2 0x88c1
+#define PCI_DEVICE_ID_S3_964_1 0x88d0
+#define PCI_DEVICE_ID_S3_964_2 0x88d1
+#define PCI_DEVICE_ID_S3_968 0x88f0
+#define PCI_DEVICE_ID_S3_TRIO64V2 0x8901
+#define PCI_DEVICE_ID_S3_PLATO_PXG 0x8902
+#define PCI_DEVICE_ID_S3_ViRGE_DXGX 0x8a01
+#define PCI_DEVICE_ID_S3_ViRGE_GX2 0x8a10
+#define PCI_DEVICE_ID_S3_ViRGE_MX 0x8c01
+#define PCI_DEVICE_ID_S3_ViRGE_MXP 0x8c02
+#define PCI_DEVICE_ID_S3_ViRGE_MXPMV 0x8c03
+#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00
+
+#define PCI_VENDOR_ID_DCI 0x6666
+#define PCI_DEVICE_ID_DCI_PCCOM4 0x0001
+
+#define PCI_VENDOR_ID_GENROCO 0x5555
+#define PCI_DEVICE_ID_GENROCO_HFP832 0x0003
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_DEVICE_ID_INTEL_21145 0x0039
+#define PCI_DEVICE_ID_INTEL_82375 0x0482
+#define PCI_DEVICE_ID_INTEL_82424 0x0483
+#define PCI_DEVICE_ID_INTEL_82378 0x0484
+#define PCI_DEVICE_ID_INTEL_82430 0x0486
+#define PCI_DEVICE_ID_INTEL_82434 0x04a3
+#define PCI_DEVICE_ID_INTEL_I960 0x0960
+#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221
+#define PCI_DEVICE_ID_INTEL_82092AA_1 0x1222
+#define PCI_DEVICE_ID_INTEL_7116 0x1223
+#define PCI_DEVICE_ID_INTEL_82596 0x1226
+#define PCI_DEVICE_ID_INTEL_82865 0x1227
+#define PCI_DEVICE_ID_INTEL_82557 0x1229
+#define PCI_DEVICE_ID_INTEL_82437 0x122d
+#define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e
+#define PCI_DEVICE_ID_INTEL_82371FB_1 0x1230
+#define PCI_DEVICE_ID_INTEL_82371MX 0x1234
+#define PCI_DEVICE_ID_INTEL_82437MX 0x1235
+#define PCI_DEVICE_ID_INTEL_82441 0x1237
+#define PCI_DEVICE_ID_INTEL_82380FB 0x124b
+#define PCI_DEVICE_ID_INTEL_82439 0x1250
+#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
+#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
+#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020
+#define PCI_DEVICE_ID_INTEL_82437VX 0x7030
+#define PCI_DEVICE_ID_INTEL_82439TX 0x7100
+#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110
+#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
+#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
+#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
+#define PCI_VENDOR_ID_COMPUTONE 0x8e0e
+#define PCI_DEVICE_ID_COMPUTONE_IP2EX 0x0291
+
+#define PCI_DEVICE_ID_INTEL_82443LX_0 0x7180
+#define PCI_DEVICE_ID_INTEL_82443LX_1 0x7181
+#define PCI_DEVICE_ID_INTEL_82443BX_0 0x7190
+#define PCI_DEVICE_ID_INTEL_82443BX_1 0x7191
+#define PCI_DEVICE_ID_INTEL_82443BX_2 0x7192
+#define PCI_DEVICE_ID_INTEL_P6 0x84c4
+#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5
+#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca
+
+#define PCI_VENDOR_ID_KTI 0x8e2e
+#define PCI_DEVICE_ID_KTI_ET32P2 0x3000
+
+#define PCI_VENDOR_ID_ADAPTEC 0x9004
+#define PCI_DEVICE_ID_ADAPTEC_7810 0x1078
+#define PCI_DEVICE_ID_ADAPTEC_7821 0x2178
+#define PCI_DEVICE_ID_ADAPTEC_38602 0x3860
+#define PCI_DEVICE_ID_ADAPTEC_7850 0x5078
+#define PCI_DEVICE_ID_ADAPTEC_7855 0x5578
+#define PCI_DEVICE_ID_ADAPTEC_5800 0x5800
+#define PCI_DEVICE_ID_ADAPTEC_3860 0x6038
+#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075
+#define PCI_DEVICE_ID_ADAPTEC_7860 0x6078
+#define PCI_DEVICE_ID_ADAPTEC_7861 0x6178
+#define PCI_DEVICE_ID_ADAPTEC_7870 0x7078
+#define PCI_DEVICE_ID_ADAPTEC_7871 0x7178
+#define PCI_DEVICE_ID_ADAPTEC_7872 0x7278
+#define PCI_DEVICE_ID_ADAPTEC_7873 0x7378
+#define PCI_DEVICE_ID_ADAPTEC_7874 0x7478
+#define PCI_DEVICE_ID_ADAPTEC_7895 0x7895
+#define PCI_DEVICE_ID_ADAPTEC_7880 0x8078
+#define PCI_DEVICE_ID_ADAPTEC_7881 0x8178
+#define PCI_DEVICE_ID_ADAPTEC_7882 0x8278
+#define PCI_DEVICE_ID_ADAPTEC_7883 0x8378
+#define PCI_DEVICE_ID_ADAPTEC_7884 0x8478
+#define PCI_DEVICE_ID_ADAPTEC_7885 0x8578
+#define PCI_DEVICE_ID_ADAPTEC_7886 0x8678
+#define PCI_DEVICE_ID_ADAPTEC_7887 0x8778
+#define PCI_DEVICE_ID_ADAPTEC_7888 0x8878
+#define PCI_DEVICE_ID_ADAPTEC_1030 0x8b78
+
+#define PCI_VENDOR_ID_ADAPTEC2 0x9005
+#define PCI_DEVICE_ID_ADAPTEC2_2940U2 0x0010
+#define PCI_DEVICE_ID_ADAPTEC2_2930U2 0x0011
+#define PCI_DEVICE_ID_ADAPTEC2_7890B 0x0013
+#define PCI_DEVICE_ID_ADAPTEC2_7890 0x001f
+#define PCI_DEVICE_ID_ADAPTEC2_3940U2 0x0050
+#define PCI_DEVICE_ID_ADAPTEC2_3950U2D 0x0051
+#define PCI_DEVICE_ID_ADAPTEC2_7896 0x005f
+#define PCI_DEVICE_ID_ADAPTEC2_7892A 0x0080
+#define PCI_DEVICE_ID_ADAPTEC2_7892B 0x0081
+#define PCI_DEVICE_ID_ADAPTEC2_7892D 0x0083
+#define PCI_DEVICE_ID_ADAPTEC2_7892P 0x008f
+#define PCI_DEVICE_ID_ADAPTEC2_7899A 0x00c0
+#define PCI_DEVICE_ID_ADAPTEC2_7899B 0x00c1
+#define PCI_DEVICE_ID_ADAPTEC2_7899D 0x00c3
+#define PCI_DEVICE_ID_ADAPTEC2_7899P 0x00cf
+
+#define PCI_VENDOR_ID_ATRONICS 0x907f
+#define PCI_DEVICE_ID_ATRONICS_2015 0x2015
+
+#define PCI_VENDOR_ID_HOLTEK 0x9412
+#define PCI_DEVICE_ID_HOLTEK_6565 0x6565
+
+#define PCI_VENDOR_ID_TIGERJET 0xe159
+#define PCI_DEVICE_ID_TIGERJET_300 0x0001
+
+#define PCI_VENDOR_ID_ARK 0xedd8
+#define PCI_DEVICE_ID_ARK_STING 0xa091
+#define PCI_DEVICE_ID_ARK_STINGARK 0xa099
+#define PCI_DEVICE_ID_ARK_2000MT 0xa0a1
+
+#define PCI_VENDOR_ID_INTERPHASE 0x107e
+#define PCI_DEVICE_ID_INTERPHASE_5526 0x0004
+#define PCI_DEVICE_ID_INTERPHASE_55x6 0x0005
+
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices. The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ * 7:3 = slot
+ * 2:0 = function
+ */
+#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/config.h>
+
+/*
+ * There is one pci_dev structure for each slot-number/function-number
+ * combination:
+ */
+struct pci_dev {
+ struct pci_bus *bus; /* bus this device is on */
+ struct pci_dev *sibling; /* next device on this bus */
+ struct pci_dev *next; /* chain of all devices */
+
+ void *sysdata; /* hook for sys-specific extension */
+ struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
+
+ unsigned int devfn; /* encoded device & function index */
+ unsigned short vendor;
+ unsigned short device;
+ unsigned int class; /* 3 bytes: (base,sub,prog-if) */
+ unsigned int hdr_type; /* PCI header type */
+ unsigned int master : 1; /* set if device is master capable */
+ /*
+ * In theory, the irq level can be read from configuration
+ * space and all would be fine. However, old PCI chips don't
+ * support these registers and return 0 instead. For example,
+ * the Vision864-P rev 0 chip can uses INTA, but returns 0 in
+ * the interrupt line and pin registers. pci_init()
+ * initializes this field with the value at PCI_INTERRUPT_LINE
+ * and it is the job of pcibios_fixup() to change it if
+ * necessary. The field must not be 0 unless the device
+ * cannot generate interrupts at all.
+ */
+ unsigned int irq; /* irq generated by this device */
+
+ /* Base registers for this device, can be adjusted by
+ * pcibios_fixup() as necessary.
+ */
+ unsigned long base_address[6];
+ unsigned long rom_address;
+};
+
+struct pci_bus {
+ struct pci_bus *parent; /* parent bus this bridge is on */
+ struct pci_bus *children; /* chain of P2P bridges on this bus */
+ struct pci_bus *next; /* chain of all PCI buses */
+
+ struct pci_dev *self; /* bridge device as seen by parent */
+ struct pci_dev *devices; /* devices behind this bridge */
+
+ void *sysdata; /* hook for sys-specific extension */
+ struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
+
+ unsigned char number; /* bus number */
+ unsigned char primary; /* number of primary bridge */
+ unsigned char secondary; /* number of secondary bridge */
+ unsigned char subordinate; /* max number of subordinate buses */
+};
+
+extern struct pci_bus pci_root; /* root bus */
+extern struct pci_dev *pci_devices; /* list of all devices */
+
+/*
+ * Error values that may be returned by the PCI bios.
+ */
+#define PCIBIOS_SUCCESSFUL 0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81
+#define PCIBIOS_BAD_VENDOR_ID 0x83
+#define PCIBIOS_DEVICE_NOT_FOUND 0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER 0x87
+#define PCIBIOS_SET_FAILED 0x88
+#define PCIBIOS_BUFFER_TOO_SMALL 0x89
+
+/* Low-level architecture-dependent routines */
+
+int pcibios_present (void);
+void pcibios_init(void);
+void pcibios_fixup(void);
+void pcibios_fixup_bus(struct pci_bus *);
+char *pcibios_setup (char *str);
+int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char *val);
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned short *val);
+int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned int *val);
+int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char val);
+int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned short val);
+int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned int val);
+
+/* Don't use these in new code, use pci_find_... instead */
+
+int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn);
+int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
+ unsigned short index, unsigned char *bus,
+ unsigned char *dev_fn);
+
+/* Generic PCI interface functions */
+
+void pci_init(void);
+void pci_setup(char *str, int *ints);
+void pci_quirks_init(void);
+unsigned int pci_scan_bus(struct pci_bus *bus);
+struct pci_bus *pci_scan_peer_bridge(int bus);
+void pci_proc_init(void);
+void proc_old_pci_init(void);
+int get_pci_list(char *buf);
+int pci_proc_attach_device(struct pci_dev *dev);
+int pci_proc_detach_device(struct pci_dev *dev);
+
+struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
+struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from);
+struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
+
+#define pci_present pcibios_present
+int pci_read_config_byte(struct pci_dev *dev, u8 where, u8 *val);
+int pci_read_config_word(struct pci_dev *dev, u8 where, u16 *val);
+int pci_read_config_dword(struct pci_dev *dev, u8 where, u32 *val);
+int pci_write_config_byte(struct pci_dev *dev, u8 where, u8 val);
+int pci_write_config_word(struct pci_dev *dev, u8 where, u16 val);
+int pci_write_config_dword(struct pci_dev *dev, u8 where, u32 val);
+void pci_set_master(struct pci_dev *dev);
+
+#ifndef CONFIG_PCI
+/* If the system does not have PCI, clearly these return errors. Define
+ these as simple inline functions to avoid hair in drivers. */
+extern inline int pcibios_present(void) { return 0; }
+
+#define _PCI_NOP(o,s,t) \
+ extern inline int pcibios_##o##_config_##s## (u8 bus, u8 dfn, u8 where, t val) \
+ { return PCIBIOS_FUNC_NOT_SUPPORTED; } \
+ extern inline int pci_##o##_config_##s## (struct pci_dev *dev, u8 where, t val) \
+ { return PCIBIOS_FUNC_NOT_SUPPORTED; }
+#define _PCI_NOP_ALL(o,x) _PCI_NOP(o,byte,u8 x) \
+ _PCI_NOP(o,word,u16 x) \
+ _PCI_NOP(o,dword,u32 x)
+_PCI_NOP_ALL(read, *)
+_PCI_NOP_ALL(write,)
+
+extern inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
+{ return NULL; }
+
+extern inline struct pci_dev *pci_find_class(unsigned int class, struct pci_dev *from)
+{ return NULL; }
+
+extern inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
+{ return NULL; }
+
+#endif /* !CONFIG_PCI */
+
+#endif /* __KERNEL__ */
+#endif /* LINUX_PCI_H */
diff --git a/pfinet/linux-src/include/linux/personality.h b/pfinet/linux-src/include/linux/personality.h
new file mode 100644
index 00000000..a927b9e7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/personality.h
@@ -0,0 +1,57 @@
+#ifndef _PERSONALITY_H
+#define _PERSONALITY_H
+
+#include <linux/linkage.h>
+#include <linux/ptrace.h>
+
+
+/* Flags for bug emulation. These occupy the top three bytes. */
+#define STICKY_TIMEOUTS 0x4000000
+#define WHOLE_SECONDS 0x2000000
+#define ADDR_LIMIT_32BIT 0x0800000
+
+/* Personality types. These go in the low byte. Avoid using the top bit,
+ * it will conflict with error returns.
+ */
+#define PER_MASK (0x00ff)
+#define PER_LINUX (0x0000)
+#define PER_LINUX_32BIT (0x0000 | ADDR_LIMIT_32BIT)
+#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS)
+#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS)
+#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
+#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS)
+#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS)
+#define PER_BSD (0x0006)
+#define PER_XENIX (0x0007 | STICKY_TIMEOUTS)
+#define PER_LINUX32 (0x0008)
+#define PER_IRIX32 (0x0009 | STICKY_TIMEOUTS) /* IRIX5 32-bit */
+#define PER_IRIXN32 (0x000a | STICKY_TIMEOUTS) /* IRIX6 new 32-bit */
+#define PER_IRIX64 (0x000b | STICKY_TIMEOUTS) /* IRIX6 64-bit */
+
+/* Prototype for an lcall7 syscall handler. */
+typedef void (*lcall7_func)(struct pt_regs *);
+
+
+/* Description of an execution domain - personality range supported,
+ * lcall7 syscall handler, start up / shut down functions etc.
+ * N.B. The name and lcall7 handler must be where they are since the
+ * offset of the handler is hard coded in kernel/sys_call.S.
+ */
+struct exec_domain {
+ const char *name;
+ lcall7_func handler;
+ unsigned char pers_low, pers_high;
+ unsigned long * signal_map;
+ unsigned long * signal_invmap;
+ struct module * module;
+ struct exec_domain *next;
+};
+
+extern struct exec_domain default_exec_domain;
+
+extern struct exec_domain *lookup_exec_domain(unsigned long personality);
+extern int register_exec_domain(struct exec_domain *it);
+extern int unregister_exec_domain(struct exec_domain *it);
+asmlinkage int sys_personality(unsigned long personality);
+
+#endif /* _PERSONALITY_H */
diff --git a/pfinet/linux-src/include/linux/pg.h b/pfinet/linux-src/include/linux/pg.h
new file mode 100644
index 00000000..c752a97c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/pg.h
@@ -0,0 +1,63 @@
+/* pg.h (c) 1998 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license
+
+
+ pg.h defines the user interface to the generic ATAPI packet
+ command driver for parallel port ATAPI devices (pg). The
+ driver is loosely modelled after the generic SCSI driver, sg,
+ although the actual interface is different.
+
+ The pg driver provides a simple character device interface for
+ sending ATAPI commands to a device. With the exception of the
+ ATAPI reset operation, all operations are performed by a pair
+ of read and write operations to the appropriate /dev/pgN device.
+ A write operation delivers a command and any outbound data in
+ a single buffer. Normally, the write will succeed unless the
+ device is offline or malfunctioning, or there is already another
+ command pending. If the write succeeds, it should be followed
+ immediately by a read operation, to obtain any returned data and
+ status information. A read will fail if there is no operation
+ in progress.
+
+ As a special case, the device can be reset with a write operation,
+ and in this case, no following read is expected, or permitted.
+
+ There are no ioctl() operations. Any single operation
+ may transfer at most PG_MAX_DATA bytes. Note that the driver must
+ copy the data through an internal buffer. In keeping with all
+ current ATAPI devices, command packets are assumed to be exactly
+ 12 bytes in length.
+
+ To permit future changes to this interface, the headers in the
+ read and write buffers contain a single character "magic" flag.
+ Currently this flag must be the character "P".
+
+*/
+
+#define PG_MAGIC 'P'
+#define PG_RESET 'Z'
+#define PG_COMMAND 'C'
+
+#define PG_MAX_DATA 32768
+
+struct pg_write_hdr {
+
+ char magic; /* == PG_MAGIC */
+ char func; /* PG_RESET or PG_COMMAND */
+ int dlen; /* number of bytes expected to transfer */
+ int timeout; /* number of seconds before timeout */
+ char packet[12]; /* packet command */
+
+};
+
+struct pg_read_hdr {
+
+ char magic; /* == PG_MAGIC */
+ char scsi; /* "scsi" status == sense key */
+ int dlen; /* size of device transfer request */
+ int duration; /* time in seconds command took */
+ char pad[12]; /* not used */
+
+};
+
+/* end of pg.h */
diff --git a/pfinet/linux-src/include/linux/pipe_fs_i.h b/pfinet/linux-src/include/linux/pipe_fs_i.h
new file mode 100644
index 00000000..3a847d72
--- /dev/null
+++ b/pfinet/linux-src/include/linux/pipe_fs_i.h
@@ -0,0 +1,34 @@
+#ifndef _LINUX_PIPE_FS_I_H
+#define _LINUX_PIPE_FS_I_H
+
+struct pipe_inode_info {
+ struct wait_queue * wait;
+ char * base;
+ unsigned int start;
+ unsigned int lock;
+ unsigned int rd_openers;
+ unsigned int wr_openers;
+ unsigned int readers;
+ unsigned int writers;
+};
+
+#define PIPE_WAIT(inode) ((inode).u.pipe_i.wait)
+#define PIPE_BASE(inode) ((inode).u.pipe_i.base)
+#define PIPE_START(inode) ((inode).u.pipe_i.start)
+#define PIPE_LEN(inode) ((inode).i_size)
+#define PIPE_RD_OPENERS(inode) ((inode).u.pipe_i.rd_openers)
+#define PIPE_WR_OPENERS(inode) ((inode).u.pipe_i.wr_openers)
+#define PIPE_READERS(inode) ((inode).u.pipe_i.readers)
+#define PIPE_WRITERS(inode) ((inode).u.pipe_i.writers)
+#define PIPE_LOCK(inode) ((inode).u.pipe_i.lock)
+#define PIPE_SIZE(inode) PIPE_LEN(inode)
+
+#define PIPE_EMPTY(inode) (PIPE_SIZE(inode)==0)
+#define PIPE_FULL(inode) (PIPE_SIZE(inode)==PIPE_BUF)
+#define PIPE_FREE(inode) (PIPE_BUF - PIPE_LEN(inode))
+#define PIPE_END(inode) ((PIPE_START(inode)+PIPE_LEN(inode))&\
+ (PIPE_BUF-1))
+#define PIPE_MAX_RCHUNK(inode) (PIPE_BUF - PIPE_START(inode))
+#define PIPE_MAX_WCHUNK(inode) (PIPE_BUF - PIPE_END(inode))
+
+#endif
diff --git a/pfinet/linux-src/include/linux/pkt_cls.h b/pfinet/linux-src/include/linux/pkt_cls.h
new file mode 100644
index 00000000..36935ed3
--- /dev/null
+++ b/pfinet/linux-src/include/linux/pkt_cls.h
@@ -0,0 +1,146 @@
+#ifndef __LINUX_PKT_CLS_H
+#define __LINUX_PKT_CLS_H
+
+struct tc_police
+{
+ __u32 index;
+ int action;
+#define TC_POLICE_UNSPEC (-1)
+#define TC_POLICE_OK 0
+#define TC_POLICE_RECLASSIFY 1
+#define TC_POLICE_SHOT 2
+
+ __u32 limit;
+ __u32 burst;
+ __u32 mtu;
+ struct tc_ratespec rate;
+ struct tc_ratespec peakrate;
+};
+
+enum
+{
+ TCA_POLICE_UNSPEC,
+ TCA_POLICE_TBF,
+ TCA_POLICE_RATE,
+ TCA_POLICE_PEAKRATE,
+ TCA_POLICE_AVRATE,
+ TCA_POLICE_RESULT
+#define TCA_POLICE_RESULT TCA_POLICE_RESULT
+};
+
+#define TCA_POLICE_MAX TCA_POLICE_RESULT
+
+/* U32 filters */
+
+#define TC_U32_HTID(h) ((h)&0xFFF00000)
+#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20)
+#define TC_U32_HASH(h) (((h)>>12)&0xFF)
+#define TC_U32_NODE(h) ((h)&0xFFF)
+#define TC_U32_KEY(h) ((h)&0xFFFFF)
+#define TC_U32_UNSPEC 0
+#define TC_U32_ROOT (0xFFF00000)
+
+enum
+{
+ TCA_U32_UNSPEC,
+ TCA_U32_CLASSID,
+ TCA_U32_HASH,
+ TCA_U32_LINK,
+ TCA_U32_DIVISOR,
+ TCA_U32_SEL,
+ TCA_U32_POLICE,
+};
+
+#define TCA_U32_MAX TCA_U32_POLICE
+
+struct tc_u32_key
+{
+ __u32 mask;
+ __u32 val;
+ int off;
+ int offmask;
+};
+
+struct tc_u32_sel
+{
+ unsigned char flags;
+ unsigned char offshift;
+ unsigned char nkeys;
+
+ __u16 offmask;
+ __u16 off;
+ short offoff;
+
+ short hoff;
+ __u32 hmask;
+
+ struct tc_u32_key keys[0];
+};
+
+/* Flags */
+
+#define TC_U32_TERMINAL 1
+#define TC_U32_OFFSET 2
+#define TC_U32_VAROFFSET 4
+#define TC_U32_EAT 8
+
+#define TC_U32_MAXDEPTH 8
+
+
+/* RSVP filter */
+
+enum
+{
+ TCA_RSVP_UNSPEC,
+ TCA_RSVP_CLASSID,
+ TCA_RSVP_DST,
+ TCA_RSVP_SRC,
+ TCA_RSVP_PINFO,
+ TCA_RSVP_POLICE,
+};
+
+#define TCA_RSVP_MAX TCA_RSVP_POLICE
+
+struct tc_rsvp_gpi
+{
+ __u32 key;
+ __u32 mask;
+ int offset;
+};
+
+struct tc_rsvp_pinfo
+{
+ struct tc_rsvp_gpi dpi;
+ struct tc_rsvp_gpi spi;
+ __u8 protocol;
+ __u8 tunnelid;
+ __u8 tunnelhdr;
+};
+
+/* ROUTE filter */
+
+enum
+{
+ TCA_ROUTE4_UNSPEC,
+ TCA_ROUTE4_CLASSID,
+ TCA_ROUTE4_TO,
+ TCA_ROUTE4_FROM,
+ TCA_ROUTE4_IIF,
+ TCA_ROUTE4_POLICE,
+};
+
+#define TCA_ROUTE4_MAX TCA_ROUTE4_POLICE
+
+
+/* FW filter */
+
+enum
+{
+ TCA_FW_UNSPEC,
+ TCA_FW_CLASSID,
+ TCA_FW_POLICE,
+};
+
+#define TCA_FW_MAX TCA_FW_POLICE
+
+#endif
diff --git a/pfinet/linux-src/include/linux/pkt_sched.h b/pfinet/linux-src/include/linux/pkt_sched.h
new file mode 100644
index 00000000..4ec170db
--- /dev/null
+++ b/pfinet/linux-src/include/linux/pkt_sched.h
@@ -0,0 +1,277 @@
+#ifndef __LINUX_PKT_SCHED_H
+#define __LINUX_PKT_SCHED_H
+
+/* Logical priority bands not depending on specific packet scheduler.
+ Every scheduler will map them to real traffic classes, if it has
+ no more precise mechanism to classify packets.
+
+ These numbers have no special meaning, though their coincidence
+ with obsolete IPv6 values is not occasional :-). New IPv6 drafts
+ preferred full anarchy inspired by diffserv group.
+
+ Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
+ class, actually, as rule it will be handled with more care than
+ filler or even bulk.
+ */
+
+#define TC_PRIO_BESTEFFORT 0
+#define TC_PRIO_FILLER 1
+#define TC_PRIO_BULK 2
+#define TC_PRIO_INTERACTIVE_BULK 4
+#define TC_PRIO_INTERACTIVE 6
+#define TC_PRIO_CONTROL 7
+
+#define TC_PRIO_MAX 15
+
+/* Generic queue statistics, available for all the elements.
+ Particular schedulers may have also their private records.
+ */
+
+struct tc_stats
+{
+ __u64 bytes; /* NUmber of enqueues bytes */
+ __u32 packets; /* Number of enqueued packets */
+ __u32 drops; /* Packets dropped because of lack of resources */
+ __u32 overlimits; /* Number of throttle events when this
+ * flow goes out of allocated bandwidth */
+ __u32 bps; /* Current flow byte rate */
+ __u32 pps; /* Current flow packet rate */
+ __u32 qlen;
+ __u32 backlog;
+};
+
+struct tc_estimator
+{
+ char interval;
+ unsigned char ewma_log;
+};
+
+/* "Handles"
+ ---------
+
+ All the traffic control objects have 32bit identifiers, or "handles".
+
+ They can be considered as opaque numbers from user API viewpoint,
+ but actually they always consist of two fields: major and
+ minor numbers, which are interpreted by kernel specially,
+ that may be used by applications, though not recommended.
+
+ F.e. qdisc handles always have minor number equal to zero,
+ classes (or flows) have major equal to parent qdisc major, and
+ minor uniquely identifying class inside qdisc.
+
+ Macros to manipulate handles:
+ */
+
+#define TC_H_MAJ_MASK (0xFFFF0000U)
+#define TC_H_MIN_MASK (0x0000FFFFU)
+#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
+#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
+#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
+
+#define TC_H_UNSPEC (0U)
+#define TC_H_ROOT (0xFFFFFFFFU)
+
+struct tc_ratespec
+{
+ unsigned char cell_log;
+ unsigned char __reserved;
+ unsigned short feature;
+ short addend;
+ unsigned short mpu;
+ __u32 rate;
+};
+
+/* FIFO section */
+
+struct tc_fifo_qopt
+{
+ __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */
+};
+
+/* PRIO section */
+
+#define TCQ_PRIO_BANDS 16
+
+struct tc_prio_qopt
+{
+ int bands; /* Number of bands */
+ __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
+};
+
+/* CSZ section */
+
+struct tc_csz_qopt
+{
+ int flows; /* Maximal number of guaranteed flows */
+ unsigned char R_log; /* Fixed point position for round number */
+ unsigned char delta_log; /* Log of maximal managed time interval */
+ __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> CSZ band */
+};
+
+struct tc_csz_copt
+{
+ struct tc_ratespec slice;
+ struct tc_ratespec rate;
+ struct tc_ratespec peakrate;
+ __u32 limit;
+ __u32 buffer;
+ __u32 mtu;
+};
+
+enum
+{
+ TCA_CSZ_UNSPEC,
+ TCA_CSZ_PARMS,
+ TCA_CSZ_RTAB,
+ TCA_CSZ_PTAB,
+};
+
+/* TBF section */
+
+struct tc_tbf_qopt
+{
+ struct tc_ratespec rate;
+ struct tc_ratespec peakrate;
+ __u32 limit;
+ __u32 buffer;
+ __u32 mtu;
+};
+
+enum
+{
+ TCA_TBF_UNSPEC,
+ TCA_TBF_PARMS,
+ TCA_TBF_RTAB,
+ TCA_TBF_PTAB,
+};
+
+
+/* TEQL section */
+
+/* TEQL does not require any parameters */
+
+/* SFQ section */
+
+struct tc_sfq_qopt
+{
+ unsigned quantum; /* Bytes per round allocated to flow */
+ int perturb_period; /* Period of hash perturbation */
+ __u32 limit; /* Maximal packets in queue */
+ unsigned divisor; /* Hash divisor */
+ unsigned flows; /* Maximal number of flows */
+};
+
+/*
+ * NOTE: limit, divisor and flows are hardwired to code at the moment.
+ *
+ * limit=flows=128, divisor=1024;
+ *
+ * The only reason for this is efficiency, it is possible
+ * to change these parameters in compile time.
+ */
+
+/* RED section */
+
+enum
+{
+ TCA_RED_UNSPEC,
+ TCA_RED_PARMS,
+ TCA_RED_STAB,
+};
+
+struct tc_red_qopt
+{
+ __u32 limit; /* HARD maximal queue length (bytes) */
+ __u32 qth_min; /* Min average length threshold (bytes) */
+ __u32 qth_max; /* Max average length threshold (bytes) */
+ unsigned char Wlog; /* log(W) */
+ unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
+ unsigned char Scell_log; /* cell size for idle damping */
+};
+
+/* CBQ section */
+
+#define TC_CBQ_MAXPRIO 8
+#define TC_CBQ_MAXLEVEL 8
+#define TC_CBQ_DEF_EWMA 5
+
+struct tc_cbq_lssopt
+{
+ unsigned char change;
+ unsigned char flags;
+#define TCF_CBQ_LSS_BOUNDED 1
+#define TCF_CBQ_LSS_ISOLATED 2
+ unsigned char ewma_log;
+ unsigned char level;
+#define TCF_CBQ_LSS_FLAGS 1
+#define TCF_CBQ_LSS_EWMA 2
+#define TCF_CBQ_LSS_MAXIDLE 4
+#define TCF_CBQ_LSS_MINIDLE 8
+#define TCF_CBQ_LSS_OFFTIME 0x10
+#define TCF_CBQ_LSS_AVPKT 0x20
+ __u32 maxidle;
+ __u32 minidle;
+ __u32 offtime;
+ __u32 avpkt;
+};
+
+struct tc_cbq_wrropt
+{
+ unsigned char flags;
+ unsigned char priority;
+ unsigned char cpriority;
+ unsigned char __reserved;
+ __u32 allot;
+ __u32 weight;
+};
+
+struct tc_cbq_ovl
+{
+ unsigned char strategy;
+#define TC_CBQ_OVL_CLASSIC 0
+#define TC_CBQ_OVL_DELAY 1
+#define TC_CBQ_OVL_LOWPRIO 2
+#define TC_CBQ_OVL_DROP 3
+#define TC_CBQ_OVL_RCLASSIC 4
+ unsigned char priority2;
+ __u32 penalty;
+};
+
+struct tc_cbq_police
+{
+ unsigned char police;
+ unsigned char __res1;
+ unsigned short __res2;
+};
+
+struct tc_cbq_fopt
+{
+ __u32 split;
+ __u32 defmap;
+ __u32 defchange;
+};
+
+struct tc_cbq_xstats
+{
+ __u32 borrows;
+ __u32 overactions;
+ __s32 avgidle;
+ __s32 undertime;
+};
+
+enum
+{
+ TCA_CBQ_UNSPEC,
+ TCA_CBQ_LSSOPT,
+ TCA_CBQ_WRROPT,
+ TCA_CBQ_FOPT,
+ TCA_CBQ_OVL_STRATEGY,
+ TCA_CBQ_RATE,
+ TCA_CBQ_RTAB,
+ TCA_CBQ_POLICE,
+};
+
+#define TCA_CBQ_MAX TCA_CBQ_POLICE
+
+#endif
diff --git a/pfinet/linux-src/include/linux/poll.h b/pfinet/linux-src/include/linux/poll.h
new file mode 100644
index 00000000..972c0cb0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/poll.h
@@ -0,0 +1,107 @@
+#ifndef _LINUX_POLL_H
+#define _LINUX_POLL_H
+
+#include <asm/poll.h>
+
+#ifdef __KERNEL__
+
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+
+
+struct poll_table_entry {
+ struct file * filp;
+ struct wait_queue wait;
+ struct wait_queue ** wait_address;
+};
+
+typedef struct poll_table_struct {
+ struct poll_table_struct * next;
+ unsigned int nr;
+ struct poll_table_entry * entry;
+} poll_table;
+
+#define __MAX_POLL_TABLE_ENTRIES ((PAGE_SIZE - sizeof (poll_table)) / sizeof (struct poll_table_entry))
+
+extern void __pollwait(struct file * filp, struct wait_queue ** wait_address, poll_table *p);
+
+extern inline void poll_wait(struct file * filp, struct wait_queue ** wait_address, poll_table *p)
+{
+ if (p && wait_address)
+ __pollwait(filp, wait_address, p);
+}
+
+/*
+ * For the kernel fd_set we use a fixed set-size for allocation purposes.
+ * This set-size doesn't necessarily bear any relation to the size the user
+ * uses, but should preferably obviously be larger than any possible user
+ * size (NR_OPEN bits).
+ *
+ * We need 6 bitmaps (in/out/ex for both incoming and outgoing), and we
+ * allocate one page for all the bitmaps. Thus we have 8*PAGE_SIZE bits,
+ * to be divided by 6. And we'd better make sure we round to a full
+ * long-word (in fact, we'll round to 64 bytes).
+ */
+
+
+#define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64)
+#define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8)
+typedef unsigned long kernel_fd_set[KFDS_NR/__NFDBITS];
+
+/*
+ * Scaleable version of the fd_set.
+ */
+
+typedef struct {
+ unsigned long *in, *out, *ex;
+ unsigned long *res_in, *res_out, *res_ex;
+} fd_set_bits;
+
+#define FDS_BITPERLONG (8*sizeof(long))
+#define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)
+#define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long))
+
+/*
+ * We do a VERIFY_WRITE here even though we are only reading this time:
+ * we'll write to it eventually..
+ *
+ * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.
+ */
+static inline
+int get_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
+{
+ nr = FDS_BYTES(nr);
+ if (ufdset) {
+ int error;
+ error = verify_area(VERIFY_WRITE, ufdset, nr);
+ if (!error && __copy_from_user(fdset, ufdset, nr))
+ error = -EFAULT;
+ return error;
+ }
+ memset(fdset, 0, nr);
+ return 0;
+}
+
+static inline
+void set_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
+{
+ if (ufdset) {
+ nr = FDS_BYTES(nr);
+ __copy_to_user(ufdset, fdset, nr);
+ }
+}
+
+static inline
+void zero_fd_set(unsigned long nr, unsigned long *fdset)
+{
+ nr = FDS_BYTES(nr);
+ memset(fdset, 0, nr);
+}
+
+extern int do_select(int n, fd_set_bits *fds, long *timeout);
+
+#endif /* KERNEL */
+
+#endif /* _LINUX_POLL_H */
diff --git a/pfinet/linux-src/include/linux/posix_types.h b/pfinet/linux-src/include/linux/posix_types.h
new file mode 100644
index 00000000..338160e4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/posix_types.h
@@ -0,0 +1,56 @@
+#ifndef _LINUX_POSIX_TYPES_H
+#define _LINUX_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+#ifndef NULL
+# define NULL ((void *) 0)
+#endif
+
+/*
+ * This allows for 1024 file descriptors: if NR_OPEN is ever grown
+ * beyond that you'll have to change this too. But 1024 fd's seem to be
+ * enough even for such "real" unices like OSF/1, so hopefully this is
+ * one limit that doesn't have to be changed [again].
+ *
+ * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
+ * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
+ * place for them. Solved by having dummy defines in <sys/time.h>.
+ */
+
+/*
+ * Those macros may have been defined in <gnu/types.h>. But we always
+ * use the ones here.
+ */
+#undef __NFDBITS
+#define __NFDBITS (8 * sizeof(unsigned long))
+
+#undef __FD_SETSIZE
+#define __FD_SETSIZE 1024
+
+#undef __FDSET_LONGS
+#define __FDSET_LONGS (__FD_SETSIZE/__NFDBITS)
+
+#undef __FDELT
+#define __FDELT(d) ((d) / __NFDBITS)
+
+#undef __FDMASK
+#define __FDMASK(d) (1UL << ((d) % __NFDBITS))
+
+typedef struct {
+ unsigned long fds_bits [__FDSET_LONGS];
+} __kernel_fd_set;
+
+/* Type of a signal handler. */
+typedef void (*__kernel_sighandler_t)(int);
+
+/* Type of a SYSV IPC key. */
+typedef int __kernel_key_t;
+
+#include <asm/posix_types.h>
+
+#endif /* _LINUX_POSIX_TYPES_H */
diff --git a/pfinet/linux-src/include/linux/ppp-comp.h b/pfinet/linux-src/include/linux/ppp-comp.h
new file mode 100644
index 00000000..3a5d5865
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ppp-comp.h
@@ -0,0 +1,198 @@
+/*
+ * ppp-comp.h - Definitions for doing PPP packet compression.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: ppp-comp.h,v 1.6 1997/11/27 06:04:44 paulus Exp $
+ */
+
+/*
+ * ==FILEVERSION 980319==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, please set the above date.
+ * ppp-comp.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new ppp-comp.h
+ * file. Don't change the format of that line otherwise, so the
+ * installation script can recognize it.
+ */
+
+#ifndef _NET_PPP_COMP_H
+#define _NET_PPP_COMP_H
+
+/*
+ * The following symbols control whether we include code for
+ * various compression methods.
+ */
+
+#ifndef DO_BSD_COMPRESS
+#define DO_BSD_COMPRESS 1 /* by default, include BSD-Compress */
+#endif
+#ifndef DO_DEFLATE
+#define DO_DEFLATE 1 /* by default, include Deflate */
+#endif
+#define DO_PREDICTOR_1 0
+#define DO_PREDICTOR_2 0
+
+/*
+ * Structure giving methods for compression/decompression.
+ */
+
+struct compressor {
+ int compress_proto; /* CCP compression protocol number */
+
+ /* Allocate space for a compressor (transmit side) */
+ void *(*comp_alloc) (unsigned char *options, int opt_len);
+
+ /* Free space used by a compressor */
+ void (*comp_free) (void *state);
+
+ /* Initialize a compressor */
+ int (*comp_init) (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int debug);
+
+ /* Reset a compressor */
+ void (*comp_reset) (void *state);
+
+ /* Compress a packet */
+ int (*compress) (void *state, unsigned char *rptr,
+ unsigned char *obuf, int isize, int osize);
+
+ /* Return compression statistics */
+ void (*comp_stat) (void *state, struct compstat *stats);
+
+ /* Allocate space for a decompressor (receive side) */
+ void *(*decomp_alloc) (unsigned char *options, int opt_len);
+
+ /* Free space used by a decompressor */
+ void (*decomp_free) (void *state);
+
+ /* Initialize a decompressor */
+ int (*decomp_init) (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int mru,
+ int debug);
+
+ /* Reset a decompressor */
+ void (*decomp_reset) (void *state);
+
+ /* Decompress a packet. */
+ int (*decompress) (void *state, unsigned char *ibuf, int isize,
+ unsigned char *obuf, int osize);
+
+ /* Update state for an incompressible packet received */
+ void (*incomp) (void *state, unsigned char *ibuf, int icnt);
+
+ /* Return decompression statistics */
+ void (*decomp_stat) (void *state, struct compstat *stats);
+};
+
+/*
+ * The return value from decompress routine is the length of the
+ * decompressed packet if successful, otherwise DECOMP_ERROR
+ * or DECOMP_FATALERROR if an error occurred.
+ *
+ * We need to make this distinction so that we can disable certain
+ * useful functionality, namely sending a CCP reset-request as a result
+ * of an error detected after decompression. This is to avoid infringing
+ * a patent held by Motorola.
+ * Don't you just lurve software patents.
+ */
+
+#define DECOMP_ERROR -1 /* error detected before decomp. */
+#define DECOMP_FATALERROR -2 /* error detected after decomp. */
+
+/*
+ * CCP codes.
+ */
+
+#define CCP_CONFREQ 1
+#define CCP_CONFACK 2
+#define CCP_TERMREQ 5
+#define CCP_TERMACK 6
+#define CCP_RESETREQ 14
+#define CCP_RESETACK 15
+
+/*
+ * Max # bytes for a CCP option
+ */
+
+#define CCP_MAX_OPTION_LENGTH 32
+
+/*
+ * Parts of a CCP packet.
+ */
+
+#define CCP_CODE(dp) ((dp)[0])
+#define CCP_ID(dp) ((dp)[1])
+#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3])
+#define CCP_HDRLEN 4
+
+#define CCP_OPT_CODE(dp) ((dp)[0])
+#define CCP_OPT_LENGTH(dp) ((dp)[1])
+#define CCP_OPT_MINLEN 2
+
+/*
+ * Definitions for BSD-Compress.
+ */
+
+#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */
+#define CILEN_BSD_COMPRESS 3 /* length of config. option */
+
+/* Macros for handling the 3rd byte of the BSD-Compress config option. */
+#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */
+#define BSD_VERSION(x) ((x) >> 5) /* version of option format */
+#define BSD_CURRENT_VERSION 1 /* current version number */
+#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n))
+
+#define BSD_MIN_BITS 9 /* smallest code size supported */
+#define BSD_MAX_BITS 15 /* largest code size supported */
+
+/*
+ * Definitions for Deflate.
+ */
+
+#define CI_DEFLATE 26 /* config option for Deflate */
+#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */
+#define CILEN_DEFLATE 4 /* length of its config option */
+
+#define DEFLATE_MIN_SIZE 8
+#define DEFLATE_MAX_SIZE 15
+#define DEFLATE_METHOD_VAL 8
+#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE)
+#define DEFLATE_METHOD(x) ((x) & 0x0F)
+#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \
+ + DEFLATE_METHOD_VAL)
+#define DEFLATE_CHK_SEQUENCE 0
+
+/*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+
+#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */
+#define CILEN_PREDICTOR_1 2 /* length of its config option */
+#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */
+#define CILEN_PREDICTOR_2 2 /* length of its config option */
+
+#endif /* _NET_PPP_COMP_H */
diff --git a/pfinet/linux-src/include/linux/ppp.h b/pfinet/linux-src/include/linux/ppp.h
new file mode 100644
index 00000000..233f961e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ppp.h
@@ -0,0 +1,4 @@
+/*
+ * Back compatibility for a while.
+ */
+#include <linux/if_ppp.h>
diff --git a/pfinet/linux-src/include/linux/ppp_defs.h b/pfinet/linux-src/include/linux/ppp_defs.h
new file mode 100644
index 00000000..c506c90a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ppp_defs.h
@@ -0,0 +1,182 @@
+/* $Id: ppp_defs.h,v 1.2 1994/09/21 01:31:06 paulus Exp $ */
+
+/*
+ * ppp_defs.h - PPP definitions.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+/*
+ * ==FILEVERSION 990114==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, please set the above date.
+ * ppp_defs.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new ppp_defs.h
+ * file. Don't change the format of that line otherwise, so the
+ * installation script can recognize it.
+ */
+
+#ifndef _PPP_DEFS_H_
+#define _PPP_DEFS_H_
+
+/*
+ * The basic PPP frame.
+ */
+#define PPP_HDRLEN 4 /* octets for standard ppp header */
+#define PPP_FCSLEN 2 /* octets for FCS */
+#define PPP_MRU 1500 /* default MRU = max length of info field */
+
+#define PPP_ADDRESS(p) (((__u8 *)(p))[0])
+#define PPP_CONTROL(p) (((__u8 *)(p))[1])
+#define PPP_PROTOCOL(p) ((((__u8 *)(p))[2] << 8) + ((__u8 *)(p))[3])
+
+/*
+ * Significant octet values.
+ */
+#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
+#define PPP_UI 0x03 /* Unnumbered Information */
+#define PPP_FLAG 0x7e /* Flag Sequence */
+#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */
+#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */
+
+/*
+ * Protocol field values.
+ */
+#define PPP_IP 0x21 /* Internet Protocol */
+#define PPP_AT 0x29 /* AppleTalk Protocol */
+#define PPP_IPX 0x2b /* IPX protocol */
+#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
+#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
+#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */
+#define PPP_COMP 0xfd /* compressed packet */
+#define PPP_IPCP 0x8021 /* IP Control Protocol */
+#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
+#define PPP_IPXCP 0x802b /* IPX Control Protocol */
+#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
+#define PPP_CCP 0x80fd /* Compression Control Protocol */
+#define PPP_LCP 0xc021 /* Link Control Protocol */
+#define PPP_PAP 0xc023 /* Password Authentication Protocol */
+#define PPP_LQR 0xc025 /* Link Quality Report protocol */
+#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
+#define PPP_CBCP 0xc029 /* Callback Control Protocol */
+
+/*
+ * Values for FCS calculations.
+ */
+
+#define PPP_INITFCS 0xffff /* Initial FCS value */
+#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
+#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
+
+/*
+ * Extended asyncmap - allows any character to be escaped.
+ */
+
+typedef __u32 ext_accm[8];
+
+/*
+ * What to do with network protocol (NP) packets.
+ */
+enum NPmode {
+ NPMODE_PASS, /* pass the packet through */
+ NPMODE_DROP, /* silently drop the packet */
+ NPMODE_ERROR, /* return an error */
+ NPMODE_QUEUE /* save it up for later. */
+};
+
+/*
+ * Statistics for LQRP and pppstats
+ */
+struct pppstat {
+ __u32 ppp_discards; /* # frames discarded */
+
+ __u32 ppp_ibytes; /* bytes received */
+ __u32 ppp_ioctects; /* bytes received not in error */
+ __u32 ppp_ipackets; /* packets received */
+ __u32 ppp_ierrors; /* receive errors */
+ __u32 ppp_ilqrs; /* # LQR frames received */
+
+ __u32 ppp_obytes; /* raw bytes sent */
+ __u32 ppp_ooctects; /* frame bytes sent */
+ __u32 ppp_opackets; /* packets sent */
+ __u32 ppp_oerrors; /* transmit errors */
+ __u32 ppp_olqrs; /* # LQR frames sent */
+};
+
+struct vjstat {
+ __u32 vjs_packets; /* outbound packets */
+ __u32 vjs_compressed; /* outbound compressed packets */
+ __u32 vjs_searches; /* searches for connection state */
+ __u32 vjs_misses; /* times couldn't find conn. state */
+ __u32 vjs_uncompressedin; /* inbound uncompressed packets */
+ __u32 vjs_compressedin; /* inbound compressed packets */
+ __u32 vjs_errorin; /* inbound unknown type packets */
+ __u32 vjs_tossed; /* inbound packets tossed because of error */
+};
+
+struct compstat {
+ __u32 unc_bytes; /* total uncompressed bytes */
+ __u32 unc_packets; /* total uncompressed packets */
+ __u32 comp_bytes; /* compressed bytes */
+ __u32 comp_packets; /* compressed packets */
+ __u32 inc_bytes; /* incompressible bytes */
+ __u32 inc_packets; /* incompressible packets */
+
+ /* the compression ratio is defined as in_count / bytes_out */
+ __u32 in_count; /* Bytes received */
+ __u32 bytes_out; /* Bytes transmitted */
+
+ double ratio; /* not computed in kernel. */
+};
+
+struct ppp_stats {
+ struct pppstat p; /* basic PPP statistics */
+ struct vjstat vj; /* VJ header compression statistics */
+};
+
+struct ppp_comp_stats {
+ struct compstat c; /* packet compression statistics */
+ struct compstat d; /* packet decompression statistics */
+};
+
+/*
+ * The following structure records the time in seconds since
+ * the last NP packet was sent or received.
+ */
+struct ppp_idle {
+ time_t xmit_idle; /* time since last NP packet sent */
+ time_t recv_idle; /* time since last NP packet received */
+};
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+#endif
+
+#endif /* _PPP_DEFS_H_ */
diff --git a/pfinet/linux-src/include/linux/prctl.h b/pfinet/linux-src/include/linux/prctl.h
new file mode 100644
index 00000000..f08f3c36
--- /dev/null
+++ b/pfinet/linux-src/include/linux/prctl.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_PRCTL_H
+#define _LINUX_PRCTL_H
+
+/* Values to pass as first argument to prctl() */
+
+#define PR_SET_PDEATHSIG 1 /* Second arg is a signal */
+
+
+#endif /* _LINUX_PRCTL_H */
diff --git a/pfinet/linux-src/include/linux/proc_fs.h b/pfinet/linux-src/include/linux/proc_fs.h
new file mode 100644
index 00000000..9d0d94e2
--- /dev/null
+++ b/pfinet/linux-src/include/linux/proc_fs.h
@@ -0,0 +1,470 @@
+#ifndef _LINUX_PROC_FS_H
+#define _LINUX_PROC_FS_H
+
+#include <linux/config.h>
+#include <linux/malloc.h>
+
+/*
+ * The proc filesystem constants/structures
+ */
+
+/*
+ * We always define these enumerators
+ */
+
+enum root_directory_inos {
+ PROC_ROOT_INO = 1,
+ PROC_LOADAVG,
+ PROC_UPTIME,
+ PROC_MEMINFO,
+ PROC_KMSG,
+ PROC_VERSION,
+ PROC_CPUINFO,
+ PROC_PCI,
+ PROC_MCA,
+ PROC_NUBUS,
+ PROC_SELF, /* will change inode # */
+ PROC_NET,
+ PROC_SCSI,
+ PROC_MALLOC,
+ PROC_KCORE,
+ PROC_MODULES,
+ PROC_STAT,
+ PROC_DEVICES,
+ PROC_PARTITIONS,
+ PROC_INTERRUPTS,
+ PROC_FILESYSTEMS,
+ PROC_KSYMS,
+ PROC_DMA,
+ PROC_IOPORTS,
+ PROC_PROFILE, /* whether enabled or not */
+ PROC_CMDLINE,
+ PROC_SYS,
+ PROC_MTAB,
+ PROC_SWAP,
+ PROC_MD,
+ PROC_RTC,
+ PROC_LOCKS,
+ PROC_HARDWARE,
+ PROC_SLABINFO,
+ PROC_PARPORT,
+ PROC_PPC_HTAB,
+ PROC_STRAM,
+ PROC_SOUND,
+ PROC_MTRR, /* whether enabled or not */
+ PROC_FS
+};
+
+enum pid_directory_inos {
+ PROC_PID_INO = 2,
+ PROC_PID_STATUS,
+ PROC_PID_MEM,
+ PROC_PID_CWD,
+ PROC_PID_ROOT,
+ PROC_PID_EXE,
+ PROC_PID_FD,
+ PROC_PID_ENVIRON,
+ PROC_PID_CMDLINE,
+ PROC_PID_STAT,
+ PROC_PID_STATM,
+ PROC_PID_MAPS,
+#if CONFIG_AP1000
+ PROC_PID_RINGBUF,
+#endif
+ PROC_PID_CPU,
+};
+
+enum pid_subdirectory_inos {
+ PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */
+};
+
+enum net_directory_inos {
+ PROC_NET_UNIX = 128,
+ PROC_NET_ARP,
+ PROC_NET_ROUTE,
+ PROC_NET_DEV,
+ PROC_NET_RAW,
+ PROC_NET_RAW6,
+ PROC_NET_TCP,
+ PROC_NET_TCP6,
+ PROC_NET_UDP,
+ PROC_NET_UDP6,
+ PROC_NET_SNMP,
+ PROC_NET_RARP,
+ PROC_NET_IGMP,
+ PROC_NET_IPMR_VIF,
+ PROC_NET_IPMR_MFC,
+ PROC_NET_IPFWFWD,
+ PROC_NET_IPFWIN,
+ PROC_NET_IPFWOUT,
+ PROC_NET_IPACCT,
+ PROC_NET_IPMSQHST,
+ PROC_NET_WIRELESS,
+ PROC_NET_IPX_INTERFACE,
+ PROC_NET_IPX_ROUTE,
+ PROC_NET_IPX,
+ PROC_NET_ATALK,
+ PROC_NET_AT_ROUTE,
+ PROC_NET_ATIF,
+ PROC_NET_AX25_ROUTE,
+ PROC_NET_AX25,
+ PROC_NET_AX25_CALLS,
+ PROC_NET_BMAC,
+ PROC_NET_NR_NODES,
+ PROC_NET_NR_NEIGH,
+ PROC_NET_NR,
+ PROC_NET_SOCKSTAT,
+ PROC_NET_SOCKSTAT6,
+ PROC_NET_RTCACHE,
+ PROC_NET_AX25_BPQETHER,
+ PROC_NET_IP_MASQ_APP,
+ PROC_NET_RT6,
+ PROC_NET_SNMP6,
+ PROC_NET_RT6_STATS,
+ PROC_NET_NDISC,
+ PROC_NET_STRIP_STATUS,
+ PROC_NET_STRIP_TRACE,
+ PROC_NET_Z8530,
+ PROC_NET_RS_NODES,
+ PROC_NET_RS_NEIGH,
+ PROC_NET_RS_ROUTES,
+ PROC_NET_RS,
+ PROC_NET_CL2LLC,
+ PROC_NET_X25_ROUTES,
+ PROC_NET_X25,
+ PROC_NET_TR_RIF,
+ PROC_NET_DN_DEV,
+ PROC_NET_DN_ADJ,
+ PROC_NET_DN_L1,
+ PROC_NET_DN_L2,
+ PROC_NET_DN_CACHE,
+ PROC_NET_DN_SKT,
+ PROC_NET_DN_FW,
+ PROC_NET_DN_RAW,
+ PROC_NET_NETSTAT,
+ PROC_NET_IPFW_CHAINS,
+ PROC_NET_IPFW_CHAIN_NAMES,
+ PROC_NET_AT_AARP,
+ PROC_NET_BRIDGE,
+ PROC_NET_LAST
+};
+
+enum scsi_directory_inos {
+ PROC_SCSI_SCSI = 256,
+ PROC_SCSI_ADVANSYS,
+ PROC_SCSI_PCI2000,
+ PROC_SCSI_PCI2220I,
+ PROC_SCSI_PSI240I,
+ PROC_SCSI_EATA,
+ PROC_SCSI_EATA_PIO,
+ PROC_SCSI_AHA152X,
+ PROC_SCSI_AHA1542,
+ PROC_SCSI_AHA1740,
+ PROC_SCSI_AIC7XXX,
+ PROC_SCSI_BUSLOGIC,
+ PROC_SCSI_U14_34F,
+ PROC_SCSI_FDOMAIN,
+ PROC_SCSI_GDTH,
+ PROC_SCSI_GENERIC_NCR5380,
+ PROC_SCSI_IN2000,
+ PROC_SCSI_PAS16,
+ PROC_SCSI_QLOGICFAS,
+ PROC_SCSI_QLOGICISP,
+ PROC_SCSI_QLOGICFC,
+ PROC_SCSI_SEAGATE,
+ PROC_SCSI_T128,
+ PROC_SCSI_NCR53C7xx,
+ PROC_SCSI_SYM53C8XX,
+ PROC_SCSI_NCR53C8XX,
+ PROC_SCSI_ULTRASTOR,
+ PROC_SCSI_7000FASST,
+ PROC_SCSI_IBMMCA,
+ PROC_SCSI_FD_MCS,
+ PROC_SCSI_EATA2X,
+ PROC_SCSI_DC390T,
+ PROC_SCSI_AM53C974,
+ PROC_SCSI_SSC,
+ PROC_SCSI_NCR53C406A,
+ PROC_SCSI_SYM53C416,
+ PROC_SCSI_MEGARAID,
+ PROC_SCSI_PPA,
+ PROC_SCSI_ATP870U,
+ PROC_SCSI_ESP,
+ PROC_SCSI_QLOGICPTI,
+ PROC_SCSI_AMIGA7XX,
+ PROC_SCSI_MVME16x,
+ PROC_SCSI_BVME6000,
+ PROC_SCSI_A3000,
+ PROC_SCSI_A2091,
+ PROC_SCSI_GVP11,
+ PROC_SCSI_ATARI,
+ PROC_SCSI_MAC,
+ PROC_SCSI_IDESCSI,
+ PROC_SCSI_SGIWD93,
+ PROC_SCSI_MESH,
+ PROC_SCSI_53C94,
+ PROC_SCSI_PLUTO,
+ PROC_SCSI_INI9100U,
+ PROC_SCSI_INIA100,
+ PROC_SCSI_IPH5526_FC,
+ PROC_SCSI_FCAL,
+ PROC_SCSI_I2O,
+ PROC_SCSI_USB_SCSI,
+ PROC_SCSI_SCSI_DEBUG,
+ PROC_SCSI_NOT_PRESENT,
+ PROC_SCSI_FILE, /* I'm assuming here that we */
+ PROC_SCSI_LAST = (PROC_SCSI_FILE + 16) /* won't ever see more than */
+}; /* 16 HBAs in one machine */
+
+enum mca_directory_inos {
+ PROC_MCA_MACHINE = (PROC_SCSI_LAST+1),
+ PROC_MCA_REGISTERS,
+ PROC_MCA_VIDEO,
+ PROC_MCA_SCSI,
+ PROC_MCA_SLOT, /* the 8 adapter slots */
+ PROC_MCA_LAST = (PROC_MCA_SLOT + 8)
+};
+
+enum bus_directory_inos {
+ PROC_BUS_PCI = PROC_MCA_LAST,
+ PROC_BUS_PCI_DEVICES,
+ PROC_BUS_ZORRO,
+ PROC_BUS_ZORRO_DEVICES,
+ PROC_BUS_LAST
+};
+
+enum fs_directory_inos {
+ PROC_FS_CODA = PROC_BUS_LAST,
+ PROC_FS_LAST
+};
+
+enum fs_coda_directory_inos {
+ PROC_VFS_STATS = PROC_FS_LAST,
+ PROC_UPCALL_STATS,
+ PROC_PERMISSION_STATS,
+ PROC_CACHE_INV_STATS,
+ PROC_CODA_FS_LAST
+};
+
+/* Finally, the dynamically allocatable proc entries are reserved: */
+
+#define PROC_DYNAMIC_FIRST 4096
+#define PROC_NDYNAMIC 4096
+#define PROC_OPENPROM_FIRST (PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
+#define PROC_OPENPROM PROC_OPENPROM_FIRST
+#define PROC_NOPENPROM 4096
+#define PROC_OPENPROMD_FIRST (PROC_OPENPROM_FIRST+PROC_NOPENPROM)
+#define PROC_NOPENPROMD 4096
+
+#define PROC_SUPER_MAGIC 0x9fa0
+
+/*
+ * This is not completely implemented yet. The idea is to
+ * create an in-memory tree (like the actual /proc filesystem
+ * tree) of these proc_dir_entries, so that we can dynamically
+ * add new files to /proc.
+ *
+ * The "next" pointer creates a linked list of one /proc directory,
+ * while parent/subdir create the directory structure (every
+ * /proc file has a parent, but "subdir" is NULL for all
+ * non-directory entries).
+ *
+ * "get_info" is called at "read", while "fill_inode" is used to
+ * fill in file type/protection/owner information specific to the
+ * particular /proc file.
+ */
+struct proc_dir_entry {
+ unsigned short low_ino;
+ unsigned short namelen;
+ const char *name;
+ mode_t mode;
+ nlink_t nlink;
+ uid_t uid;
+ gid_t gid;
+ unsigned long size;
+ struct inode_operations * ops;
+ int (*get_info)(char *, char **, off_t, int, int);
+ void (*fill_inode)(struct inode *, int);
+ struct proc_dir_entry *next, *parent, *subdir;
+ void *data;
+ int (*read_proc)(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+ int (*write_proc)(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+ int (*readlink_proc)(struct proc_dir_entry *de, char *page);
+ unsigned int count; /* use count */
+ int deleted; /* delete flag */
+};
+
+typedef int (read_proc_t)(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+typedef int (write_proc_t)(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+
+extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
+ off_t offset, int length, int inout);
+
+#ifdef CONFIG_PROC_FS
+
+extern struct proc_dir_entry proc_root;
+extern struct proc_dir_entry proc_root_fs;
+extern struct proc_dir_entry *proc_net;
+extern struct proc_dir_entry *proc_scsi;
+extern struct proc_dir_entry proc_sys;
+extern struct proc_dir_entry proc_openprom;
+extern struct proc_dir_entry proc_pid;
+extern struct proc_dir_entry proc_pid_fd;
+extern struct proc_dir_entry proc_mca;
+extern struct proc_dir_entry *proc_bus;
+
+extern struct inode_operations proc_scsi_inode_operations;
+
+extern void proc_root_init(void);
+extern void proc_base_init(void);
+
+extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
+extern int proc_unregister(struct proc_dir_entry *, int);
+
+static inline int proc_net_register(struct proc_dir_entry * x)
+{
+ return proc_register(proc_net, x);
+}
+
+static inline int proc_net_unregister(int x)
+{
+ return proc_unregister(proc_net, x);
+}
+
+static inline int proc_scsi_register(struct proc_dir_entry *driver,
+ struct proc_dir_entry *x)
+{
+ x->ops = &proc_scsi_inode_operations;
+ if(x->low_ino < PROC_SCSI_FILE){
+ return(proc_register(proc_scsi, x));
+ }else{
+ return(proc_register(driver, x));
+ }
+}
+
+static inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
+{
+ extern void scsi_init_free(char *ptr, unsigned int size);
+
+ if(x < PROC_SCSI_FILE)
+ return(proc_unregister(proc_scsi, x));
+ else {
+ struct proc_dir_entry **p = &driver->subdir, *dp;
+ int ret;
+
+ while ((dp = *p) != NULL) {
+ if (dp->low_ino == x)
+ break;
+ p = &dp->next;
+ }
+ ret = proc_unregister(driver, x);
+ scsi_init_free((char *) dp, sizeof(struct proc_dir_entry) + 4);
+ return(ret);
+ }
+}
+
+extern struct dentry_operations proc_dentry_operations;
+extern struct super_block *proc_read_super(struct super_block *,void *,int);
+extern int init_proc_fs(void);
+extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *);
+extern int proc_statfs(struct super_block *, struct statfs *, int);
+extern void proc_read_inode(struct inode *);
+extern void proc_write_inode(struct inode *);
+extern int proc_permission(struct inode *, int);
+
+extern int proc_match(int, const char *,struct proc_dir_entry *);
+
+/*
+ * These are generic /proc routines that use the internal
+ * "struct proc_dir_entry" tree to traverse the filesystem.
+ *
+ * The /proc root directory has extended versions to take care
+ * of the /proc/<pid> subdirectories.
+ */
+extern int proc_readdir(struct file *, void *, filldir_t);
+extern struct dentry *proc_lookup(struct inode *, struct dentry *);
+
+struct openpromfs_dev {
+ struct openpromfs_dev *next;
+ u32 node;
+ ino_t inode;
+ kdev_t rdev;
+ mode_t mode;
+ char name[32];
+};
+extern struct inode_operations *
+proc_openprom_register(int (*readdir)(struct file *, void *, filldir_t),
+ struct dentry * (*lookup)(struct inode *, struct dentry *),
+ void (*use)(struct inode *, int),
+ struct openpromfs_dev ***);
+extern void proc_openprom_deregister(void);
+extern void (*proc_openprom_use)(struct inode *,int);
+extern int proc_openprom_regdev(struct openpromfs_dev *);
+extern int proc_openprom_unregdev(struct openpromfs_dev *);
+
+extern struct inode_operations proc_dir_inode_operations;
+extern struct inode_operations proc_file_inode_operations;
+extern struct inode_operations proc_net_inode_operations;
+extern struct inode_operations proc_netdir_inode_operations;
+extern struct inode_operations proc_openprom_inode_operations;
+extern struct inode_operations proc_mem_inode_operations;
+extern struct inode_operations proc_sys_inode_operations;
+extern struct inode_operations proc_array_inode_operations;
+extern struct inode_operations proc_arraylong_inode_operations;
+extern struct inode_operations proc_kcore_inode_operations;
+extern struct inode_operations proc_profile_inode_operations;
+extern struct inode_operations proc_kmsg_inode_operations;
+extern struct inode_operations proc_link_inode_operations;
+extern struct inode_operations proc_fd_inode_operations;
+#if CONFIG_AP1000
+extern struct inode_operations proc_ringbuf_inode_operations;
+#endif
+extern struct inode_operations proc_omirr_inode_operations;
+extern struct inode_operations proc_ppc_htab_inode_operations;
+
+/*
+ * generic.c
+ */
+struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
+ struct proc_dir_entry *parent);
+void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
+
+/*
+ * proc_tty.c
+ */
+extern void proc_tty_init(void);
+extern void proc_tty_register_driver(struct tty_driver *driver);
+extern void proc_tty_unregister_driver(struct tty_driver *driver);
+
+/*
+ * proc_devtree.c
+ */
+extern void proc_device_tree_init(void);
+
+#else
+
+extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) { return 0; };
+extern inline int proc_unregister(struct proc_dir_entry *a, int b) { return 0; };
+extern inline int proc_net_register(struct proc_dir_entry *a) { return 0; };
+extern inline int proc_net_unregister(int x) { return 0; };
+extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; };
+extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; };
+
+extern inline struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
+ struct proc_dir_entry *parent)
+{
+ return NULL;
+}
+
+extern inline void remove_proc_entry(const char *name, struct proc_dir_entry *parent) {};
+
+extern inline void proc_tty_register_driver(struct tty_driver *driver) {};
+extern inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
+
+
+#endif
+#endif /* _LINUX_PROC_FS_H */
diff --git a/pfinet/linux-src/include/linux/ps2esdi.h b/pfinet/linux-src/include/linux/ps2esdi.h
new file mode 100644
index 00000000..c0e050b1
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ps2esdi.h
@@ -0,0 +1,98 @@
+#ifndef _PS2ESDI_H_
+#define _PS2ESDI_H_
+
+#define NRML_ESDI_ID 0xddff
+#define INTG_ESDI_ID 0xdf9f
+
+#define PRIMARY_IO_BASE 0x3510
+#define ALT_IO_BASE 0x3518
+
+#define ESDI_CMD_INT (io_base+0)
+#define ESDI_STT_INT (io_base+0)
+#define ESDI_CONTROL (io_base+2)
+#define ESDI_STATUS (io_base+2)
+#define ESDI_ATTN (io_base+3)
+#define ESDI_INTRPT (io_base+3)
+
+#define STATUS_ENABLED 0x01
+#define STATUS_ALTERNATE 0x02
+#define STATUS_BUSY 0x10
+#define STATUS_STAT_AVAIL 0x08
+#define STATUS_INTR 0x01
+#define STATUS_RESET_FAIL 0xea
+#define STATUS_CMD_INF 0x04
+
+#define CTRL_SOFT_RESET 0xe4
+#define CTRL_HARD_RESET 0x80
+#define CTRL_EOI 0xe2
+#define CTRL_ENABLE_DMA 0x02
+#define CTRL_ENABLE_INTR 0x01
+#define CTRL_DISABLE_INTR 0x00
+
+#define ATT_EOI 0x02
+
+/* bits of word 0 of configuration status block. more info see p.38 of tech ref */
+#define CONFIG_IS 0x10 /* Invalid Secondary */
+#define CONFIG_ZD 0x08 /* Zero Defect */
+#define CONFIG_SF 0x04 /* Skewed Format */
+#define CONFIG_FR 0x02 /* Removable */
+#define CONFIG_RT 0x01 /* Retries */
+
+#define PORT_SYS_A 0x92
+#define PORT_DMA_FN 0x18
+#define PORT_DMA_EX 0x1a
+
+#define ON (unsigned char)0x40
+#define OFF (unsigned char)~ON
+#define LITE_ON outb(inb(PORT_SYS_A) | ON,PORT_SYS_A)
+#define LITE_OFF outb((inb(PORT_SYS_A) & OFF),PORT_SYS_A)
+
+#define FAIL 0
+#define SUCCES 1
+
+#define INT_CMD_COMPLETE 0x01
+#define INT_CMD_ECC 0x03
+#define INT_CMD_RETRY 0x05
+#define INT_CMD_FORMAT 0x06
+#define INT_CMD_ECC_RETRY 0x07
+#define INT_CMD_WARNING 0x08
+#define INT_CMD_ABORT 0x09
+#define INT_RESET 0x0A
+#define INT_TRANSFER_REQ 0x0B
+#define INT_CMD_FAILED 0x0C
+#define INT_DMA_ERR 0x0D
+#define INT_CMD_BLK_ERR 0x0E
+#define INT_ATTN_ERROR 0x0F
+
+#define DMA_MASK_CHAN 0x90
+#define DMA_UNMASK_CHAN 0xA0
+#define DMA_WRITE_ADDR 0x20
+#define DMA_WRITE_TC 0x40
+#define DMA_WRITE_MODE 0x70
+
+#define CMD_GET_DEV_CONFIG 0x09
+#define CMD_READ 0x4601
+#define CMD_WRITE 0x4602
+#define DMA_READ_16 0x4C
+#define DMA_WRITE_16 0x44
+
+
+#define MB 1024*1024
+#define SECT_SIZE 512
+
+#define ERROR 1
+#define OK 0
+
+#define HDIO_GETGEO 0x0301
+
+#define FALSE 0
+#define TRUE !FALSE
+
+struct ps2esdi_geometry {
+ unsigned char heads;
+ unsigned char sectors;
+ unsigned short cylinders;
+ unsigned long start;
+};
+
+#endif /* _PS2ESDI_H_ */
diff --git a/pfinet/linux-src/include/linux/ptrace.h b/pfinet/linux-src/include/linux/ptrace.h
new file mode 100644
index 00000000..0a02879d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ptrace.h
@@ -0,0 +1,26 @@
+#ifndef _LINUX_PTRACE_H
+#define _LINUX_PTRACE_H
+/* ptrace.h */
+/* structs and defines to help the user use the ptrace system call. */
+
+/* has the defines to get at the registers. */
+
+#define PTRACE_TRACEME 0
+#define PTRACE_PEEKTEXT 1
+#define PTRACE_PEEKDATA 2
+#define PTRACE_PEEKUSR 3
+#define PTRACE_POKETEXT 4
+#define PTRACE_POKEDATA 5
+#define PTRACE_POKEUSR 6
+#define PTRACE_CONT 7
+#define PTRACE_KILL 8
+#define PTRACE_SINGLESTEP 9
+
+#define PTRACE_ATTACH 0x10
+#define PTRACE_DETACH 0x11
+
+#define PTRACE_SYSCALL 24
+
+#include <asm/ptrace.h>
+
+#endif
diff --git a/pfinet/linux-src/include/linux/qic117.h b/pfinet/linux-src/include/linux/qic117.h
new file mode 100644
index 00000000..07b537e5
--- /dev/null
+++ b/pfinet/linux-src/include/linux/qic117.h
@@ -0,0 +1,290 @@
+#ifndef _QIC117_H
+#define _QIC117_H
+
+/*
+ * Copyright (C) 1993-1996 Bas Laarhoven,
+ * (C) 1997 Claus-Justus Heine.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *
+ * $Source: /homes/cvs/ftape-stacked/include/linux/qic117.h,v $
+ * $Revision: 1.2 $
+ * $Date: 1997/10/05 19:19:32 $
+ *
+ * This file contains QIC-117 spec. related definitions for the
+ * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
+ *
+ * These data were taken from the Quarter-Inch Cartridge
+ * Drive Standards, Inc. document titled:
+ * `Common Command Set Interface Specification for Flexible
+ * Disk Controller Based Minicartridge Tape Drives'
+ * document QIC-117 Revision J, 28 Aug 96.
+ * For more information, contact:
+ * Quarter-Inch Cartridge Drive Standards, Inc.
+ * 311 East Carrillo Street
+ * Santa Barbara, California 93101
+ * Telephone (805) 963-3853
+ * Fax (805) 962-1541
+ * WWW http://www.qic.org
+ *
+ * Current QIC standard revisions (of interest) are:
+ * QIC-40-MC, Rev. M, 2 Sep 92.
+ * QIC-80-MC, Rev. N, 20 Mar 96.
+ * QIC-80-MC, Rev. K, 15 Dec 94.
+ * QIC-113, Rev. G, 15 Jun 95.
+ * QIC-117, Rev. J, 28 Aug 96.
+ * QIC-122, Rev. B, 6 Mar 91.
+ * QIC-130, Rev. C, 2 Sep 92.
+ * QIC-3010-MC, Rev. F, 14 Jun 95.
+ * QIC-3020-MC, Rev. G, 31 Aug 95.
+ * QIC-CRF3, Rev. B, 15 Jun 95.
+ * */
+
+/*
+ * QIC-117 common command set rev. J.
+ * These commands are sent to the tape unit
+ * as number of pulses over the step line.
+ */
+
+typedef enum {
+ QIC_NO_COMMAND = 0,
+ QIC_RESET = 1,
+ QIC_REPORT_NEXT_BIT = 2,
+ QIC_PAUSE = 3,
+ QIC_MICRO_STEP_PAUSE = 4,
+ QIC_ALTERNATE_TIMEOUT = 5,
+ QIC_REPORT_DRIVE_STATUS = 6,
+ QIC_REPORT_ERROR_CODE = 7,
+ QIC_REPORT_DRIVE_CONFIGURATION = 8,
+ QIC_REPORT_ROM_VERSION = 9,
+ QIC_LOGICAL_FORWARD = 10,
+ QIC_PHYSICAL_REVERSE = 11,
+ QIC_PHYSICAL_FORWARD = 12,
+ QIC_SEEK_HEAD_TO_TRACK = 13,
+ QIC_SEEK_LOAD_POINT = 14,
+ QIC_ENTER_FORMAT_MODE = 15,
+ QIC_WRITE_REFERENCE_BURST = 16,
+ QIC_ENTER_VERIFY_MODE = 17,
+ QIC_STOP_TAPE = 18,
+/* commands 19-20: reserved */
+ QIC_MICRO_STEP_HEAD_UP = 21,
+ QIC_MICRO_STEP_HEAD_DOWN = 22,
+ QIC_SOFT_SELECT = 23,
+ QIC_SOFT_DESELECT = 24,
+ QIC_SKIP_REVERSE = 25,
+ QIC_SKIP_FORWARD = 26,
+ QIC_SELECT_RATE = 27,
+/* command 27, in ccs2: Select Rate or Format */
+ QIC_ENTER_DIAGNOSTIC_1 = 28,
+ QIC_ENTER_DIAGNOSTIC_2 = 29,
+ QIC_ENTER_PRIMARY_MODE = 30,
+/* command 31: vendor unique */
+ QIC_REPORT_VENDOR_ID = 32,
+ QIC_REPORT_TAPE_STATUS = 33,
+ QIC_SKIP_EXTENDED_REVERSE = 34,
+ QIC_SKIP_EXTENDED_FORWARD = 35,
+ QIC_CALIBRATE_TAPE_LENGTH = 36,
+ QIC_REPORT_FORMAT_SEGMENTS = 37,
+ QIC_SET_FORMAT_SEGMENTS = 38,
+/* commands 39-45: reserved */
+ QIC_PHANTOM_SELECT = 46,
+ QIC_PHANTOM_DESELECT = 47
+} qic117_cmd_t;
+
+typedef enum {
+ discretional = 0, required, ccs1, ccs2
+} qic_compatibility;
+
+typedef enum {
+ unused, mode, motion, report
+} command_types;
+
+struct qic117_command_table {
+ char *name;
+ __u8 mask;
+ __u8 state;
+ __u8 cmd_type;
+ __u8 non_intr;
+ __u8 level;
+};
+
+#define QIC117_COMMANDS {\
+/* command mask state cmd_type */\
+/* | name | | | non_intr */\
+/* | | | | | | level */\
+/* 0*/ {NULL, 0x00, 0x00, mode, 0, discretional},\
+/* 1*/ {"soft reset", 0x00, 0x00, motion, 1, required},\
+/* 2*/ {"report next bit", 0x00, 0x00, report, 0, required},\
+/* 3*/ {"pause", 0x36, 0x24, motion, 1, required},\
+/* 4*/ {"micro step pause", 0x36, 0x24, motion, 1, required},\
+/* 5*/ {"alternate command timeout", 0x00, 0x00, mode, 0, required},\
+/* 6*/ {"report drive status", 0x00, 0x00, report, 0, required},\
+/* 7*/ {"report error code", 0x01, 0x01, report, 0, required},\
+/* 8*/ {"report drive configuration",0x00, 0x00, report, 0, required},\
+/* 9*/ {"report rom version", 0x00, 0x00, report, 0, required},\
+/*10*/ {"logical forward", 0x37, 0x25, motion, 0, required},\
+/*11*/ {"physical reverse", 0x17, 0x05, motion, 0, required},\
+/*12*/ {"physical forward", 0x17, 0x05, motion, 0, required},\
+/*13*/ {"seek head to track", 0x37, 0x25, motion, 0, required},\
+/*14*/ {"seek load point", 0x17, 0x05, motion, 1, required},\
+/*15*/ {"enter format mode", 0x1f, 0x05, mode, 0, required},\
+/*16*/ {"write reference burst", 0x1f, 0x05, motion, 1, required},\
+/*17*/ {"enter verify mode", 0x37, 0x25, mode, 0, required},\
+/*18*/ {"stop tape", 0x00, 0x00, motion, 1, required},\
+/*19*/ {"reserved (19)", 0x00, 0x00, unused, 0, discretional},\
+/*20*/ {"reserved (20)", 0x00, 0x00, unused, 0, discretional},\
+/*21*/ {"micro step head up", 0x02, 0x00, motion, 0, required},\
+/*22*/ {"micro step head down", 0x02, 0x00, motion, 0, required},\
+/*23*/ {"soft select", 0x00, 0x00, mode, 0, discretional},\
+/*24*/ {"soft deselect", 0x00, 0x00, mode, 0, discretional},\
+/*25*/ {"skip segments reverse", 0x36, 0x24, motion, 1, required},\
+/*26*/ {"skip segments forward", 0x36, 0x24, motion, 1, required},\
+/*27*/ {"select rate or format", 0x03, 0x01, mode, 0, required /* [ccs2] */},\
+/*28*/ {"enter diag mode 1", 0x00, 0x00, mode, 0, discretional},\
+/*29*/ {"enter diag mode 2", 0x00, 0x00, mode, 0, discretional},\
+/*30*/ {"enter primary mode", 0x00, 0x00, mode, 0, required},\
+/*31*/ {"vendor unique (31)", 0x00, 0x00, unused, 0, discretional},\
+/*32*/ {"report vendor id", 0x00, 0x00, report, 0, required},\
+/*33*/ {"report tape status", 0x04, 0x04, report, 0, ccs1},\
+/*34*/ {"skip extended reverse", 0x36, 0x24, motion, 1, ccs1},\
+/*35*/ {"skip extended forward", 0x36, 0x24, motion, 1, ccs1},\
+/*36*/ {"calibrate tape length", 0x17, 0x05, motion, 1, ccs2},\
+/*37*/ {"report format segments", 0x17, 0x05, report, 0, ccs2},\
+/*38*/ {"set format segments", 0x17, 0x05, mode, 0, ccs2},\
+/*39*/ {"reserved (39)", 0x00, 0x00, unused, 0, discretional},\
+/*40*/ {"vendor unique (40)", 0x00, 0x00, unused, 0, discretional},\
+/*41*/ {"vendor unique (41)", 0x00, 0x00, unused, 0, discretional},\
+/*42*/ {"vendor unique (42)", 0x00, 0x00, unused, 0, discretional},\
+/*43*/ {"vendor unique (43)", 0x00, 0x00, unused, 0, discretional},\
+/*44*/ {"vendor unique (44)", 0x00, 0x00, unused, 0, discretional},\
+/*45*/ {"vendor unique (45)", 0x00, 0x00, unused, 0, discretional},\
+/*46*/ {"phantom select", 0x00, 0x00, mode, 0, discretional},\
+/*47*/ {"phantom deselect", 0x00, 0x00, mode, 0, discretional},\
+}
+
+/*
+ * Status bits returned by QIC_REPORT_DRIVE_STATUS
+ */
+
+#define QIC_STATUS_READY 0x01 /* Drive is ready or idle. */
+#define QIC_STATUS_ERROR 0x02 /* Error detected, must read
+ error code to clear this */
+#define QIC_STATUS_CARTRIDGE_PRESENT 0x04 /* Tape is present */
+#define QIC_STATUS_WRITE_PROTECT 0x08 /* Tape is write protected */
+#define QIC_STATUS_NEW_CARTRIDGE 0x10 /* New cartridge inserted, must
+ read error status to clear. */
+#define QIC_STATUS_REFERENCED 0x20 /* Cartridge appears to have been
+ formatted. */
+#define QIC_STATUS_AT_BOT 0x40 /* Cartridge is at physical
+ beginning of tape. */
+#define QIC_STATUS_AT_EOT 0x80 /* Cartridge is at physical end
+ of tape. */
+/*
+ * Status bits returned by QIC_REPORT_DRIVE_CONFIGURATION
+ */
+
+#define QIC_CONFIG_RATE_MASK 0x18
+#define QIC_CONFIG_RATE_SHIFT 3
+#define QIC_CONFIG_RATE_250 0
+#define QIC_CONFIG_RATE_500 2
+#define QIC_CONFIG_RATE_1000 3
+#define QIC_CONFIG_RATE_2000 1
+#define QIC_CONFIG_RATE_4000 0 /* since QIC-117 Rev. J */
+
+#define QIC_CONFIG_LONG 0x40 /* Extra Length Tape Detected */
+#define QIC_CONFIG_80 0x80 /* QIC-80 detected. */
+
+/*
+ * Status bits returned by QIC_REPORT_TAPE_STATUS
+ */
+
+#define QIC_TAPE_STD_MASK 0x0f
+#define QIC_TAPE_QIC40 0x01
+#define QIC_TAPE_QIC80 0x02
+#define QIC_TAPE_QIC3020 0x03
+#define QIC_TAPE_QIC3010 0x04
+
+#define QIC_TAPE_LEN_MASK 0x70
+#define QIC_TAPE_205FT 0x10
+#define QIC_TAPE_307FT 0x20
+#define QIC_TAPE_VARIABLE 0x30
+#define QIC_TAPE_1100FT 0x40
+#define QIC_TAPE_FLEX 0x60
+
+#define QIC_TAPE_WIDE 0x80
+
+/* Define a value (in feet) slightly higher than
+ * the possible maximum tape length.
+ */
+#define QIC_TOP_TAPE_LEN 1500
+
+/*
+ * Errors: List of error codes, and their severity.
+ */
+
+typedef struct {
+ char *message; /* Text describing the error. */
+ unsigned int fatal:1; /* Non-zero if the error is fatal. */
+} ftape_error;
+
+#define QIC117_ERRORS {\
+ /* 0*/ { "No error", 0, },\
+ /* 1*/ { "Command Received while Drive Not Ready", 0, },\
+ /* 2*/ { "Cartridge Not Present or Removed", 1, },\
+ /* 3*/ { "Motor Speed Error (not within 1%)", 1, },\
+ /* 4*/ { "Motor Speed Fault (jammed, or gross speed error", 1, },\
+ /* 5*/ { "Cartridge Write Protected", 1, },\
+ /* 6*/ { "Undefined or Reserved Command Code", 1, },\
+ /* 7*/ { "Illegal Track Address Specified for Seek", 1, },\
+ /* 8*/ { "Illegal Command in Report Subcontext", 0, },\
+ /* 9*/ { "Illegal Entry into a Diagnostic Mode", 1, },\
+ /*10*/ { "Broken Tape Detected (based on hole sensor)", 1, },\
+ /*11*/ { "Warning--Read Gain Setting Error", 1, },\
+ /*12*/ { "Command Received While Error Status Pending (obs)", 1, },\
+ /*13*/ { "Command Received While New Cartridge Pending", 1, },\
+ /*14*/ { "Command Illegal or Undefined in Primary Mode", 1, },\
+ /*15*/ { "Command Illegal or Undefined in Format Mode", 1, },\
+ /*16*/ { "Command Illegal or Undefined in Verify Mode", 1, },\
+ /*17*/ { "Logical Forward Not at Logical BOT or no Format Segments in Format Mode", 1, },\
+ /*18*/ { "Logical EOT Before All Segments generated", 1, },\
+ /*19*/ { "Command Illegal When Cartridge Not Referenced", 1, },\
+ /*20*/ { "Self-Diagnostic Failed (cannot be cleared)", 1, },\
+ /*21*/ { "Warning EEPROM Not Initialized, Defaults Set", 1, },\
+ /*22*/ { "EEPROM Corrupted or Hardware Failure", 1, },\
+ /*23*/ { "Motion Time-out Error", 1, },\
+ /*24*/ { "Data Segment Too Long -- Logical Forward or Pause", 1, },\
+ /*25*/ { "Transmit Overrun (obs)", 1, },\
+ /*26*/ { "Power On Reset Occurred", 0, },\
+ /*27*/ { "Software Reset Occurred", 0, },\
+ /*28*/ { "Diagnostic Mode 1 Error", 1, },\
+ /*29*/ { "Diagnostic Mode 2 Error", 1, },\
+ /*30*/ { "Command Received During Non-Interruptible Process", 1, },\
+ /*31*/ { "Rate or Format Selection Error", 1, },\
+ /*32*/ { "Illegal Command While in High Speed Mode", 1, },\
+ /*33*/ { "Illegal Seek Segment Value", 1, },\
+ /*34*/ { "Invalid Media", 1, },\
+ /*35*/ { "Head Positioning Failure", 1, },\
+ /*36*/ { "Write Reference Burst Failure", 1, },\
+ /*37*/ { "Prom Code Missing", 1, },\
+ /*38*/ { "Invalid Format", 1, },\
+ /*39*/ { "EOT/BOT System Failure", 1, },\
+ /*40*/ { "Prom A Checksum Error", 1, },\
+ /*41*/ { "Drive Wakeup Reset Occurred", 1, },\
+ /*42*/ { "Prom B Checksum Error", 1, },\
+ /*43*/ { "Illegal Entry into Format Mode", 1, },\
+}
+
+#endif /* _QIC117_H */
diff --git a/pfinet/linux-src/include/linux/qnx4_fs.h b/pfinet/linux-src/include/linux/qnx4_fs.h
new file mode 100644
index 00000000..c5a01039
--- /dev/null
+++ b/pfinet/linux-src/include/linux/qnx4_fs.h
@@ -0,0 +1,123 @@
+/*
+ * Name : qnx4_fs.h
+ * Author : Richard Frowijn
+ * Function : qnx4 global filesystem definitions
+ * Version : 1.0
+ * Last modified : 23-03-1998
+ *
+ * History : 23-03-1998 created
+ */
+#ifndef _LINUX_QNX4_FS_H
+#define _LINUX_QNX4_FS_H
+
+#include <linux/qnxtypes.h>
+
+#define QNX4_ROOT_INO 1
+
+#define _MAX_XTNTS_PER_XBLK 60
+/* for di_status */
+#define QNX4_FILE_USED 0x01
+#define QNX4_FILE_MODIFIED 0x02
+#define QNX4_FILE_BUSY 0x04
+#define QNX4_FILE_LINK 0x08
+#define QNX4_FILE_INODE 0x10
+#define QNX4_FILE_FSYSCLEAN 0x20
+
+#define QNX4_I_MAP_SLOTS 8
+#define QNX4_Z_MAP_SLOTS 64
+#define QNX4_SUPER_MAGIC 0x002f /* qnx4 fs detection */
+#define QNX4_VALID_FS 0x0001 /* Clean fs. */
+#define QNX4_ERROR_FS 0x0002 /* fs has errors. */
+#define QNX4_BLOCK_SIZE 0x200 /* blocksize of 512 bytes */
+#define QNX4_DIR_ENTRY_SIZE 0x040 /* dir entry size */
+#define QNX4_XBLK_ENTRY_SIZE 0x200 /* xblk entry size */
+#define QNX4_INODES_PER_BLOCK 0x08 /* 512 / 64 */
+
+/* for filenames */
+#define _SHORT_NAME_MAX 16
+#define QNX4_NAME_MAX 48
+
+/*
+ * This is the original qnx4 inode layout on disk.
+ */
+struct qnx4_inode_entry {
+ char di_fname[16];
+ off_t di_size;
+ _xtnt_t di_first_xtnt;
+ long di_xblk;
+ time_t di_ftime;
+ time_t di_mtime;
+ time_t di_atime;
+ time_t di_ctime;
+ _nxtnt_t di_num_xtnts;
+ mode_t di_mode;
+ muid_t di_uid;
+ mgid_t di_gid;
+ nlink_t di_nlink;
+ char di_zero[4];
+ _ftype_t di_type;
+ unsigned char di_status;
+};
+
+struct qnx4_link_info {
+ char dl_fname[QNX4_NAME_MAX];
+ long dl_inode_blk;
+ unsigned char dl_inode_ndx;
+ unsigned char dl_spare[10];
+ unsigned char dl_status;
+};
+
+struct qnx4_xblk {
+ long xblk_next_xblk;
+ long xblk_prev_xblk;
+ unsigned char xblk_num_xtnts;
+ char xblk_spare[3];
+ long xblk_num_blocks;
+ _xtnt_t xblk_xnts[_MAX_XTNTS_PER_XBLK];
+ char xblk_signature[8];
+ _xtnt_t xblk_first_xtnt;
+};
+
+struct qnx4_super_block {
+ struct qnx4_inode_entry RootDir;
+ struct qnx4_inode_entry Inode;
+ struct qnx4_inode_entry Boot;
+ struct qnx4_inode_entry AltBoot;
+};
+
+#ifdef __KERNEL__
+
+#define QNX4_DEBUG 0
+
+#if QNX4_DEBUG
+#define QNX4DEBUG(X) printk X
+#else
+#define QNX4DEBUG(X) (void) 0
+#endif
+
+extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry);
+extern unsigned long qnx4_count_free_inodes(struct super_block *sb);
+extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
+
+extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
+extern struct buffer_head *qnx4_bread(struct inode *, int, int);
+
+extern int init_qnx4_fs(void);
+extern int qnx4_create(struct inode *dir, struct dentry *dentry, int mode);
+extern struct inode_operations qnx4_file_inode_operations;
+extern struct inode_operations qnx4_dir_inode_operations;
+extern struct inode_operations qnx4_symlink_inode_operations;
+extern int qnx4_is_free(struct super_block *sb, int block);
+extern int qnx4_set_bitmap(struct super_block *sb, int block, int busy);
+extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode);
+extern void qnx4_truncate(struct inode *inode);
+extern void qnx4_free_inode(struct inode *inode);
+extern int qnx4_unlink(struct inode *dir, struct dentry *dentry);
+extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry);
+extern int qnx4_sync_file(struct file *file, struct dentry *dentry);
+extern int qnx4_sync_inode(struct inode *inode);
+extern int qnx4_bmap(struct inode *inode, int block);
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/qnx4_fs_i.h b/pfinet/linux-src/include/linux/qnx4_fs_i.h
new file mode 100644
index 00000000..83d53e52
--- /dev/null
+++ b/pfinet/linux-src/include/linux/qnx4_fs_i.h
@@ -0,0 +1,38 @@
+/*
+ * Name : qnx4_fs_i.h
+ * Author : Richard Frowijn
+ * Function : qnx4 inode definitions
+ * Version : 1.0
+ * Last modified : 25-05-1998
+ *
+ * History : 23-03-1998 created
+ *
+ */
+#ifndef _QNX4_FS_I
+#define _QNX4_FS_I
+
+#include <linux/qnxtypes.h>
+
+/*
+ * qnx4 fs inode entry
+ */
+struct qnx4_inode_info {
+ char i_reserved[16]; /* 16 */
+ off_t i_size; /* 4 */
+ _xtnt_t i_first_xtnt; /* 8 */
+ long i_xblk; /* 4 */
+ time_t i_ftime; /* 4 */
+ time_t i_mtime; /* 4 */
+ time_t i_atime; /* 4 */
+ time_t i_ctime; /* 4 */
+ _nxtnt_t i_num_xtnts; /* 2 */
+ mode_t i_mode; /* 2 */
+ muid_t i_uid; /* 2 */
+ mgid_t i_gid; /* 2 */
+ nlink_t i_nlink; /* 2 */
+ char i_zero[4]; /* 4 */
+ _ftype_t i_type; /* 1 */
+ unsigned char i_status; /* 1 */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/qnx4_fs_sb.h b/pfinet/linux-src/include/linux/qnx4_fs_sb.h
new file mode 100644
index 00000000..9f28d3cb
--- /dev/null
+++ b/pfinet/linux-src/include/linux/qnx4_fs_sb.h
@@ -0,0 +1,27 @@
+/*
+ * Name : qnx4_fs_sb.h
+ * Author : Richard Frowijn
+ * Function : qnx4 superblock definitions
+ * Version : 1.0
+ * Last modified : 20-05-1998
+ *
+ * History : 23-03-1998 created
+ *
+ */
+#ifndef _QNX4_FS_SB
+#define _QNX4_FS_SB
+
+#include <linux/qnxtypes.h>
+
+/*
+ * qnx4 super-block data in memory
+ */
+
+struct qnx4_sb_info {
+ struct buffer_head *sb_buf; /* superblock buffer */
+ struct qnx4_super_block *sb; /* our superblock */
+ unsigned int Version; /* may be useful */
+ struct qnx4_inode_entry *BitMap; /* useful */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/qnxtypes.h b/pfinet/linux-src/include/linux/qnxtypes.h
new file mode 100644
index 00000000..054da0d1
--- /dev/null
+++ b/pfinet/linux-src/include/linux/qnxtypes.h
@@ -0,0 +1,28 @@
+/*
+ * Name : qnxtypes.h
+ * Author : Richard Frowijn
+ * Function : standard qnx types
+ * Version : 1.0
+ * Last modified : 22-03-1998
+ *
+ * History : 22-03-1998 created
+ *
+ */
+
+#ifndef _QNX4TYPES_H
+#define _QNX4TYPES_H
+
+typedef unsigned short _nxtnt_t;
+typedef unsigned char _ftype_t;
+
+typedef struct {
+ long xtnt_blk;
+ long xtnt_size;
+} _xtnt_t;
+
+typedef unsigned short muid_t;
+typedef unsigned short mgid_t;
+typedef unsigned long qnx_off_t;
+typedef unsigned short qnx_nlink_t;
+
+#endif
diff --git a/pfinet/linux-src/include/linux/quota.h b/pfinet/linux-src/include/linux/quota.h
new file mode 100644
index 00000000..2c4a5bce
--- /dev/null
+++ b/pfinet/linux-src/include/linux/quota.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Version: $Id: quota.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $
+ */
+
+#ifndef _LINUX_QUOTA_
+#define _LINUX_QUOTA_
+
+#include <linux/errno.h>
+
+/*
+ * Convert diskblocks to blocks and the other way around.
+ */
+#define dbtob(num) (num << 10)
+#define btodb(num) (num >> 10)
+
+/*
+ * Convert count of filesystem blocks to diskquota blocks, meant
+ * for filesystems where i_blksize != BLOCK_SIZE
+ */
+#define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / BLOCK_SIZE)
+
+/*
+ * Definitions for disk quotas imposed on the average user
+ * (big brother finally hits Linux).
+ *
+ * The following constants define the amount of time given a user
+ * before the soft limits are treated as hard limits (usually resulting
+ * in an allocation failure). The timer is started when the user crosses
+ * their soft limit, it is reset when they go below their soft limit.
+ */
+#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
+#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
+
+#define MAXQUOTAS 2
+#define USRQUOTA 0 /* element used for user quotas */
+#define GRPQUOTA 1 /* element used for group quotas */
+
+/*
+ * Definitions for the default names of the quotas files.
+ */
+#define INITQFNAMES { \
+ "user", /* USRQUOTA */ \
+ "group", /* GRPQUOTA */ \
+ "undefined", \
+};
+
+#define QUOTAFILENAME "quota"
+#define QUOTAGROUP "staff"
+
+extern int nr_dquots, nr_free_dquots;
+extern int max_dquots;
+extern int dquot_root_squash;
+
+#define NR_DQHASH 43 /* Just an arbitrary number */
+#define NR_DQUOTS 1024 /* Maximum number of quotas active at one time (Configurable from /proc/sys/fs) */
+
+/*
+ * Command definitions for the 'quotactl' system call.
+ * The commands are broken into a main command defined below
+ * and a subcommand that is used to convey the type of
+ * quota that is being manipulated (see above).
+ */
+#define SUBCMDMASK 0x00ff
+#define SUBCMDSHIFT 8
+#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
+
+#define Q_QUOTAON 0x0100 /* enable quotas */
+#define Q_QUOTAOFF 0x0200 /* disable quotas */
+#define Q_GETQUOTA 0x0300 /* get limits and usage */
+#define Q_SETQUOTA 0x0400 /* set limits and usage */
+#define Q_SETUSE 0x0500 /* set usage */
+#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */
+#define Q_SETQLIM 0x0700 /* set limits */
+#define Q_GETSTATS 0x0800 /* get collected stats */
+#define Q_RSQUASH 0x1000 /* set root_squash option */
+
+/*
+ * The following structure defines the format of the disk quota file
+ * (as it appears on disk) - the file is an array of these structures
+ * indexed by user or group number.
+ */
+struct dqblk {
+ __u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */
+ __u32 dqb_bsoftlimit; /* preferred limit on disk blks */
+ __u32 dqb_curblocks; /* current block count */
+ __u32 dqb_ihardlimit; /* absolute limit on allocated inodes */
+ __u32 dqb_isoftlimit; /* preferred inode limit */
+ __u32 dqb_curinodes; /* current # allocated inodes */
+ time_t dqb_btime; /* time limit for excessive disk use */
+ time_t dqb_itime; /* time limit for excessive inode use */
+};
+
+/*
+ * Shorthand notation.
+ */
+#define dq_bhardlimit dq_dqb.dqb_bhardlimit
+#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit
+#define dq_curblocks dq_dqb.dqb_curblocks
+#define dq_ihardlimit dq_dqb.dqb_ihardlimit
+#define dq_isoftlimit dq_dqb.dqb_isoftlimit
+#define dq_curinodes dq_dqb.dqb_curinodes
+#define dq_btime dq_dqb.dqb_btime
+#define dq_itime dq_dqb.dqb_itime
+
+#define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk)))
+
+struct dqstats {
+ __u32 lookups;
+ __u32 drops;
+ __u32 reads;
+ __u32 writes;
+ __u32 cache_hits;
+ __u32 allocated_dquots;
+ __u32 free_dquots;
+ __u32 syncs;
+};
+
+#ifdef __KERNEL__
+
+/*
+ * Maximum length of a message generated in the quota system,
+ * that needs to be kicked onto the tty.
+ */
+#define MAX_QUOTA_MESSAGE 75
+
+#define DQ_LOCKED 0x01 /* locked for update */
+#define DQ_WANT 0x02 /* wanted for update */
+#define DQ_MOD 0x04 /* dquot modified since read */
+#define DQ_BLKS 0x10 /* uid/gid has been warned about blk limit */
+#define DQ_INODES 0x20 /* uid/gid has been warned about inode limit */
+#define DQ_FAKE 0x40 /* no limits only usage */
+
+struct dquot {
+ struct dquot *dq_next; /* Pointer to next dquot */
+ struct dquot **dq_pprev;
+ struct list_head dq_free; /* free list element */
+ struct dquot *dq_hash_next; /* Pointer to next in dquot_hash */
+ struct dquot **dq_hash_pprev; /* Pointer to previous in dquot_hash */
+ struct wait_queue *dq_wait; /* Pointer to waitqueue */
+ int dq_count; /* Reference count */
+
+ /* fields after this point are cleared when invalidating */
+ struct vfsmount *dq_mnt; /* VFS_mount_point this applies to */
+ unsigned int dq_id; /* ID this applies to (uid, gid) */
+ kdev_t dq_dev; /* Device this applies to */
+ short dq_type; /* Type of quota */
+ short dq_flags; /* See DQ_* */
+ unsigned long dq_referenced; /* Number of times this dquot was
+ referenced during its lifetime */
+ struct dqblk dq_dqb; /* Diskquota usage */
+};
+
+#define NODQUOT (struct dquot *)NULL
+
+/*
+ * Flags used for set_dqblk.
+ */
+#define QUOTA_SYSCALL 0x01
+#define SET_QUOTA 0x02
+#define SET_USE 0x04
+#define SET_QLIMIT 0x08
+
+#define QUOTA_OK 0
+#define NO_QUOTA 1
+
+#else
+
+# /* nodep */ include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int quotactl __P ((int, const char *, int, caddr_t));
+__END_DECLS
+
+#endif /* __KERNEL__ */
+#endif /* _QUOTA_ */
diff --git a/pfinet/linux-src/include/linux/quotaops.h b/pfinet/linux-src/include/linux/quotaops.h
new file mode 100644
index 00000000..8de13430
--- /dev/null
+++ b/pfinet/linux-src/include/linux/quotaops.h
@@ -0,0 +1,135 @@
+/*
+ * Definitions for diskquota-operations. When diskquota is configured these
+ * macros expand to the right source-code.
+ *
+ * Author: Marco van Wieringen <mvw@planets.elm.net>
+ *
+ * Version: $Id: quotaops.h,v 1.2 1998/01/15 16:22:26 ecd Exp $
+ *
+ */
+#ifndef _LINUX_QUOTAOPS_
+#define _LINUX_QUOTAOPS_
+
+#include <linux/config.h>
+
+#if defined(CONFIG_QUOTA)
+
+/*
+ * declaration of quota_function calls in kernel.
+ */
+extern void dquot_initialize(struct inode *inode, short type);
+extern void dquot_drop(struct inode *inode);
+extern void invalidate_dquots(kdev_t dev, short type);
+extern int quota_off(kdev_t dev, short type);
+extern int sync_dquots(kdev_t dev, short type);
+
+extern int dquot_alloc_block(const struct inode *inode, unsigned long number,
+ uid_t initiator, char warn);
+extern int dquot_alloc_inode(const struct inode *inode, unsigned long number,
+ uid_t initiator);
+
+extern void dquot_free_block(const struct inode *inode, unsigned long number);
+extern void dquot_free_inode(const struct inode *inode, unsigned long number);
+
+extern int dquot_transfer(struct dentry *dentry, struct iattr *iattr,
+ uid_t initiator);
+
+/*
+ * Operations supported for diskquotas.
+ */
+extern __inline__ void DQUOT_INIT(struct inode *inode)
+{
+ if (inode->i_sb && inode->i_sb->dq_op)
+ inode->i_sb->dq_op->initialize(inode, -1);
+}
+
+extern __inline__ void DQUOT_DROP(struct inode *inode)
+{
+ if (IS_QUOTAINIT(inode)) {
+ if (inode->i_sb && inode->i_sb->dq_op)
+ inode->i_sb->dq_op->drop(inode);
+ }
+}
+
+extern __inline__ int DQUOT_PREALLOC_BLOCK(struct super_block *sb, const struct inode *inode, int nr)
+{
+ if (sb->dq_op) {
+ if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize),
+ current->fsuid, 0) == NO_QUOTA)
+ return 1;
+ }
+ return 0;
+}
+
+extern __inline__ int DQUOT_ALLOC_BLOCK(struct super_block *sb, const struct inode *inode, int nr)
+{
+ if (sb->dq_op) {
+ if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize),
+ current->fsuid, 1) == NO_QUOTA)
+ return 1;
+ }
+ return 0;
+}
+
+extern __inline__ int DQUOT_ALLOC_INODE(struct super_block *sb, struct inode *inode)
+{
+ if (sb->dq_op) {
+ sb->dq_op->initialize (inode, -1);
+ if (sb->dq_op->alloc_inode (inode, 1, current->fsuid))
+ return 1;
+ }
+ inode->i_flags |= S_QUOTA;
+ return 0;
+}
+
+extern __inline__ void DQUOT_FREE_BLOCK(struct super_block *sb, const struct inode *inode, int nr)
+{
+ if (sb->dq_op)
+ sb->dq_op->free_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize));
+}
+
+extern __inline__ void DQUOT_FREE_INODE(struct super_block *sb, struct inode *inode)
+{
+ if (sb->dq_op)
+ sb->dq_op->free_inode(inode, 1);
+}
+
+extern __inline__ int DQUOT_TRANSFER(struct dentry *dentry, struct iattr *iattr)
+{
+ int error = -EDQUOT;
+
+ if (dentry->d_inode->i_sb->dq_op) {
+ if (IS_QUOTAINIT(dentry->d_inode) == 0)
+ dentry->d_inode->i_sb->dq_op->initialize(dentry->d_inode, -1);
+ error = dentry->d_inode->i_sb->dq_op->transfer(dentry, iattr, current->fsuid);
+ } else {
+ error = notify_change(dentry, iattr);
+ }
+ return error;
+}
+
+#define DQUOT_SYNC(dev) sync_dquots(dev, -1)
+#define DQUOT_OFF(dev) quota_off(dev, -1)
+
+#else
+
+/*
+ * NO-OP when quota not configured.
+ */
+#define DQUOT_INIT(inode) do { } while(0)
+#define DQUOT_DROP(inode) do { } while(0)
+#define DQUOT_PREALLOC_BLOCK(sb, inode, nr) (0)
+#define DQUOT_ALLOC_BLOCK(sb, inode, nr) (0)
+#define DQUOT_ALLOC_INODE(sb, inode) (0)
+#define DQUOT_FREE_BLOCK(sb, inode, nr) do { } while(0)
+#define DQUOT_FREE_INODE(sb, inode) do { } while(0)
+#define DQUOT_SYNC(dev) do { } while(0)
+#define DQUOT_OFF(dev) do { } while(0)
+
+/*
+ * Special case expands to a simple notify_change.
+ */
+#define DQUOT_TRANSFER(dentry, iattr) notify_change(dentry, iattr)
+
+#endif /* CONFIG_QUOTA */
+#endif /* _LINUX_QUOTAOPS_ */
diff --git a/pfinet/linux-src/include/linux/raid0.h b/pfinet/linux-src/include/linux/raid0.h
new file mode 100644
index 00000000..e1ae51c0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/raid0.h
@@ -0,0 +1,27 @@
+#ifndef _RAID0_H
+#define _RAID0_H
+
+struct strip_zone
+{
+ int zone_offset; /* Zone offset in md_dev */
+ int dev_offset; /* Zone offset in real dev */
+ int size; /* Zone size */
+ int nb_dev; /* Number of devices attached to the zone */
+ struct real_dev *dev[MAX_REAL]; /* Devices attached to the zone */
+};
+
+struct raid0_hash
+{
+ struct strip_zone *zone0, *zone1;
+};
+
+struct raid0_data
+{
+ struct raid0_hash *hash_table; /* Dynamically allocated */
+ struct strip_zone *strip_zone; /* This one too */
+ int nr_strip_zones;
+ struct strip_zone *smallest;
+ int nr_zones;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/raid1.h b/pfinet/linux-src/include/linux/raid1.h
new file mode 100644
index 00000000..4b031e68
--- /dev/null
+++ b/pfinet/linux-src/include/linux/raid1.h
@@ -0,0 +1,49 @@
+#ifndef _RAID1_H
+#define _RAID1_H
+
+#include <linux/md.h>
+
+struct mirror_info {
+ int number;
+ int raid_disk;
+ kdev_t dev;
+ int next;
+ int sect_limit;
+
+ /*
+ * State bits:
+ */
+ int operational;
+ int write_only;
+ int spare;
+};
+
+struct raid1_data {
+ struct md_dev *mddev;
+ struct mirror_info mirrors[MD_SB_DISKS]; /* RAID1 devices, 2 to MD_SB_DISKS */
+ int raid_disks;
+ int working_disks; /* Number of working disks */
+ int last_used;
+ unsigned long next_sect;
+ int sect_count;
+ int resync_running;
+};
+
+/*
+ * this is our 'private' 'collective' RAID1 buffer head.
+ * it contains information about what kind of IO operations were started
+ * for this RAID5 operation, and about their status:
+ */
+
+struct raid1_bh {
+ unsigned int remaining;
+ int cmd;
+ unsigned long state;
+ struct md_dev *mddev;
+ struct buffer_head *master_bh;
+ struct buffer_head *mirror_bh [MD_SB_DISKS];
+ struct buffer_head bh_req;
+ struct buffer_head *next_retry;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/raid5.h b/pfinet/linux-src/include/linux/raid5.h
new file mode 100644
index 00000000..5efd211a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/raid5.h
@@ -0,0 +1,110 @@
+#ifndef _RAID5_H
+#define _RAID5_H
+
+#ifdef __KERNEL__
+#include <linux/md.h>
+#include <asm/atomic.h>
+
+struct disk_info {
+ kdev_t dev;
+ int operational;
+ int number;
+ int raid_disk;
+ int write_only;
+ int spare;
+};
+
+struct stripe_head {
+ struct stripe_head *hash_next, **hash_pprev; /* hash pointers */
+ struct stripe_head *free_next; /* pool of free sh's */
+ struct buffer_head *buffer_pool; /* pool of free buffers */
+ struct buffer_head *bh_pool; /* pool of free bh's */
+ struct raid5_data *raid_conf;
+ struct buffer_head *bh_old[MD_SB_DISKS]; /* disk image */
+ struct buffer_head *bh_new[MD_SB_DISKS]; /* buffers of the MD device (present in buffer cache) */
+ struct buffer_head *bh_copy[MD_SB_DISKS]; /* copy on write of bh_new (bh_new can change from under us) */
+ struct buffer_head *bh_req[MD_SB_DISKS]; /* copy of bh_new (only the buffer heads), queued to the lower levels */
+ int cmd_new[MD_SB_DISKS]; /* READ/WRITE for new */
+ int new[MD_SB_DISKS]; /* buffer added since the last handle_stripe() */
+ unsigned long sector; /* sector of this row */
+ int size; /* buffers size */
+ int pd_idx; /* parity disk index */
+ int nr_pending; /* nr of pending cmds */
+ unsigned long state; /* state flags */
+ int cmd; /* stripe cmd */
+ int count; /* nr of waiters */
+ int write_method; /* reconstruct-write / read-modify-write */
+ int phase; /* PHASE_BEGIN, ..., PHASE_COMPLETE */
+ struct wait_queue *wait; /* processes waiting for this stripe */
+};
+
+/*
+ * Phase
+ */
+#define PHASE_BEGIN 0
+#define PHASE_READ_OLD 1
+#define PHASE_WRITE 2
+#define PHASE_READ 3
+#define PHASE_COMPLETE 4
+
+/*
+ * Write method
+ */
+#define METHOD_NONE 0
+#define RECONSTRUCT_WRITE 1
+#define READ_MODIFY_WRITE 2
+
+/*
+ * Stripe state
+ */
+#define STRIPE_LOCKED 0
+#define STRIPE_ERROR 1
+
+/*
+ * Stripe commands
+ */
+#define STRIPE_NONE 0
+#define STRIPE_WRITE 1
+#define STRIPE_READ 2
+
+struct raid5_data {
+ struct stripe_head **stripe_hashtbl;
+ struct md_dev *mddev;
+ struct md_thread *thread, *resync_thread;
+ struct disk_info disks[MD_SB_DISKS];
+ struct disk_info *spare;
+ int buffer_size;
+ int chunk_size, level, algorithm;
+ int raid_disks, working_disks, failed_disks;
+ int sector_count;
+ unsigned long next_sector;
+ atomic_t nr_handle;
+ struct stripe_head *next_free_stripe;
+ int nr_stripes;
+ int resync_parity;
+ int max_nr_stripes;
+ int clock;
+ int nr_hashed_stripes;
+ int nr_locked_stripes;
+ int nr_pending_stripes;
+ int nr_cached_stripes;
+
+ /*
+ * Free stripes pool
+ */
+ int nr_free_sh;
+ struct stripe_head *free_sh_list;
+ struct wait_queue *wait_for_stripe;
+};
+
+#endif
+
+/*
+ * Our supported algorithms
+ */
+#define ALGORITHM_LEFT_ASYMMETRIC 0
+#define ALGORITHM_RIGHT_ASYMMETRIC 1
+#define ALGORITHM_LEFT_SYMMETRIC 2
+#define ALGORITHM_RIGHT_SYMMETRIC 3
+
+#endif
diff --git a/pfinet/linux-src/include/linux/random.h b/pfinet/linux-src/include/linux/random.h
new file mode 100644
index 00000000..58c93b9b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/random.h
@@ -0,0 +1,73 @@
+/*
+ * include/linux/random.h
+ *
+ * Include file for the random number generator.
+ */
+
+#ifndef _LINUX_RANDOM_H
+#define _LINUX_RANDOM_H
+
+#include <linux/ioctl.h>
+
+/* ioctl()'s for the random number generator */
+
+/* Get the entropy count. */
+#define RNDGETENTCNT _IOR( 'R', 0x00, int )
+
+/* Add to (or subtract from) the entropy count. (Superuser only.) */
+#define RNDADDTOENTCNT _IOW( 'R', 0x01, int )
+
+/* Get the contents of the entropy pool. (Superuser only.) */
+#define RNDGETPOOL _IOR( 'R', 0x02, int [2] )
+
+/*
+ * Write bytes into the entropy pool and add to the entropy count.
+ * (Superuser only.)
+ */
+#define RNDADDENTROPY _IOW( 'R', 0x03, int [2] )
+
+/* Clear entropy count to 0. (Superuser only.) */
+#define RNDZAPENTCNT _IO( 'R', 0x04 )
+
+/* Clear the entropy pool and associated counters. (Superuser only.) */
+#define RNDCLEARPOOL _IO( 'R', 0x06 )
+
+struct rand_pool_info {
+ int entropy_count;
+ int buf_size;
+ __u32 buf[0];
+};
+
+/* Exported functions */
+
+#ifdef __KERNEL__
+
+extern void rand_initialize(void);
+extern void rand_initialize_irq(int irq);
+extern void rand_initialize_blkdev(int irq, int mode);
+
+extern void add_keyboard_randomness(unsigned char scancode);
+extern void add_mouse_randomness(__u32 mouse_data);
+extern void add_interrupt_randomness(int irq);
+extern void add_blkdev_randomness(int major);
+
+extern void get_random_bytes(void *buf, int nbytes);
+
+extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
+ __u16 sport, __u16 dport);
+extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
+ __u16 sport, __u16 dport,
+ __u32 sseq, __u32 count,
+ __u32 data);
+extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr,
+ __u32 daddr, __u16 sport,
+ __u16 dport, __u32 sseq,
+ __u32 count, __u32 maxdiff);
+
+#ifndef MODULE
+extern struct file_operations random_fops, urandom_fops;
+#endif
+
+#endif /* __KERNEL___ */
+
+#endif /* _LINUX_RANDOM_H */
diff --git a/pfinet/linux-src/include/linux/reboot.h b/pfinet/linux-src/include/linux/reboot.h
new file mode 100644
index 00000000..463350f5
--- /dev/null
+++ b/pfinet/linux-src/include/linux/reboot.h
@@ -0,0 +1,52 @@
+#ifndef _LINUX_REBOOT_H
+#define _LINUX_REBOOT_H
+
+/*
+ * Magic values required to use _reboot() system call.
+ */
+
+#define LINUX_REBOOT_MAGIC1 0xfee1dead
+#define LINUX_REBOOT_MAGIC2 672274793
+#define LINUX_REBOOT_MAGIC2A 85072278
+#define LINUX_REBOOT_MAGIC2B 369367448
+
+
+/*
+ * Commands accepted by the _reboot() system call.
+ *
+ * RESTART Restart system using default command and mode.
+ * HALT Stop OS and give system control to ROM monitor, if any.
+ * CAD_ON Ctrl-Alt-Del sequence causes RESTART command.
+ * CAD_OFF Ctrl-Alt-Del sequence sends SIGINT to init task.
+ * POWER_OFF Stop OS and remove all power from system, if possible.
+ * RESTART2 Restart system using given command string.
+ */
+
+#define LINUX_REBOOT_CMD_RESTART 0x01234567
+#define LINUX_REBOOT_CMD_HALT 0xCDEF0123
+#define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
+#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
+#define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
+#define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
+
+
+#ifdef __KERNEL__
+
+#include <linux/notifier.h>
+
+extern struct notifier_block *reboot_notifier_list;
+extern int register_reboot_notifier(struct notifier_block *);
+extern int unregister_reboot_notifier(struct notifier_block *);
+
+
+/*
+ * Architecture-specific implementations of sys_reboot commands.
+ */
+
+extern void machine_restart(char *cmd);
+extern void machine_halt(void);
+extern void machine_power_off(void);
+
+#endif
+
+#endif /* _LINUX_REBOOT_H */
diff --git a/pfinet/linux-src/include/linux/resource.h b/pfinet/linux-src/include/linux/resource.h
new file mode 100644
index 00000000..f3bffbd7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/resource.h
@@ -0,0 +1,60 @@
+#ifndef _LINUX_RESOURCE_H
+#define _LINUX_RESOURCE_H
+
+#include <linux/time.h>
+
+/*
+ * Resource control/accounting header file for linux
+ */
+
+/*
+ * Definition of struct rusage taken from BSD 4.3 Reno
+ *
+ * We don't support all of these yet, but we might as well have them....
+ * Otherwise, each time we add new items, programs which depend on this
+ * structure will lose. This reduces the chances of that happening.
+ */
+#define RUSAGE_SELF 0
+#define RUSAGE_CHILDREN (-1)
+#define RUSAGE_BOTH (-2) /* sys_wait4() uses this */
+
+struct rusage {
+ struct timeval ru_utime; /* user time used */
+ struct timeval ru_stime; /* system time used */
+ long ru_maxrss; /* maximum resident set size */
+ long ru_ixrss; /* integral shared memory size */
+ long ru_idrss; /* integral unshared data size */
+ long ru_isrss; /* integral unshared stack size */
+ long ru_minflt; /* page reclaims */
+ long ru_majflt; /* page faults */
+ long ru_nswap; /* swaps */
+ long ru_inblock; /* block input operations */
+ long ru_oublock; /* block output operations */
+ long ru_msgsnd; /* messages sent */
+ long ru_msgrcv; /* messages received */
+ long ru_nsignals; /* signals received */
+ long ru_nvcsw; /* voluntary context switches */
+ long ru_nivcsw; /* involuntary " */
+};
+
+#define RLIM_INFINITY ((long)(~0UL>>1))
+
+struct rlimit {
+ long rlim_cur;
+ long rlim_max;
+};
+
+#define PRIO_MIN (-20)
+#define PRIO_MAX 20
+
+#define PRIO_PROCESS 0
+#define PRIO_PGRP 1
+#define PRIO_USER 2
+
+/*
+ * Due to binary compatibility, the actual resource numbers
+ * may be different for different linux versions..
+ */
+#include <asm/resource.h>
+
+#endif
diff --git a/pfinet/linux-src/include/linux/rocket.h b/pfinet/linux-src/include/linux/rocket.h
new file mode 100644
index 00000000..2019d4d3
--- /dev/null
+++ b/pfinet/linux-src/include/linux/rocket.h
@@ -0,0 +1,55 @@
+/*
+ * This file contains the exported interface of the rocket driver to
+ * its configuration program.
+ */
+
+struct rocket_config {
+ int line;
+ int flags;
+ int closing_wait;
+ int close_delay;
+ int port;
+ int reserved[32];
+};
+
+struct rocket_ports {
+ int tty_major;
+ int callout_major;
+ int port_bitmap[4];
+ int reserved[32];
+};
+
+/*
+ * Rocketport flags
+ */
+#define ROCKET_CALLOUT_NOHUP 0x00000001
+#define ROCKET_FORCE_CD 0x00000002
+#define ROCKET_HUP_NOTIFY 0x00000004
+#define ROCKET_SPLIT_TERMIOS 0x00000008
+#define ROCKET_SPD_MASK 0x00000070
+#define ROCKET_SPD_HI 0x00000010 /* Use 56000 instead of 38400 bps */
+#define ROCKET_SPD_VHI 0x00000020 /* Use 115200 instead of 38400 bps*/
+#define ROCKET_SPD_SHI 0x00000030 /* Use 230400 instead of 38400 bps*/
+#define ROCKET_SPD_WARP 0x00000040 /* Use 460800 instead of 38400 bps*/
+#define ROCKET_SAK 0x00000080
+#define ROCKET_SESSION_LOCKOUT 0x00000100
+#define ROCKET_PGRP_LOCKOUT 0x00000200
+
+#define ROCKET_FLAGS 0x000003FF
+
+#define ROCKET_USR_MASK 0x0071 /* Legal flags that non-privileged
+ * users can set or reset */
+
+/*
+ * For closing_wait and closing_wait2
+ */
+#define ROCKET_CLOSING_WAIT_NONE 65535
+#define ROCKET_CLOSING_WAIT_INF 0
+
+/*
+ * Rocketport ioctls -- "RP"
+ */
+#define RCKP_GET_STRUCT 0x00525001
+#define RCKP_GET_CONFIG 0x00525002
+#define RCKP_SET_CONFIG 0x00525003
+#define RCKP_GET_PORTS 0x00525004
diff --git a/pfinet/linux-src/include/linux/romfs_fs.h b/pfinet/linux-src/include/linux/romfs_fs.h
new file mode 100644
index 00000000..844e22f9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/romfs_fs.h
@@ -0,0 +1,62 @@
+#ifndef __LINUX_ROMFS_FS_H
+#define __LINUX_ROMFS_FS_H
+
+/* The basic structures of the romfs filesystem */
+
+#define ROMBSIZE BLOCK_SIZE
+#define ROMBSBITS BLOCK_SIZE_BITS
+#define ROMBMASK (ROMBSIZE-1)
+#define ROMFS_MAGIC 0x7275
+
+#define ROMFS_MAXFN 128
+
+#define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
+#define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
+#define __mk4(a,b,c,d) htonl(__mkl(__mkw(a,b),__mkw(c,d)))
+#define ROMSB_WORD0 __mk4('-','r','o','m')
+#define ROMSB_WORD1 __mk4('1','f','s','-')
+
+/* On-disk "super block" */
+
+struct romfs_super_block {
+ __u32 word0;
+ __u32 word1;
+ __u32 size;
+ __u32 checksum;
+ char name[0]; /* volume name */
+};
+
+/* On disk inode */
+
+struct romfs_inode {
+ __u32 next; /* low 4 bits see ROMFH_ */
+ __u32 spec;
+ __u32 size;
+ __u32 checksum;
+ char name[0];
+};
+
+#define ROMFH_TYPE 7
+#define ROMFH_HRD 0
+#define ROMFH_DIR 1
+#define ROMFH_REG 2
+#define ROMFH_SYM 3
+#define ROMFH_BLK 4
+#define ROMFH_CHR 5
+#define ROMFH_SCK 6
+#define ROMFH_FIF 7
+#define ROMFH_EXEC 8
+
+/* Alignment */
+
+#define ROMFH_SIZE 16
+#define ROMFH_PAD (ROMFH_SIZE-1)
+#define ROMFH_MASK (~ROMFH_PAD)
+
+#ifdef __KERNEL__
+
+/* Not much now */
+extern int init_romfs_fs(void);
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/pfinet/linux-src/include/linux/romfs_fs_i.h b/pfinet/linux-src/include/linux/romfs_fs_i.h
new file mode 100644
index 00000000..1ffe4b7d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/romfs_fs_i.h
@@ -0,0 +1,11 @@
+#ifndef __ROMFS_FS_I
+#define __ROMFS_FS_I
+
+/* inode in-kernel data */
+
+struct romfs_inode_info {
+ unsigned long i_metasize; /* size of non-data area */
+ unsigned long i_dataoffset; /* from the start of fs */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/romfs_fs_sb.h b/pfinet/linux-src/include/linux/romfs_fs_sb.h
new file mode 100644
index 00000000..02da2280
--- /dev/null
+++ b/pfinet/linux-src/include/linux/romfs_fs_sb.h
@@ -0,0 +1,10 @@
+#ifndef __ROMFS_FS_SB
+#define __ROMFS_FS_SB
+
+/* romfs superblock in-core data */
+
+struct romfs_sb_info {
+ unsigned long s_maxsize;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/rose.h b/pfinet/linux-src/include/linux/rose.h
new file mode 100644
index 00000000..c7b4b184
--- /dev/null
+++ b/pfinet/linux-src/include/linux/rose.h
@@ -0,0 +1,87 @@
+/*
+ * These are the public elements of the Linux kernel Rose implementation.
+ * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the
+ * definition of the ax25_address structure.
+ */
+
+#ifndef ROSE_KERNEL_H
+#define ROSE_KERNEL_H
+
+#define ROSE_MTU 251
+
+#define ROSE_MAX_DIGIS 6
+
+#define ROSE_DEFER 1
+#define ROSE_T1 2
+#define ROSE_T2 3
+#define ROSE_T3 4
+#define ROSE_IDLE 5
+#define ROSE_QBITINCL 6
+#define ROSE_HOLDBACK 7
+
+#define SIOCRSGCAUSE (SIOCPROTOPRIVATE+0)
+#define SIOCRSSCAUSE (SIOCPROTOPRIVATE+1)
+#define SIOCRSL2CALL (SIOCPROTOPRIVATE+2)
+#define SIOCRSSL2CALL (SIOCPROTOPRIVATE+2)
+#define SIOCRSACCEPT (SIOCPROTOPRIVATE+3)
+#define SIOCRSCLRRT (SIOCPROTOPRIVATE+4)
+#define SIOCRSGL2CALL (SIOCPROTOPRIVATE+5)
+#define SIOCRSGFACILITIES (SIOCPROTOPRIVATE+6)
+
+#define ROSE_DTE_ORIGINATED 0x00
+#define ROSE_NUMBER_BUSY 0x01
+#define ROSE_INVALID_FACILITY 0x03
+#define ROSE_NETWORK_CONGESTION 0x05
+#define ROSE_OUT_OF_ORDER 0x09
+#define ROSE_ACCESS_BARRED 0x0B
+#define ROSE_NOT_OBTAINABLE 0x0D
+#define ROSE_REMOTE_PROCEDURE 0x11
+#define ROSE_LOCAL_PROCEDURE 0x13
+#define ROSE_SHIP_ABSENT 0x39
+
+typedef struct {
+ char rose_addr[5];
+} rose_address;
+
+struct sockaddr_rose {
+ sa_family_t srose_family;
+ rose_address srose_addr;
+ ax25_address srose_call;
+ int srose_ndigis;
+ ax25_address srose_digi;
+};
+
+struct full_sockaddr_rose {
+ sa_family_t srose_family;
+ rose_address srose_addr;
+ ax25_address srose_call;
+ unsigned int srose_ndigis;
+ ax25_address srose_digis[ROSE_MAX_DIGIS];
+};
+
+struct rose_route_struct {
+ rose_address address;
+ unsigned short mask;
+ ax25_address neighbour;
+ char device[16];
+ unsigned char ndigis;
+ ax25_address digipeaters[AX25_MAX_DIGIS];
+};
+
+struct rose_cause_struct {
+ unsigned char cause;
+ unsigned char diagnostic;
+};
+
+struct rose_facilities_struct {
+ rose_address source_addr, dest_addr;
+ ax25_address source_call, dest_call;
+ unsigned char source_ndigis, dest_ndigis;
+ ax25_address source_digis[ROSE_MAX_DIGIS];
+ ax25_address dest_digis[ROSE_MAX_DIGIS];
+ unsigned int rand;
+ rose_address fail_addr;
+ ax25_address fail_call;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/route.h b/pfinet/linux-src/include/linux/route.h
new file mode 100644
index 00000000..e670dbac
--- /dev/null
+++ b/pfinet/linux-src/include/linux/route.h
@@ -0,0 +1,70 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the IP router interface.
+ *
+ * Version: @(#)route.h 1.0.3 05/27/93
+ *
+ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988
+ * for the purposes of compatibility only.
+ *
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * Changes:
+ * Mike McLagan : Routing by source
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_ROUTE_H
+#define _LINUX_ROUTE_H
+
+#include <linux/if.h>
+
+
+/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */
+struct rtentry
+{
+ unsigned long rt_pad1;
+ struct sockaddr rt_dst; /* target address */
+ struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */
+ struct sockaddr rt_genmask; /* target network mask (IP) */
+ unsigned short rt_flags;
+ short rt_pad2;
+ unsigned long rt_pad3;
+ void *rt_pad4;
+ short rt_metric; /* +1 for binary compatibility! */
+ char *rt_dev; /* forcing the device at add */
+ unsigned long rt_mtu; /* per route MTU/Window */
+#ifndef __KERNEL__
+#define rt_mss rt_mtu /* Compatibility :-( */
+#endif
+ unsigned long rt_window; /* Window clamping */
+ unsigned short rt_irtt; /* Initial RTT */
+};
+
+
+#define RTF_UP 0x0001 /* route usable */
+#define RTF_GATEWAY 0x0002 /* destination is a gateway */
+#define RTF_HOST 0x0004 /* host entry (net otherwise) */
+#define RTF_REINSTATE 0x0008 /* reinstate route after tmout */
+#define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */
+#define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */
+#define RTF_MTU 0x0040 /* specific MTU for this route */
+#define RTF_MSS RTF_MTU /* Compatibility :-( */
+#define RTF_WINDOW 0x0080 /* per route window clamping */
+#define RTF_IRTT 0x0100 /* Initial round trip time */
+#define RTF_REJECT 0x0200 /* Reject route */
+
+/*
+ * <linux/ipv6_route.h> uses RTF values >= 64k
+ */
+
+
+
+#endif /* _LINUX_ROUTE_H */
+
diff --git a/pfinet/linux-src/include/linux/rpcsock.h b/pfinet/linux-src/include/linux/rpcsock.h
new file mode 100644
index 00000000..80f1fc4c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/rpcsock.h
@@ -0,0 +1,121 @@
+/*
+ * rpcsock.h Declarations for the RPC call interface.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+
+#ifndef _LINUX_RPCSOCK_H
+#define _LINUX_RPCSOCK_H
+
+/*
+ * The rpcsock code maintains an estimate on the maximum number of out-
+ * standing RPC requests, using the congestion avoidance implemented in
+ * 44BSD. This is basically the Van Jacobson slow start algorithm: If a
+ * retransmit occurs, the congestion window is halved; otherwise, it is
+ * incremented by 1/cwnd when a reply is received and a full number of
+ * requests are outstanding.
+ *
+ * Upper procedures may check whether a request would block waiting for
+ * a free RPC slot by using the RPC_CONGESTED() macro.
+ *
+ * Note: on machines with low memory we should probably use a smaller
+ * MAXREQS value: At 32 outstanding reqs with 8 megs of RAM, fragment
+ * reassembly will frequently run out of memory.
+ */
+#define RPC_MAXREQS 32
+#define RPC_CWNDSCALE 256
+#define RPC_MAXCWND (RPC_MAXREQS * RPC_CWNDSCALE)
+/* #define RPC_INITCWND (RPC_MAXCWND / 2) */
+#define RPC_INITCWND RPC_CWNDSCALE
+#define RPC_CONGESTED(rsock) ((rsock)->cong >= (rsock)->cwnd)
+
+/* RPC reply header size: xid, direction, status, accept_status (verifier
+ * size computed separately)
+ */
+#define RPC_HDRSIZE (4 * 4)
+
+/*
+ * This describes a timeout strategy
+ */
+struct rpc_timeout {
+ unsigned long to_initval,
+ to_maxval,
+ to_increment;
+ int to_retries;
+ char to_exponential;
+};
+
+/*
+ * This describes a complete RPC request
+ */
+struct rpc_ioreq {
+ struct rpc_wait * rq_slot;
+ struct sockaddr * rq_addr;
+ int rq_alen;
+ struct iovec rq_svec[UIO_FASTIOV];
+ unsigned int rq_snr;
+ unsigned long rq_slen;
+ struct iovec rq_rvec[UIO_FASTIOV];
+ unsigned int rq_rnr;
+ unsigned long rq_rlen;
+};
+
+/*
+ * This is the callback handler for async RPC.
+ */
+struct rpc_wait;
+typedef void (*rpc_callback_fn_t)(int, struct rpc_wait *, void *);
+
+/*
+ * Wait information. This struct defines all the state of an RPC
+ * request currently in flight.
+ */
+struct rpc_wait {
+ struct rpc_sock * w_sock;
+ struct rpc_wait * w_prev;
+ struct rpc_wait * w_next;
+ struct rpc_ioreq * w_req;
+ int w_result;
+ struct wait_queue * w_wait;
+ rpc_callback_fn_t w_handler;
+ void * w_cdata;
+ char w_queued;
+ char w_gotit;
+ __u32 w_xid;
+};
+
+struct rpc_sock {
+ struct file * file;
+ struct socket * sock;
+ struct sock * inet;
+ struct rpc_wait waiting[RPC_MAXREQS];
+ unsigned long cong;
+ unsigned long cwnd;
+ struct rpc_wait * pending;
+ struct rpc_wait * free;
+ struct wait_queue * backlog;
+ struct wait_queue * shutwait;
+ int shutdown;
+};
+
+#ifdef __KERNEL__
+
+/* rpc_call: Call synchronously */
+int rpc_call(struct rpc_sock *, struct rpc_ioreq *,
+ struct rpc_timeout *);
+/* These implement asynch calls for nfsiod: Process calls rpc_reserve and
+ * rpc_transmits, then passes the request to nfsiod, which collects the
+ * results via rpc_doio
+ */
+int rpc_reserve(struct rpc_sock *, struct rpc_ioreq *, int);
+void rpc_release(struct rpc_sock *, struct rpc_ioreq *);
+int rpc_transmit(struct rpc_sock *, struct rpc_ioreq *);
+int rpc_doio(struct rpc_sock *, struct rpc_ioreq *,
+ struct rpc_timeout *, int);
+struct rpc_sock * rpc_makesock(struct file *);
+int rpc_closesock(struct rpc_sock *);
+
+#endif /* __KERNEL__*/
+
+#endif /* _LINUX_RPCSOCK_H */
diff --git a/pfinet/linux-src/include/linux/rtnetlink.h b/pfinet/linux-src/include/linux/rtnetlink.h
new file mode 100644
index 00000000..b339f652
--- /dev/null
+++ b/pfinet/linux-src/include/linux/rtnetlink.h
@@ -0,0 +1,667 @@
+#ifndef __LINUX_RTNETLINK_H
+#define __LINUX_RTNETLINK_H
+
+#include <linux/config.h>
+#include <linux/netlink.h>
+
+#define RTNL_DEBUG 1
+
+
+/****
+ * Routing/neighbour discovery messages.
+ ****/
+
+/* Types of messages */
+
+#define RTM_BASE 0x10
+
+#define RTM_NEWLINK (RTM_BASE+0)
+#define RTM_DELLINK (RTM_BASE+1)
+#define RTM_GETLINK (RTM_BASE+2)
+
+#define RTM_NEWADDR (RTM_BASE+4)
+#define RTM_DELADDR (RTM_BASE+5)
+#define RTM_GETADDR (RTM_BASE+6)
+
+#define RTM_NEWROUTE (RTM_BASE+8)
+#define RTM_DELROUTE (RTM_BASE+9)
+#define RTM_GETROUTE (RTM_BASE+10)
+
+#define RTM_NEWNEIGH (RTM_BASE+12)
+#define RTM_DELNEIGH (RTM_BASE+13)
+#define RTM_GETNEIGH (RTM_BASE+14)
+
+#define RTM_NEWRULE (RTM_BASE+16)
+#define RTM_DELRULE (RTM_BASE+17)
+#define RTM_GETRULE (RTM_BASE+18)
+
+#define RTM_NEWQDISC (RTM_BASE+20)
+#define RTM_DELQDISC (RTM_BASE+21)
+#define RTM_GETQDISC (RTM_BASE+22)
+
+#define RTM_NEWTCLASS (RTM_BASE+24)
+#define RTM_DELTCLASS (RTM_BASE+25)
+#define RTM_GETTCLASS (RTM_BASE+26)
+
+#define RTM_NEWTFILTER (RTM_BASE+28)
+#define RTM_DELTFILTER (RTM_BASE+29)
+#define RTM_GETTFILTER (RTM_BASE+30)
+
+#define RTM_MAX (RTM_BASE+31)
+
+/*
+ Generic structure for encapsulation optional route information.
+ It is reminiscent of sockaddr, but with sa_family replaced
+ with attribute type.
+ */
+
+struct rtattr
+{
+ unsigned short rta_len;
+ unsigned short rta_type;
+};
+
+/* Macros to handle rtattributes */
+
+#define RTA_ALIGNTO 4
+#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
+#define RTA_OK(rta,len) ((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \
+ (rta)->rta_len <= (len))
+#define RTA_NEXT(rta,attrlen) ((attrlen) -= RTA_ALIGN((rta)->rta_len), \
+ (struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))
+#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
+#define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len))
+#define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
+#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
+
+
+
+
+/******************************************************************************
+ * Definitions used in routing table administation.
+ ****/
+
+struct rtmsg
+{
+ unsigned char rtm_family;
+ unsigned char rtm_dst_len;
+ unsigned char rtm_src_len;
+ unsigned char rtm_tos;
+
+ unsigned char rtm_table; /* Routing table id */
+ unsigned char rtm_protocol; /* Routing protocol; see below */
+ unsigned char rtm_scope; /* See below */
+ unsigned char rtm_type; /* See below */
+
+ unsigned rtm_flags;
+};
+
+/* rtm_type */
+
+enum
+{
+ RTN_UNSPEC,
+ RTN_UNICAST, /* Gateway or direct route */
+ RTN_LOCAL, /* Accept locally */
+ RTN_BROADCAST, /* Accept locally as broadcast,
+ send as broadcast */
+ RTN_ANYCAST, /* Accept locally as broadcast,
+ but send as unicast */
+ RTN_MULTICAST, /* Multicast route */
+ RTN_BLACKHOLE, /* Drop */
+ RTN_UNREACHABLE, /* Destination is unreachable */
+ RTN_PROHIBIT, /* Administratively prohibited */
+ RTN_THROW, /* Not in this table */
+ RTN_NAT, /* Translate this address */
+ RTN_XRESOLVE, /* Use external resolver */
+};
+
+#define RTN_MAX RTN_XRESOLVE
+
+
+/* rtm_protocol */
+
+#define RTPROT_UNSPEC 0
+#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects;
+ not used by current IPv4 */
+#define RTPROT_KERNEL 2 /* Route installed by kernel */
+#define RTPROT_BOOT 3 /* Route installed during boot */
+#define RTPROT_STATIC 4 /* Route installed by administrator */
+
+/* Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
+ they just passed from user and back as is.
+ It will be used by hypothetical multiple routing daemons.
+ Note that protocol values should be standardized in order to
+ avoid conflicts.
+ */
+
+#define RTPROT_GATED 8 /* Apparently, GateD */
+#define RTPROT_RA 9 /* RDISC/ND router advertisments */
+#define RTPROT_MRT 10 /* Merit MRT */
+#define RTPROT_ZEBRA 11 /* Zebra */
+#define RTPROT_BIRD 12 /* BIRD */
+
+/* rtm_scope
+
+ Really it is not scope, but sort of distance to the destination.
+ NOWHERE are reserved for not existing destinations, HOST is our
+ local addresses, LINK are destinations, located on directly attached
+ link and UNIVERSE is everywhere in the Universe.
+
+ Intermediate values are also possible f.e. interior routes
+ could be assigned a value between UNIVERSE and LINK.
+*/
+
+enum rt_scope_t
+{
+ RT_SCOPE_UNIVERSE=0,
+/* User defined values */
+ RT_SCOPE_SITE=200,
+ RT_SCOPE_LINK=253,
+ RT_SCOPE_HOST=254,
+ RT_SCOPE_NOWHERE=255
+};
+
+/* rtm_flags */
+
+#define RTM_F_NOTIFY 0x100 /* Notify user of route change */
+#define RTM_F_CLONED 0x200 /* This route is cloned */
+#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */
+
+/* Reserved table identifiers */
+
+enum rt_class_t
+{
+ RT_TABLE_UNSPEC=0,
+/* User defined values */
+ RT_TABLE_DEFAULT=253,
+ RT_TABLE_MAIN=254,
+ RT_TABLE_LOCAL=255
+};
+#define RT_TABLE_MAX RT_TABLE_LOCAL
+
+
+
+/* Routing message attributes */
+
+enum rtattr_type_t
+{
+ RTA_UNSPEC,
+ RTA_DST,
+ RTA_SRC,
+ RTA_IIF,
+ RTA_OIF,
+ RTA_GATEWAY,
+ RTA_PRIORITY,
+ RTA_PREFSRC,
+ RTA_METRICS,
+ RTA_MULTIPATH,
+ RTA_PROTOINFO,
+ RTA_FLOW,
+ RTA_CACHEINFO
+};
+
+#define RTA_MAX RTA_CACHEINFO
+
+#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
+#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
+
+/* RTM_MULTIPATH --- array of struct rtnexthop.
+ *
+ * "struct rtnexthop" describres all necessary nexthop information,
+ * i.e. parameters of path to a destination via this nextop.
+ *
+ * At the moment it is impossible to set different prefsrc, mtu, window
+ * and rtt for different paths from multipath.
+ */
+
+struct rtnexthop
+{
+ unsigned short rtnh_len;
+ unsigned char rtnh_flags;
+ unsigned char rtnh_hops;
+ int rtnh_ifindex;
+};
+
+/* rtnh_flags */
+
+#define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
+#define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
+#define RTNH_F_ONLINK 4 /* Gateway is forced on link */
+
+/* Macros to handle hexthops */
+
+#define RTNH_ALIGNTO 4
+#define RTNH_ALIGN(len) ( ((len)+RTNH_ALIGNTO-1) & ~(RTNH_ALIGNTO-1) )
+#define RTNH_OK(rtnh,len) ((rtnh)->rtnh_len >= sizeof(struct rtnexthop) && \
+ ((int)(rtnh)->rtnh_len) <= (len))
+#define RTNH_NEXT(rtnh) ((struct rtnexthop*)(((char*)(rtnh)) + RTNH_ALIGN((rtnh)->rtnh_len)))
+#define RTNH_LENGTH(len) (RTNH_ALIGN(sizeof(struct rtnexthop)) + (len))
+#define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len))
+#define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0)))
+
+/* RTM_CACHEINFO */
+
+struct rta_cacheinfo
+{
+ __u32 rta_clntref;
+ __u32 rta_lastuse;
+ __s32 rta_expires;
+ __u32 rta_error;
+ __u32 rta_used;
+};
+
+/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
+
+enum
+{
+ RTAX_UNSPEC,
+ RTAX_LOCK,
+ RTAX_MTU,
+ RTAX_WINDOW,
+ RTAX_RTT,
+ RTAX_HOPS,
+ RTAX_SSTHRESH,
+ RTAX_CWND,
+};
+
+#define RTAX_MAX RTAX_CWND
+
+
+
+/*********************************************************
+ * Interface address.
+ ****/
+
+struct ifaddrmsg
+{
+ unsigned char ifa_family;
+ unsigned char ifa_prefixlen; /* The prefix length */
+ unsigned char ifa_flags; /* Flags */
+ unsigned char ifa_scope; /* See above */
+ int ifa_index; /* Link index */
+};
+
+enum
+{
+ IFA_UNSPEC,
+ IFA_ADDRESS,
+ IFA_LOCAL,
+ IFA_LABEL,
+ IFA_BROADCAST,
+ IFA_ANYCAST,
+ IFA_CACHEINFO
+};
+
+#define IFA_MAX IFA_CACHEINFO
+
+/* ifa_flags */
+
+#define IFA_F_SECONDARY 0x01
+
+#define IFA_F_DEPRECATED 0x20
+#define IFA_F_TENTATIVE 0x40
+#define IFA_F_PERMANENT 0x80
+
+struct ifa_cacheinfo
+{
+ __s32 ifa_prefered;
+ __s32 ifa_valid;
+};
+
+
+#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+
+/*
+ Important comment:
+ IFA_ADDRESS is prefix address, rather than local interface address.
+ It makes no difference for normally configured broadcast interfaces,
+ but for point-to-point IFA_ADDRESS is DESTINATION address,
+ local address is supplied in IFA_LOCAL attribute.
+ */
+
+/**************************************************************
+ * Neighbour discovery.
+ ****/
+
+struct ndmsg
+{
+ unsigned char ndm_family;
+ unsigned char ndm_pad1;
+ unsigned short ndm_pad2;
+ int ndm_ifindex; /* Link index */
+ __u16 ndm_state;
+ __u8 ndm_flags;
+ __u8 ndm_type;
+};
+
+enum
+{
+ NDA_UNSPEC,
+ NDA_DST,
+ NDA_LLADDR,
+ NDA_CACHEINFO
+};
+
+#define NDA_MAX NDA_CACHEINFO
+
+#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
+#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
+
+/*
+ * Neighbor Cache Entry Flags
+ */
+
+#define NTF_PROXY 0x08 /* == ATF_PUBL */
+#define NTF_ROUTER 0x80
+
+/*
+ * Neighbor Cache Entry States.
+ */
+
+#define NUD_INCOMPLETE 0x01
+#define NUD_REACHABLE 0x02
+#define NUD_STALE 0x04
+#define NUD_DELAY 0x08
+#define NUD_PROBE 0x10
+#define NUD_FAILED 0x20
+
+/* Dummy states */
+#define NUD_NOARP 0x40
+#define NUD_PERMANENT 0x80
+#define NUD_NONE 0x00
+
+
+struct nda_cacheinfo
+{
+ __u32 ndm_confirmed;
+ __u32 ndm_used;
+ __u32 ndm_updated;
+ __u32 ndm_refcnt;
+};
+
+/****
+ * General form of address family dependent message.
+ ****/
+
+struct rtgenmsg
+{
+ unsigned char rtgen_family;
+};
+
+/*****************************************************************
+ * Link layer specific messages.
+ ****/
+
+/* struct ifinfomsg
+ * passes link level specific information, not dependent
+ * on network protocol.
+ */
+
+struct ifinfomsg
+{
+ unsigned char ifi_family;
+ unsigned char __ifi_pad;
+ unsigned short ifi_type; /* ARPHRD_* */
+ int ifi_index; /* Link index */
+ unsigned ifi_flags; /* IFF_* flags */
+ unsigned ifi_change; /* IFF_* change mask */
+};
+
+enum
+{
+ IFLA_UNSPEC,
+ IFLA_ADDRESS,
+ IFLA_BROADCAST,
+ IFLA_IFNAME,
+ IFLA_MTU,
+ IFLA_LINK,
+ IFLA_QDISC,
+ IFLA_STATS
+};
+
+
+#define IFLA_MAX IFLA_STATS
+
+#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
+#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
+
+/* ifi_flags.
+
+ IFF_* flags.
+
+ The only change is:
+ IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
+ more not changeable by user. They describe link media
+ characteristics and set by device driver.
+
+ Comments:
+ - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
+ - If neiher of these three flags are set;
+ the interface is NBMA.
+
+ - IFF_MULTICAST does not mean anything special:
+ multicasts can be used on all not-NBMA links.
+ IFF_MULTICAST means that this media uses special encapsulation
+ for multicast frames. Apparently, all IFF_POINTOPOINT and
+ IFF_BROADCAST devices are able to use multicasts too.
+ */
+
+/* ifi_link.
+ For usual devices it is equal ifi_index.
+ If it is a "virtual interface" (f.e. tunnel), ifi_link
+ can point to real physical interface (f.e. for bandwidth calculations),
+ or maybe 0, what means, that real media is unknown (usual
+ for IPIP tunnels, when route to endpoint is allowed to change)
+ */
+
+/*****************************************************************
+ * Traffic control messages.
+ ****/
+
+struct tcmsg
+{
+ unsigned char tcm_family;
+ unsigned char tcm__pad1;
+ unsigned short tcm__pad2;
+ int tcm_ifindex;
+ __u32 tcm_handle;
+ __u32 tcm_parent;
+ __u32 tcm_info;
+};
+
+enum
+{
+ TCA_UNSPEC,
+ TCA_KIND,
+ TCA_OPTIONS,
+ TCA_STATS,
+ TCA_XSTATS,
+ TCA_RATE,
+};
+
+#define TCA_MAX TCA_RATE
+
+#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
+#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
+
+
+/* SUMMARY: maximal rtattr understood by kernel */
+
+#define RTATTR_MAX RTA_MAX
+
+/* RTnetlink multicast groups */
+
+#define RTMGRP_LINK 1
+#define RTMGRP_NOTIFY 2
+#define RTMGRP_NEIGH 4
+#define RTMGRP_TC 8
+
+#define RTMGRP_IPV4_IFADDR 0x10
+#define RTMGRP_IPV4_MROUTE 0x20
+#define RTMGRP_IPV4_ROUTE 0x40
+
+#define RTMGRP_IPV6_IFADDR 0x100
+#define RTMGRP_IPV6_MROUTE 0x200
+#define RTMGRP_IPV6_ROUTE 0x400
+
+/* End of information exported to user level */
+
+#ifdef __KERNEL__
+
+extern atomic_t rtnl_rlockct;
+extern struct wait_queue *rtnl_wait;
+
+extern __inline__ int rtattr_strcmp(struct rtattr *rta, char *str)
+{
+ int len = strlen(str) + 1;
+ return len > rta->rta_len || memcmp(RTA_DATA(rta), str, len);
+}
+
+extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
+
+#ifdef CONFIG_RTNETLINK
+extern struct sock *rtnl;
+
+struct rtnetlink_link
+{
+ int (*doit)(struct sk_buff *, struct nlmsghdr*, void *attr);
+ int (*dumpit)(struct sk_buff *, struct netlink_callback *cb);
+};
+
+extern struct rtnetlink_link * rtnetlink_links[NPROTO];
+extern int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb);
+extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
+
+extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data);
+
+#define RTA_PUT(skb, attrtype, attrlen, data) \
+({ if (skb_tailroom(skb) < (int)RTA_SPACE(attrlen)) goto rtattr_failure; \
+ __rta_fill(skb, attrtype, attrlen, data); })
+
+extern unsigned long rtnl_wlockct;
+
+/* NOTE: these locks are not interrupt safe, are not SMP safe,
+ * they are even not atomic. 8)8)8) ... and it is not a bug.
+ * Really, if these locks will be programmed correctly,
+ * all the addressing/routing machine would become SMP safe,
+ * but is absolutely useless at the moment, because all the kernel
+ * is not reenterable in any case. --ANK
+ *
+ * Well, atomic_* and set_bit provide the only thing here:
+ * gcc is confused not to overoptimize them, that's all.
+ * I remember as gcc splitted ++ operation, but cannot reproduce
+ * it with gcc-2.7.*. --ANK
+ *
+ * One more note: rwlock facility should be written and put
+ * to a kernel wide location: f.e. current implementation of semaphores
+ * (especially, for x86) looks like a wonder. It would be good
+ * to have something similar for rwlock. Recursive lock could be also
+ * useful thing. --ANK
+ */
+
+extern __inline__ int rtnl_shlock_nowait(void)
+{
+ atomic_inc(&rtnl_rlockct);
+ if (test_bit(0, &rtnl_wlockct)) {
+ atomic_dec(&rtnl_rlockct);
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+extern __inline__ void rtnl_shlock(void)
+{
+ while (rtnl_shlock_nowait())
+ sleep_on(&rtnl_wait);
+}
+
+/* Check for possibility to PROMOTE shared lock to exclusive.
+ Shared lock must be already grabbed with rtnl_shlock*().
+ */
+
+extern __inline__ int rtnl_exlock_nowait(void)
+{
+ if (atomic_read(&rtnl_rlockct) > 1)
+ return -EAGAIN;
+ if (test_and_set_bit(0, &rtnl_wlockct))
+ return -EAGAIN;
+ return 0;
+}
+
+extern __inline__ void rtnl_exlock(void)
+{
+ while (rtnl_exlock_nowait())
+ sleep_on(&rtnl_wait);
+}
+
+#if 0
+extern __inline__ void rtnl_shunlock(void)
+{
+ atomic_dec(&rtnl_rlockct);
+ if (atomic_read(&rtnl_rlockct) <= 1) {
+ wake_up(&rtnl_wait);
+ if (rtnl && rtnl->receive_queue.qlen)
+ rtnl->data_ready(rtnl, 0);
+ }
+}
+#else
+
+/* The problem: inline requires to include <net/sock.h> and, hence,
+ almost all of net includes :-(
+ */
+
+#define rtnl_shunlock() ({ \
+ atomic_dec(&rtnl_rlockct); \
+ if (atomic_read(&rtnl_rlockct) <= 1) { \
+ wake_up(&rtnl_wait); \
+ if (rtnl && rtnl->receive_queue.qlen) \
+ rtnl->data_ready(rtnl, 0); \
+ } \
+})
+#endif
+
+/* Release exclusive lock. Note, that we do not wake up rtnetlink socket,
+ * it will be done later after releasing shared lock.
+ */
+
+extern __inline__ void rtnl_exunlock(void)
+{
+ clear_bit(0, &rtnl_wlockct);
+ wake_up(&rtnl_wait);
+}
+
+#else
+
+extern __inline__ void rtnl_shlock(void)
+{
+ while (atomic_read(&rtnl_rlockct))
+ sleep_on(&rtnl_wait);
+ atomic_inc(&rtnl_rlockct);
+}
+
+extern __inline__ void rtnl_shunlock(void)
+{
+ if (atomic_dec_and_test(&rtnl_rlockct))
+ wake_up(&rtnl_wait);
+}
+
+extern __inline__ void rtnl_exlock(void)
+{
+}
+
+extern __inline__ void rtnl_exunlock(void)
+{
+}
+
+#endif
+
+extern void rtnl_lock(void);
+extern void rtnl_unlock(void);
+extern void rtnetlink_init(void);
+
+#endif /* __KERNEL__ */
+
+
+#endif /* __LINUX_RTNETLINK_H */
diff --git a/pfinet/linux-src/include/linux/sc26198.h b/pfinet/linux-src/include/linux/sc26198.h
new file mode 100644
index 00000000..38685e07
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sc26198.h
@@ -0,0 +1,533 @@
+/*****************************************************************************/
+
+/*
+ * sc26198.h -- SC26198 UART hardware info.
+ *
+ * Copyright (C) 1995-1998 Stallion Technologies (support@stallion.oz.au).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*****************************************************************************/
+#ifndef _SC26198_H
+#define _SC26198_H
+/*****************************************************************************/
+
+/*
+ * Define the number of async ports per sc26198 uart device.
+ */
+#define SC26198_PORTS 8
+
+/*
+ * Baud rate timing clocks. All derived from a master 14.7456 MHz clock.
+ */
+#define SC26198_MASTERCLOCK 14745600L
+#define SC26198_DCLK (SC26198_MASTERCLOCK)
+#define SC26198_CCLK (SC26198_MASTERCLOCK / 2)
+#define SC26198_BCLK (SC26198_MASTERCLOCK / 4)
+
+/*
+ * Define internal FIFO sizes for the 26198 ports.
+ */
+#define SC26198_TXFIFOSIZE 16
+#define SC26198_RXFIFOSIZE 16
+
+/*****************************************************************************/
+
+/*
+ * Global register definitions. These registers are global to each 26198
+ * device, not specific ports on it.
+ */
+#define TSTR 0x0d
+#define GCCR 0x0f
+#define ICR 0x1b
+#define WDTRCR 0x1d
+#define IVR 0x1f
+#define BRGTRUA 0x84
+#define GPOSR 0x87
+#define GPOC 0x8b
+#define UCIR 0x8c
+#define CIR 0x8c
+#define BRGTRUB 0x8d
+#define GRXFIFO 0x8e
+#define GTXFIFO 0x8e
+#define GCCR2 0x8f
+#define BRGTRLA 0x94
+#define GPOR 0x97
+#define GPOD 0x9b
+#define BRGTCR 0x9c
+#define GICR 0x9c
+#define BRGTRLB 0x9d
+#define GIBCR 0x9d
+#define GITR 0x9f
+
+/*
+ * Per port channel registers. These are the register offsets within
+ * the port address space, so need to have the port address (0 to 7)
+ * inserted in bit positions 4:6.
+ */
+#define MR0 0x00
+#define MR1 0x01
+#define IOPCR 0x02
+#define BCRBRK 0x03
+#define BCRCOS 0x04
+#define BCRX 0x06
+#define BCRA 0x07
+#define XONCR 0x08
+#define XOFFCR 0x09
+#define ARCR 0x0a
+#define RXCSR 0x0c
+#define TXCSR 0x0e
+#define MR2 0x80
+#define SR 0x81
+#define SCCR 0x81
+#define ISR 0x82
+#define IMR 0x82
+#define TXFIFO 0x83
+#define RXFIFO 0x83
+#define IPR 0x84
+#define IOPIOR 0x85
+#define XISR 0x86
+
+/*
+ * For any given port calculate the address to use to access a specified
+ * register. This is only used for unusual access, mostly this is done
+ * through the assembler access routines.
+ */
+#define SC26198_PORTREG(port,reg) ((((port) & 0x07) << 4) | (reg))
+
+/*****************************************************************************/
+
+/*
+ * Global configuration control register bit definitions.
+ */
+#define GCCR_NOACK 0x00
+#define GCCR_IVRACK 0x02
+#define GCCR_IVRCHANACK 0x04
+#define GCCR_IVRTYPCHANACK 0x06
+#define GCCR_ASYNCCYCLE 0x00
+#define GCCR_SYNCCYCLE 0x40
+
+/*****************************************************************************/
+
+/*
+ * Mode register 0 bit definitions.
+ */
+#define MR0_ADDRNONE 0x00
+#define MR0_AUTOWAKE 0x01
+#define MR0_AUTODOZE 0x02
+#define MR0_AUTOWAKEDOZE 0x03
+#define MR0_SWFNONE 0x00
+#define MR0_SWFTX 0x04
+#define MR0_SWFRX 0x08
+#define MR0_SWFRXTX 0x0c
+#define MR0_TXMASK 0x30
+#define MR0_TXEMPTY 0x00
+#define MR0_TXHIGH 0x10
+#define MR0_TXHALF 0x20
+#define MR0_TXRDY 0x00
+#define MR0_ADDRNT 0x00
+#define MR0_ADDRT 0x40
+#define MR0_SWFNT 0x00
+#define MR0_SWFT 0x80
+
+/*
+ * Mode register 1 bit definitions.
+ */
+#define MR1_CS5 0x00
+#define MR1_CS6 0x01
+#define MR1_CS7 0x02
+#define MR1_CS8 0x03
+#define MR1_PAREVEN 0x00
+#define MR1_PARODD 0x04
+#define MR1_PARENB 0x00
+#define MR1_PARFORCE 0x08
+#define MR1_PARNONE 0x10
+#define MR1_PARSPECIAL 0x18
+#define MR1_ERRCHAR 0x00
+#define MR1_ERRBLOCK 0x20
+#define MR1_ISRUNMASKED 0x00
+#define MR1_ISRMASKED 0x40
+#define MR1_AUTORTS 0x80
+
+/*
+ * Mode register 2 bit definitions.
+ */
+#define MR2_STOP1 0x00
+#define MR2_STOP15 0x01
+#define MR2_STOP2 0x02
+#define MR2_STOP916 0x03
+#define MR2_RXFIFORDY 0x00
+#define MR2_RXFIFOHALF 0x04
+#define MR2_RXFIFOHIGH 0x08
+#define MR2_RXFIFOFULL 0x0c
+#define MR2_AUTOCTS 0x10
+#define MR2_TXRTS 0x20
+#define MR2_MODENORM 0x00
+#define MR2_MODEAUTOECHO 0x40
+#define MR2_MODELOOP 0x80
+#define MR2_MODEREMECHO 0xc0
+
+/*****************************************************************************/
+
+/*
+ * Baud Rate Generator (BRG) selector values.
+ */
+#define BRG_50 0x00
+#define BRG_75 0x01
+#define BRG_150 0x02
+#define BRG_200 0x03
+#define BRG_300 0x04
+#define BRG_450 0x05
+#define BRG_600 0x06
+#define BRG_900 0x07
+#define BRG_1200 0x08
+#define BRG_1800 0x09
+#define BRG_2400 0x0a
+#define BRG_3600 0x0b
+#define BRG_4800 0x0c
+#define BRG_7200 0x0d
+#define BRG_9600 0x0e
+#define BRG_14400 0x0f
+#define BRG_19200 0x10
+#define BRG_28200 0x11
+#define BRG_38400 0x12
+#define BRG_57600 0x13
+#define BRG_115200 0x14
+#define BRG_230400 0x15
+#define BRG_GIN0 0x16
+#define BRG_GIN1 0x17
+#define BRG_CT0 0x18
+#define BRG_CT1 0x19
+#define BRG_RX2TX316 0x1b
+#define BRG_RX2TX31 0x1c
+
+#define SC26198_MAXBAUD 921600
+
+/*****************************************************************************/
+
+/*
+ * Command register command definitions.
+ */
+#define CR_NULL 0x04
+#define CR_ADDRNORMAL 0x0c
+#define CR_RXRESET 0x14
+#define CR_TXRESET 0x1c
+#define CR_CLEARRXERR 0x24
+#define CR_BREAKRESET 0x2c
+#define CR_TXSTARTBREAK 0x34
+#define CR_TXSTOPBREAK 0x3c
+#define CR_RTSON 0x44
+#define CR_RTSOFF 0x4c
+#define CR_ADDRINIT 0x5c
+#define CR_RXERRBLOCK 0x6c
+#define CR_TXSENDXON 0x84
+#define CR_TXSENDXOFF 0x8c
+#define CR_GANGXONSET 0x94
+#define CR_GANGXOFFSET 0x9c
+#define CR_GANGXONINIT 0xa4
+#define CR_GANGXOFFINIT 0xac
+#define CR_HOSTXON 0xb4
+#define CR_HOSTXOFF 0xbc
+#define CR_CANCELXOFF 0xc4
+#define CR_ADDRRESET 0xdc
+#define CR_RESETALLPORTS 0xf4
+#define CR_RESETALL 0xfc
+
+#define CR_RXENABLE 0x01
+#define CR_TXENABLE 0x02
+
+/*****************************************************************************/
+
+/*
+ * Channel status register.
+ */
+#define SR_RXRDY 0x01
+#define SR_RXFULL 0x02
+#define SR_TXRDY 0x04
+#define SR_TXEMPTY 0x08
+#define SR_RXOVERRUN 0x10
+#define SR_RXPARITY 0x20
+#define SR_RXFRAMING 0x40
+#define SR_RXBREAK 0x80
+
+#define SR_RXERRS (SR_RXPARITY | SR_RXFRAMING | SR_RXOVERRUN)
+
+/*****************************************************************************/
+
+/*
+ * Interrupt status register and interrupt mask register bit definitions.
+ */
+#define IR_TXRDY 0x01
+#define IR_RXRDY 0x02
+#define IR_RXBREAK 0x04
+#define IR_XONXOFF 0x10
+#define IR_ADDRRECOG 0x20
+#define IR_RXWATCHDOG 0x40
+#define IR_IOPORT 0x80
+
+/*****************************************************************************/
+
+/*
+ * Interrupt vector register field definitions.
+ */
+#define IVR_CHANMASK 0x07
+#define IVR_TYPEMASK 0x18
+#define IVR_CONSTMASK 0xc0
+
+#define IVR_RXDATA 0x10
+#define IVR_RXBADDATA 0x18
+#define IVR_TXDATA 0x08
+#define IVR_OTHER 0x00
+
+/*****************************************************************************/
+
+/*
+ * BRG timer control register bit definitions.
+ */
+#define BRGCTCR_DISABCLK0 0x00
+#define BRGCTCR_ENABCLK0 0x08
+#define BRGCTCR_DISABCLK1 0x00
+#define BRGCTCR_ENABCLK1 0x80
+
+#define BRGCTCR_0SCLK16 0x00
+#define BRGCTCR_0SCLK32 0x01
+#define BRGCTCR_0SCLK64 0x02
+#define BRGCTCR_0SCLK128 0x03
+#define BRGCTCR_0X1 0x04
+#define BRGCTCR_0X12 0x05
+#define BRGCTCR_0IO1A 0x06
+#define BRGCTCR_0GIN0 0x07
+
+#define BRGCTCR_1SCLK16 0x00
+#define BRGCTCR_1SCLK32 0x10
+#define BRGCTCR_1SCLK64 0x20
+#define BRGCTCR_1SCLK128 0x30
+#define BRGCTCR_1X1 0x40
+#define BRGCTCR_1X12 0x50
+#define BRGCTCR_1IO1B 0x60
+#define BRGCTCR_1GIN1 0x70
+
+/*****************************************************************************/
+
+/*
+ * Watch dog timer enable register.
+ */
+#define WDTRCR_ENABALL 0xff
+
+/*****************************************************************************/
+
+/*
+ * XON/XOFF interrupt status register.
+ */
+#define XISR_TXCHARMASK 0x03
+#define XISR_TXCHARNORMAL 0x00
+#define XISR_TXWAIT 0x01
+#define XISR_TXXOFFPEND 0x02
+#define XISR_TXXONPEND 0x03
+
+#define XISR_TXFLOWMASK 0x0c
+#define XISR_TXNORMAL 0x00
+#define XISR_TXSTOPPEND 0x04
+#define XISR_TXSTARTED 0x08
+#define XISR_TXSTOPPED 0x0c
+
+#define XISR_RXFLOWMASK 0x30
+#define XISR_RXFLOWNONE 0x00
+#define XISR_RXXONSENT 0x10
+#define XISR_RXXOFFSENT 0x20
+
+#define XISR_RXXONGOT 0x40
+#define XISR_RXXOFFGOT 0x80
+
+/*****************************************************************************/
+
+/*
+ * Current interrupt register.
+ */
+#define CIR_TYPEMASK 0xc0
+#define CIR_TYPEOTHER 0x00
+#define CIR_TYPETX 0x40
+#define CIR_TYPERXGOOD 0x80
+#define CIR_TYPERXBAD 0xc0
+
+#define CIR_RXDATA 0x80
+#define CIR_RXBADDATA 0x40
+#define CIR_TXDATA 0x40
+
+#define CIR_CHANMASK 0x07
+#define CIR_CNTMASK 0x38
+
+#define CIR_SUBTYPEMASK 0x38
+#define CIR_SUBNONE 0x00
+#define CIR_SUBCOS 0x08
+#define CIR_SUBADDR 0x10
+#define CIR_SUBXONXOFF 0x18
+#define CIR_SUBBREAK 0x28
+
+/*****************************************************************************/
+
+/*
+ * Global interrupting channel register.
+ */
+#define GICR_CHANMASK 0x07
+
+/*****************************************************************************/
+
+/*
+ * Global interrupting byte count register.
+ */
+#define GICR_COUNTMASK 0x0f
+
+/*****************************************************************************/
+
+/*
+ * Global interrupting type register.
+ */
+#define GITR_RXMASK 0xc0
+#define GITR_RXNONE 0x00
+#define GITR_RXBADDATA 0x80
+#define GITR_RXGOODDATA 0xc0
+#define GITR_TXDATA 0x20
+
+#define GITR_SUBTYPEMASK 0x07
+#define GITR_SUBNONE 0x00
+#define GITR_SUBCOS 0x01
+#define GITR_SUBADDR 0x02
+#define GITR_SUBXONXOFF 0x03
+#define GITR_SUBBREAK 0x05
+
+/*****************************************************************************/
+
+/*
+ * Input port change register.
+ */
+#define IPR_CTS 0x01
+#define IPR_DTR 0x02
+#define IPR_RTS 0x04
+#define IPR_DCD 0x08
+#define IPR_CTSCHANGE 0x10
+#define IPR_DTRCHANGE 0x20
+#define IPR_RTSCHANGE 0x40
+#define IPR_DCDCHANGE 0x80
+
+#define IPR_CHANGEMASK 0xf0
+
+/*****************************************************************************/
+
+/*
+ * IO port interrupt and output register.
+ */
+#define IOPR_CTS 0x01
+#define IOPR_DTR 0x02
+#define IOPR_RTS 0x04
+#define IOPR_DCD 0x08
+#define IOPR_CTSCOS 0x10
+#define IOPR_DTRCOS 0x20
+#define IOPR_RTSCOS 0x40
+#define IOPR_DCDCOS 0x80
+
+/*****************************************************************************/
+
+/*
+ * IO port configuration register.
+ */
+#define IOPCR_SETCTS 0x00
+#define IOPCR_SETDTR 0x04
+#define IOPCR_SETRTS 0x10
+#define IOPCR_SETDCD 0x00
+
+#define IOPCR_SETSIGS (IOPCR_SETRTS | IOPCR_SETRTS | IOPCR_SETDTR | IOPCR_SETDCD)
+
+/*****************************************************************************/
+
+/*
+ * General purpose output select register.
+ */
+#define GPORS_TXC1XA 0x08
+#define GPORS_TXC16XA 0x09
+#define GPORS_RXC16XA 0x0a
+#define GPORS_TXC16XB 0x0b
+#define GPORS_GPOR3 0x0c
+#define GPORS_GPOR2 0x0d
+#define GPORS_GPOR1 0x0e
+#define GPORS_GPOR0 0x0f
+
+/*****************************************************************************/
+
+/*
+ * General purpose output register.
+ */
+#define GPOR_0 0x01
+#define GPOR_1 0x02
+#define GPOR_2 0x04
+#define GPOR_3 0x08
+
+/*****************************************************************************/
+
+/*
+ * General purpose output clock register.
+ */
+#define GPORC_0NONE 0x00
+#define GPORC_0GIN0 0x01
+#define GPORC_0GIN1 0x02
+#define GPORC_0IO3A 0x02
+
+#define GPORC_1NONE 0x00
+#define GPORC_1GIN0 0x04
+#define GPORC_1GIN1 0x08
+#define GPORC_1IO3C 0x0c
+
+#define GPORC_2NONE 0x00
+#define GPORC_2GIN0 0x10
+#define GPORC_2GIN1 0x20
+#define GPORC_2IO3E 0x20
+
+#define GPORC_3NONE 0x00
+#define GPORC_3GIN0 0x40
+#define GPORC_3GIN1 0x80
+#define GPORC_3IO3G 0xc0
+
+/*****************************************************************************/
+
+/*
+ * General purpose output data register.
+ */
+#define GPOD_0MASK 0x03
+#define GPOD_0SET1 0x00
+#define GPOD_0SET0 0x01
+#define GPOD_0SETR0 0x02
+#define GPOD_0SETIO3B 0x03
+
+#define GPOD_1MASK 0x0c
+#define GPOD_1SET1 0x00
+#define GPOD_1SET0 0x04
+#define GPOD_1SETR0 0x08
+#define GPOD_1SETIO3D 0x0c
+
+#define GPOD_2MASK 0x30
+#define GPOD_2SET1 0x00
+#define GPOD_2SET0 0x10
+#define GPOD_2SETR0 0x20
+#define GPOD_2SETIO3F 0x30
+
+#define GPOD_3MASK 0xc0
+#define GPOD_3SET1 0x00
+#define GPOD_3SET0 0x40
+#define GPOD_3SETR0 0x80
+#define GPOD_3SETIO3H 0xc0
+
+/*****************************************************************************/
+#endif
diff --git a/pfinet/linux-src/include/linux/scc.h b/pfinet/linux-src/include/linux/scc.h
new file mode 100644
index 00000000..7ad72e10
--- /dev/null
+++ b/pfinet/linux-src/include/linux/scc.h
@@ -0,0 +1,258 @@
+/* $Id: scc.h,v 1.29 1997/04/02 14:56:45 jreuter Exp jreuter $ */
+
+#ifndef _SCC_H
+#define _SCC_H
+
+#include <linux/config.h>
+
+/* selection of hardware types */
+
+#define PA0HZP 0x00 /* hardware type for PA0HZP SCC card and compatible */
+#define EAGLE 0x01 /* hardware type for EAGLE card */
+#define PC100 0x02 /* hardware type for PC100 card */
+#define PRIMUS 0x04 /* hardware type for PRIMUS-PC (DG9BL) card */
+#define DRSI 0x08 /* hardware type for DRSI PC*Packet card */
+#define BAYCOM 0x10 /* hardware type for BayCom (U)SCC */
+
+/* DEV ioctl() commands */
+
+enum SCC_ioctl_cmds {
+ SIOCSCCRESERVED = SIOCDEVPRIVATE,
+ SIOCSCCCFG,
+ SIOCSCCINI,
+ SIOCSCCCHANINI,
+ SIOCSCCSMEM,
+ SIOCSCCGKISS,
+ SIOCSCCSKISS,
+ SIOCSCCGSTAT,
+ SIOCSCCCAL
+};
+
+/* magic number */
+
+#define SCC_MAGIC 0x8530 /* ;-) */
+
+/* Device parameter control (from WAMPES) */
+
+enum L1_params {
+ PARAM_DATA,
+ PARAM_TXDELAY,
+ PARAM_PERSIST,
+ PARAM_SLOTTIME,
+ PARAM_TXTAIL,
+ PARAM_FULLDUP,
+ PARAM_SOFTDCD, /* was: PARAM_HW */
+ PARAM_MUTE, /* ??? */
+ PARAM_DTR,
+ PARAM_RTS,
+ PARAM_SPEED,
+ PARAM_ENDDELAY, /* ??? */
+ PARAM_GROUP,
+ PARAM_IDLE,
+ PARAM_MIN,
+ PARAM_MAXKEY,
+ PARAM_WAIT,
+ PARAM_MAXDEFER,
+ PARAM_TX,
+ PARAM_HWEVENT = 31,
+ PARAM_RETURN = 255 /* reset kiss mode */
+};
+
+/* fulldup parameter */
+
+enum FULLDUP_modes {
+ KISS_DUPLEX_HALF, /* normal CSMA operation */
+ KISS_DUPLEX_FULL, /* fullduplex, key down trx after transmission */
+ KISS_DUPLEX_LINK, /* fullduplex, key down trx after 'idletime' sec */
+ KISS_DUPLEX_OPTIMA /* fullduplex, let the protocol layer control the hw */
+};
+
+/* misc. parameters */
+
+#define TIMER_OFF 65535U /* to switch off timers */
+#define NO_SUCH_PARAM 65534U /* param not implemented */
+
+/* HWEVENT parameter */
+
+enum HWEVENT_opts {
+ HWEV_DCD_ON,
+ HWEV_DCD_OFF,
+ HWEV_ALL_SENT
+};
+
+/* channel grouping */
+
+#define RXGROUP 0100 /* if set, only tx when all channels clear */
+#define TXGROUP 0200 /* if set, don't transmit simultaneously */
+
+/* Tx/Rx clock sources */
+
+enum CLOCK_sources {
+ CLK_DPLL, /* normal halfduplex operation */
+ CLK_EXTERNAL, /* external clocking (G3RUH/DF9IC modems) */
+ CLK_DIVIDER, /* Rx = DPLL, Tx = divider (fullduplex with */
+ /* modems without clock regeneration */
+ CLK_BRG /* experimental fullduplex mode with DPLL/BRG for */
+ /* MODEMs without clock recovery */
+};
+
+/* Tx state */
+
+enum TX_state {
+ TXS_IDLE, /* Transmitter off, no data pending */
+ TXS_BUSY, /* waiting for permission to send / tailtime */
+ TXS_ACTIVE, /* Transmitter on, sending data */
+ TXS_NEWFRAME, /* reset CRC and send (next) frame */
+ TXS_IDLE2, /* Transmitter on, no data pending */
+ TXS_WAIT, /* Waiting for Mintime to expire */
+ TXS_TIMEOUT /* We had a transmission timeout */
+};
+
+typedef unsigned long io_port; /* type definition for an 'io port address' */
+
+/* SCC statistical information */
+
+struct scc_stat {
+ long rxints; /* Receiver interrupts */
+ long txints; /* Transmitter interrupts */
+ long exints; /* External/status interrupts */
+ long spints; /* Special receiver interrupts */
+
+ long txframes; /* Packets sent */
+ long rxframes; /* Number of Frames Actually Received */
+ long rxerrs; /* CRC Errors */
+ long txerrs; /* KISS errors */
+
+ unsigned int nospace; /* "Out of buffers" */
+ unsigned int rx_over; /* Receiver Overruns */
+ unsigned int tx_under; /* Transmitter Underruns */
+
+ unsigned int tx_state; /* Transmitter state */
+ int tx_queued; /* tx frames enqueued */
+
+ unsigned int maxqueue; /* allocated tx_buffers */
+ unsigned int bufsize; /* used buffersize */
+};
+
+struct scc_modem {
+ long speed; /* Line speed, bps */
+ char clocksrc; /* 0 = DPLL, 1 = external, 2 = divider */
+ char nrz; /* NRZ instead of NRZI */
+};
+
+struct scc_kiss_cmd {
+ int command; /* one of the KISS-Commands defined above */
+ unsigned param; /* KISS-Param */
+};
+
+struct scc_hw_config {
+ io_port data_a; /* data port channel A */
+ io_port ctrl_a; /* control port channel A */
+ io_port data_b; /* data port channel B */
+ io_port ctrl_b; /* control port channel B */
+ io_port vector_latch; /* INTACK-Latch (#) */
+ io_port special; /* special function port */
+
+ int irq; /* irq */
+ long clock; /* clock */
+ char option; /* command for function port */
+
+ char brand; /* hardware type */
+ char escc; /* use ext. features of a 8580/85180/85280 */
+};
+
+/* (#) only one INTACK latch allowed. */
+
+
+struct scc_mem_config {
+ unsigned int dummy;
+ unsigned int bufsize;
+};
+
+struct scc_calibrate {
+ unsigned int time;
+ unsigned char pattern;
+};
+
+#ifdef __KERNEL__
+
+enum {TX_OFF, TX_ON}; /* command for scc_key_trx() */
+
+/* Vector masks in RR2B */
+
+#define VECTOR_MASK 0x06
+#define TXINT 0x00
+#define EXINT 0x02
+#define RXINT 0x04
+#define SPINT 0x06
+
+#ifdef CONFIG_SCC_DELAY
+#define Inb(port) inb_p(port)
+#define Outb(port, val) outb_p(val, port)
+#else
+#define Inb(port) inb(port)
+#define Outb(port, val) outb(val, port)
+#endif
+
+/* SCC channel control structure for KISS */
+
+struct scc_kiss {
+ unsigned char txdelay; /* Transmit Delay 10 ms/cnt */
+ unsigned char persist; /* Persistence (0-255) as a % */
+ unsigned char slottime; /* Delay to wait on persistence hit */
+ unsigned char tailtime; /* Delay after last byte written */
+ unsigned char fulldup; /* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */
+ unsigned char waittime; /* Waittime before any transmit attempt */
+ unsigned int maxkeyup; /* Maximum time to transmit (seconds) */
+ unsigned char mintime; /* Minimal offtime after MAXKEYUP timeout (seconds) */
+ unsigned int idletime; /* Maximum idle time in ALWAYS KEYED mode (seconds) */
+ unsigned int maxdefer; /* Timer for CSMA channel busy limit */
+ unsigned char tx_inhibit; /* Transmit is not allowed when set */
+ unsigned char group; /* Group ID for AX.25 TX interlocking */
+ unsigned char mode; /* 'normal' or 'hwctrl' mode (unused) */
+ unsigned char softdcd; /* Use DPLL instead of DCD pin for carrier detect */
+};
+
+
+/* SCC channel structure */
+
+struct scc_channel {
+ int magic; /* magic word */
+
+ int init; /* channel exists? */
+
+ struct device *dev; /* link to device control structure */
+ struct net_device_stats dev_stat;/* device statistics */
+
+ char brand; /* manufacturer of the board */
+ long clock; /* used clock */
+
+ io_port ctrl; /* I/O address of CONTROL register */
+ io_port data; /* I/O address of DATA register */
+ io_port special; /* I/O address of special function port */
+ int irq; /* Number of Interrupt */
+
+ char option;
+ char enhanced; /* Enhanced SCC support */
+
+ unsigned char wreg[16]; /* Copy of last written value in WRx */
+ unsigned char status; /* Copy of R0 at last external interrupt */
+ unsigned char dcd; /* DCD status */
+
+ struct scc_kiss kiss; /* control structure for KISS params */
+ struct scc_stat stat; /* statistical information */
+ struct scc_modem modem; /* modem information */
+
+ struct sk_buff_head tx_queue; /* next tx buffer */
+ struct sk_buff *rx_buff; /* pointer to frame currently received */
+ struct sk_buff *tx_buff; /* pointer to frame currently transmitted */
+
+ /* Timer */
+
+ struct timer_list tx_t; /* tx timer for this channel */
+ struct timer_list tx_wdog; /* tx watchdogs */
+};
+
+int scc_init(void);
+#endif /* defined(__KERNEL__) */
+#endif /* defined(_SCC_H) */
diff --git a/pfinet/linux-src/include/linux/sched.h b/pfinet/linux-src/include/linux/sched.h
new file mode 100644
index 00000000..5ef85c63
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sched.h
@@ -0,0 +1,810 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <asm/param.h> /* for HZ */
+
+extern unsigned long event;
+
+#include <linux/binfmts.h>
+#include <linux/personality.h>
+#include <linux/tasks.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/times.h>
+#include <linux/timex.h>
+
+#include <asm/system.h>
+#include <asm/semaphore.h>
+#include <asm/page.h>
+
+#include <linux/smp.h>
+#include <linux/tty.h>
+#include <linux/sem.h>
+#include <linux/signal.h>
+#include <linux/securebits.h>
+
+/*
+ * cloning flags:
+ */
+#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
+#define CLONE_VM 0x00000100 /* set if VM shared between processes */
+#define CLONE_FS 0x00000200 /* set if fs info shared between processes */
+#define CLONE_FILES 0x00000400 /* set if open files shared between processes */
+#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */
+#define CLONE_PID 0x00001000 /* set if pid shared */
+#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
+#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
+
+/*
+ * These are the constant used to fake the fixed-point load-average
+ * counting. Some notes:
+ * - 11 bit fractions expand to 22 bits by the multiplies: this gives
+ * a load-average precision of 10 bits integer + 11 bits fractional
+ * - if you want to count load-averages more often, you need more
+ * precision, or rounding will get you. With 2-second counting freq,
+ * the EXP_n values would be 1981, 2034 and 2043 if still using only
+ * 11 bit fractions.
+ */
+extern unsigned long avenrun[]; /* Load averages */
+
+#define FSHIFT 11 /* nr of bits of precision */
+#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
+#define LOAD_FREQ (5*HZ) /* 5 sec intervals */
+#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */
+#define EXP_5 2014 /* 1/exp(5sec/5min) */
+#define EXP_15 2037 /* 1/exp(5sec/15min) */
+
+#define CALC_LOAD(load,exp,n) \
+ load *= exp; \
+ load += n*(FIXED_1-exp); \
+ load >>= FSHIFT;
+
+#define CT_TO_SECS(x) ((x) / HZ)
+#define CT_TO_USECS(x) (((x) % HZ) * 1000000/HZ)
+
+extern int nr_running, nr_tasks;
+extern int last_pid;
+
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/param.h>
+#include <linux/resource.h>
+#include <linux/timer.h>
+
+#include <asm/processor.h>
+
+#define TASK_RUNNING 0
+#define TASK_INTERRUPTIBLE 1
+#define TASK_UNINTERRUPTIBLE 2
+#define TASK_ZOMBIE 4
+#define TASK_STOPPED 8
+#define TASK_SWAPPING 16
+
+/*
+ * Scheduling policies
+ */
+#define SCHED_OTHER 0
+#define SCHED_FIFO 1
+#define SCHED_RR 2
+
+/*
+ * This is an additional bit set when we want to
+ * yield the CPU for one re-schedule..
+ */
+#define SCHED_YIELD 0x10
+
+struct sched_param {
+ int sched_priority;
+};
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#ifdef __KERNEL__
+
+#include <asm/spinlock.h>
+
+/*
+ * This serializes "schedule()" and also protects
+ * the run-queue from deletions/modifications (but
+ * _adding_ to the beginning of the run-queue has
+ * a separate lock).
+ */
+extern rwlock_t tasklist_lock;
+extern spinlock_t runqueue_lock;
+
+extern void sched_init(void);
+extern void init_idle(void);
+extern void show_state(void);
+extern void trap_init(void);
+
+#define MAX_SCHEDULE_TIMEOUT LONG_MAX
+extern signed long FASTCALL(schedule_timeout(signed long timeout));
+asmlinkage void schedule(void);
+
+/*
+ * The default fd array needs to be at least BITS_PER_LONG,
+ * as this is the granularity returned by copy_fdset().
+ */
+#define NR_OPEN_DEFAULT BITS_PER_LONG
+
+/*
+ * Open file table structure
+ */
+struct files_struct {
+ atomic_t count;
+ int max_fds;
+ int max_fdset;
+ int next_fd;
+ struct file ** fd; /* current fd array */
+ fd_set *close_on_exec;
+ fd_set *open_fds;
+ fd_set close_on_exec_init;
+ fd_set open_fds_init;
+ struct file * fd_array[NR_OPEN_DEFAULT];
+};
+
+#define INIT_FILES { \
+ ATOMIC_INIT(1), \
+ NR_OPEN_DEFAULT, \
+ __FD_SETSIZE, \
+ 0, \
+ &init_files.fd_array[0], \
+ &init_files.close_on_exec_init, \
+ &init_files.open_fds_init, \
+ { { 0, } }, \
+ { { 0, } }, \
+ { NULL, } \
+}
+
+struct fs_struct {
+ atomic_t count;
+ int umask;
+ struct dentry * root, * pwd;
+};
+
+#define INIT_FS { \
+ ATOMIC_INIT(1), \
+ 0022, \
+ NULL, NULL \
+}
+
+/* Maximum number of active map areas.. This is a random (large) number */
+#define MAX_MAP_COUNT (65536)
+
+/* Number of map areas at which the AVL tree is activated. This is arbitrary. */
+#define AVL_MIN_MAP_COUNT 32
+
+struct mm_struct {
+ struct vm_area_struct *mmap; /* list of VMAs */
+ struct vm_area_struct *mmap_avl; /* tree of VMAs */
+ struct vm_area_struct *mmap_cache; /* last find_vma result */
+ pgd_t * pgd;
+ atomic_t count;
+ int map_count; /* number of VMAs */
+ struct semaphore mmap_sem;
+ unsigned long context;
+ unsigned long start_code, end_code, start_data, end_data;
+ unsigned long start_brk, brk, start_stack;
+ unsigned long arg_start, arg_end, env_start, env_end;
+ unsigned long rss, total_vm, locked_vm;
+ unsigned long def_flags;
+ unsigned long cpu_vm_mask;
+ unsigned long swap_cnt; /* number of pages to swap on next pass */
+ unsigned long swap_address;
+ /*
+ * This is an architecture-specific pointer: the portable
+ * part of Linux does not know about any segments.
+ */
+ void * segments;
+};
+
+#define INIT_MM { \
+ &init_mmap, NULL, NULL, \
+ swapper_pg_dir, \
+ ATOMIC_INIT(1), 1, \
+ MUTEX, \
+ 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, \
+ 0, 0, 0, 0, NULL }
+
+struct signal_struct {
+ atomic_t count;
+ struct k_sigaction action[_NSIG];
+ spinlock_t siglock;
+};
+
+
+#define INIT_SIGNALS { \
+ ATOMIC_INIT(1), \
+ { {{0,}}, }, \
+ SPIN_LOCK_UNLOCKED }
+
+/*
+ * Some day this will be a full-fledged user tracking system..
+ * Right now it is only used to track how many processes a
+ * user has, but it has the potential to track memory usage etc.
+ */
+struct user_struct;
+
+struct task_struct {
+/* these are hardcoded - don't touch */
+ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
+ unsigned long flags; /* per process flags, defined below */
+ int sigpending;
+ mm_segment_t addr_limit; /* thread address space:
+ 0-0xBFFFFFFF for user-thead
+ 0-0xFFFFFFFF for kernel-thread
+ */
+ struct exec_domain *exec_domain;
+ long need_resched;
+
+/* various fields */
+ long counter;
+ long priority;
+ cycles_t avg_slice;
+/* SMP and runqueue state */
+ int has_cpu;
+ int processor;
+ int last_processor;
+ int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */
+ struct task_struct *next_task, *prev_task;
+ struct task_struct *next_run, *prev_run;
+
+/* task state */
+ struct linux_binfmt *binfmt;
+ int exit_code, exit_signal;
+ int pdeath_signal; /* The signal sent when the parent dies */
+ /* ??? */
+ unsigned long personality;
+ int dumpable:1;
+ int did_exec:1;
+ pid_t pid;
+ pid_t pgrp;
+ pid_t tty_old_pgrp;
+ pid_t session;
+ /* boolean value for session group leader */
+ int leader;
+ /*
+ * pointers to (original) parent process, youngest child, younger sibling,
+ * older sibling, respectively. (p->father can be replaced with
+ * p->p_pptr->pid)
+ */
+ struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+
+ /* PID hash table linkage. */
+ struct task_struct *pidhash_next;
+ struct task_struct **pidhash_pprev;
+
+ /* Pointer to task[] array linkage. */
+ struct task_struct **tarray_ptr;
+
+ struct wait_queue *wait_chldexit; /* for wait4() */
+ struct semaphore *vfork_sem; /* for vfork() */
+ unsigned long policy, rt_priority;
+ unsigned long it_real_value, it_prof_value, it_virt_value;
+ unsigned long it_real_incr, it_prof_incr, it_virt_incr;
+ struct timer_list real_timer;
+ struct tms times;
+ unsigned long start_time;
+ long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
+/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
+ unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
+ int swappable:1;
+/* process credentials */
+ uid_t uid,euid,suid,fsuid;
+ gid_t gid,egid,sgid,fsgid;
+ int ngroups;
+ gid_t groups[NGROUPS];
+ kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
+ struct user_struct *user;
+/* limits */
+ struct rlimit rlim[RLIM_NLIMITS];
+ unsigned short used_math;
+ char comm[16];
+/* file system info */
+ int link_count;
+ struct tty_struct *tty; /* NULL if no tty */
+/* ipc stuff */
+ struct sem_undo *semundo;
+ struct sem_queue *semsleeping;
+/* tss for this task */
+ struct thread_struct tss;
+/* filesystem information */
+ struct fs_struct *fs;
+/* open file information */
+ struct files_struct *files;
+/* memory management info */
+ struct mm_struct *mm;
+
+/* signal handlers */
+ spinlock_t sigmask_lock; /* Protects signal and blocked */
+ struct signal_struct *sig;
+ sigset_t signal, blocked;
+ struct signal_queue *sigqueue, **sigqueue_tail;
+ unsigned long sas_ss_sp;
+ size_t sas_ss_size;
+};
+
+/*
+ * Per process flags
+ */
+#define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */
+ /* Not implemented yet, only for 486*/
+#define PF_STARTING 0x00000002 /* being created */
+#define PF_EXITING 0x00000004 /* getting shut down */
+#define PF_PTRACED 0x00000010 /* set if ptrace (0) has been called */
+#define PF_TRACESYS 0x00000020 /* tracing system calls */
+#define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */
+#define PF_SUPERPRIV 0x00000100 /* used super-user privileges */
+#define PF_DUMPCORE 0x00000200 /* dumped core */
+#define PF_SIGNALED 0x00000400 /* killed by a signal */
+#define PF_MEMALLOC 0x00000800 /* Allocating memory */
+#define PF_VFORK 0x00001000 /* Wake up parent in mm_release */
+
+#define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */
+#define PF_DTRACE 0x00200000 /* delayed trace (used on m68k, i386) */
+
+/*
+ * Limit the stack by to some sane default: root can always
+ * increase this limit if needed.. 8MB seems reasonable.
+ */
+#define _STK_LIM (8*1024*1024)
+
+#define DEF_PRIORITY (20*HZ/100) /* 210 ms time slices */
+
+/*
+ * INIT_TASK is used to set up the first task table, touch at
+ * your own risk!. Base=0, limit=0x1fffff (=2MB)
+ */
+#define INIT_TASK \
+/* state etc */ { 0,0,0,KERNEL_DS,&default_exec_domain,0, \
+/* counter */ DEF_PRIORITY,DEF_PRIORITY,0, \
+/* SMP */ 0,0,0,-1, \
+/* schedlink */ &init_task,&init_task, &init_task, &init_task, \
+/* binfmt */ NULL, \
+/* ec,brk... */ 0,0,0,0,0,0, \
+/* pid etc.. */ 0,0,0,0,0, \
+/* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \
+/* pidhash */ NULL, NULL, \
+/* tarray */ &task[0], \
+/* chld wait */ NULL, NULL, \
+/* timeout */ SCHED_OTHER,0,0,0,0,0,0,0, \
+/* timer */ { NULL, NULL, 0, 0, it_real_fn }, \
+/* utime */ {0,0,0,0},0, \
+/* per CPU times */ {0, }, {0, }, \
+/* flt */ 0,0,0,0,0,0, \
+/* swp */ 0, \
+/* process credentials */ \
+/* uid etc */ 0,0,0,0,0,0,0,0, \
+/* suppl grps*/ 0, {0,}, \
+/* caps */ CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \
+/* user */ NULL, \
+/* rlimits */ INIT_RLIMITS, \
+/* math */ 0, \
+/* comm */ "swapper", \
+/* fs info */ 0,NULL, \
+/* ipc */ NULL, NULL, \
+/* tss */ INIT_TSS, \
+/* fs */ &init_fs, \
+/* files */ &init_files, \
+/* mm */ &init_mm, \
+/* signals */ SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
+}
+
+union task_union {
+ struct task_struct task;
+ unsigned long stack[2048];
+};
+
+extern union task_union init_task_union;
+
+extern struct mm_struct init_mm;
+extern struct task_struct *task[NR_TASKS];
+
+extern struct task_struct **tarray_freelist;
+extern spinlock_t taskslot_lock;
+
+extern __inline__ void add_free_taskslot(struct task_struct **t)
+{
+ spin_lock(&taskslot_lock);
+ *t = (struct task_struct *) tarray_freelist;
+ tarray_freelist = t;
+ spin_unlock(&taskslot_lock);
+}
+
+extern __inline__ struct task_struct **get_free_taskslot(void)
+{
+ struct task_struct **tslot;
+
+ spin_lock(&taskslot_lock);
+ if((tslot = tarray_freelist) != NULL)
+ tarray_freelist = (struct task_struct **) *tslot;
+ spin_unlock(&taskslot_lock);
+
+ return tslot;
+}
+
+/* PID hashing. */
+#define PIDHASH_SZ (NR_TASKS >> 2)
+extern struct task_struct *pidhash[PIDHASH_SZ];
+
+#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
+
+extern __inline__ void hash_pid(struct task_struct *p)
+{
+ struct task_struct **htable = &pidhash[pid_hashfn(p->pid)];
+
+ if((p->pidhash_next = *htable) != NULL)
+ (*htable)->pidhash_pprev = &p->pidhash_next;
+ *htable = p;
+ p->pidhash_pprev = htable;
+}
+
+extern __inline__ void unhash_pid(struct task_struct *p)
+{
+ if(p->pidhash_next)
+ p->pidhash_next->pidhash_pprev = p->pidhash_pprev;
+ *p->pidhash_pprev = p->pidhash_next;
+}
+
+extern __inline__ struct task_struct *find_task_by_pid(int pid)
+{
+ struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)];
+
+ for(p = *htable; p && p->pid != pid; p = p->pidhash_next)
+ ;
+
+ return p;
+}
+
+/* per-UID process charging. */
+extern int alloc_uid(struct task_struct *p);
+void free_uid(struct task_struct *p);
+
+#include <asm/current.h>
+
+extern unsigned long volatile jiffies;
+extern unsigned long itimer_ticks;
+extern unsigned long itimer_next;
+extern struct timeval xtime;
+extern void do_timer(struct pt_regs *);
+
+extern unsigned int * prof_buffer;
+extern unsigned long prof_len;
+extern unsigned long prof_shift;
+
+#define CURRENT_TIME (xtime.tv_sec)
+
+extern void FASTCALL(__wake_up(struct wait_queue ** p, unsigned int mode));
+extern void FASTCALL(sleep_on(struct wait_queue ** p));
+extern long FASTCALL(sleep_on_timeout(struct wait_queue ** p,
+ signed long timeout));
+extern void FASTCALL(interruptible_sleep_on(struct wait_queue ** p));
+extern long FASTCALL(interruptible_sleep_on_timeout(struct wait_queue ** p,
+ signed long timeout));
+extern void FASTCALL(wake_up_process(struct task_struct * tsk));
+
+#define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
+#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE)
+
+extern int in_group_p(gid_t grp);
+
+extern void flush_signals(struct task_struct *);
+extern void flush_signal_handlers(struct task_struct *);
+extern int dequeue_signal(sigset_t *block, siginfo_t *);
+extern int send_sig_info(int, struct siginfo *info, struct task_struct *);
+extern int force_sig_info(int, struct siginfo *info, struct task_struct *);
+extern int kill_pg_info(int, struct siginfo *info, pid_t);
+extern int kill_sl_info(int, struct siginfo *info, pid_t);
+extern int kill_proc_info(int, struct siginfo *info, pid_t);
+extern int kill_something_info(int, struct siginfo *info, int);
+extern void notify_parent(struct task_struct * tsk, int);
+extern void force_sig(int sig, struct task_struct * p);
+extern int send_sig(int sig, struct task_struct * p, int priv);
+extern int kill_pg(pid_t, int, int);
+extern int kill_sl(pid_t, int, int);
+extern int kill_proc(pid_t, int, int);
+extern int do_sigaction(int sig, const struct k_sigaction *act,
+ struct k_sigaction *oact);
+extern int do_sigaltstack(const stack_t *ss, stack_t *oss, unsigned long sp);
+
+extern inline int signal_pending(struct task_struct *p)
+{
+ return (p->sigpending != 0);
+}
+
+/* Reevaluate whether the task has signals pending delivery.
+ This is required every time the blocked sigset_t changes.
+ All callers should have t->sigmask_lock. */
+
+static inline void recalc_sigpending(struct task_struct *t)
+{
+ unsigned long ready;
+ long i;
+
+ switch (_NSIG_WORDS) {
+ default:
+ for (i = _NSIG_WORDS, ready = 0; --i >= 0 ;)
+ ready |= t->signal.sig[i] &~ t->blocked.sig[i];
+ break;
+
+ case 4: ready = t->signal.sig[3] &~ t->blocked.sig[3];
+ ready |= t->signal.sig[2] &~ t->blocked.sig[2];
+ ready |= t->signal.sig[1] &~ t->blocked.sig[1];
+ ready |= t->signal.sig[0] &~ t->blocked.sig[0];
+ break;
+
+ case 2: ready = t->signal.sig[1] &~ t->blocked.sig[1];
+ ready |= t->signal.sig[0] &~ t->blocked.sig[0];
+ break;
+
+ case 1: ready = t->signal.sig[0] &~ t->blocked.sig[0];
+ }
+
+ t->sigpending = (ready != 0);
+}
+
+/* True if we are on the alternate signal stack. */
+
+static inline int on_sig_stack(unsigned long sp)
+{
+ return (sp >= current->sas_ss_sp
+ && sp < current->sas_ss_sp + current->sas_ss_size);
+}
+
+static inline int sas_ss_flags(unsigned long sp)
+{
+ return (current->sas_ss_size == 0 ? SS_DISABLE
+ : on_sig_stack(sp) ? SS_ONSTACK : 0);
+}
+
+extern int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags,
+ const char *device,
+ void *dev_id);
+extern void free_irq(unsigned int irq, void *dev_id);
+
+/*
+ * This has now become a routine instead of a macro, it sets a flag if
+ * it returns true (to do BSD-style accounting where the process is flagged
+ * if it uses root privs). The implication of this is that you should do
+ * normal permissions checks first, and check suser() last.
+ *
+ * [Dec 1997 -- Chris Evans]
+ * For correctness, the above considerations need to be extended to
+ * fsuser(). This is done, along with moving fsuser() checks to be
+ * last.
+ *
+ * These will be removed, but in the mean time, when the SECURE_NOROOT
+ * flag is set, uids don't grant privilege.
+ */
+extern inline int suser(void)
+{
+ if (!issecure(SECURE_NOROOT) && current->euid == 0) {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+ return 0;
+}
+
+extern inline int fsuser(void)
+{
+ if (!issecure(SECURE_NOROOT) && current->fsuid == 0) {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * capable() checks for a particular capability.
+ * New privilege checks should use this interface, rather than suser() or
+ * fsuser(). See include/linux/capability.h for defined capabilities.
+ */
+
+extern inline int capable(int cap)
+{
+#if 1 /* ok now */
+ if (cap_raised(current->cap_effective, cap))
+#else
+ if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0)
+#endif
+ {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Routines for handling mm_structs
+ */
+extern struct mm_struct * mm_alloc(void);
+static inline void mmget(struct mm_struct * mm)
+{
+ atomic_inc(&mm->count);
+}
+extern void mmput(struct mm_struct *);
+/* Remove the current tasks stale references to the old mm_struct */
+extern void mm_release(void);
+
+/*
+ * Routines for handling the fd arrays
+ */
+extern struct file ** alloc_fd_array(int);
+extern int expand_fd_array(struct files_struct *, int nr);
+extern void free_fd_array(struct file **, int);
+
+extern fd_set *alloc_fdset(int);
+extern int expand_fdset(struct files_struct *, int nr);
+extern void free_fdset(fd_set *, int);
+
+/* Expand files. Return <0 on error; 0 nothing done; 1 files expanded,
+ * we may have blocked. */
+static inline int expand_files(struct files_struct *files, int nr)
+{
+ int err, expand = 0;
+#ifdef FDSET_DEBUG
+ printk (KERN_ERR __FUNCTION__ " %d: nr = %d\n", current->pid, nr);
+#endif
+
+ if (nr >= files->max_fdset) {
+ expand = 1;
+ if ((err = expand_fdset(files, nr)))
+ goto out;
+ }
+ if (nr >= files->max_fds) {
+ expand = 1;
+ if ((err = expand_fd_array(files, nr)))
+ goto out;
+ }
+ err = expand;
+ out:
+#ifdef FDSET_DEBUG
+ if (err)
+ printk (KERN_ERR __FUNCTION__ " %d: return %d\n", current->pid, err);
+#endif
+ return err;
+}
+
+extern int copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
+extern void flush_thread(void);
+extern void exit_thread(void);
+
+extern void exit_mm(struct task_struct *);
+extern void exit_fs(struct task_struct *);
+extern void exit_files(struct task_struct *);
+extern void exit_sighand(struct task_struct *);
+
+extern int do_execve(char *, char **, char **, struct pt_regs *);
+extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
+
+/*
+ * The wait-queues are circular lists, and you have to be *very* sure
+ * to keep them correct. Use only these two functions to add/remove
+ * entries in the queues.
+ */
+extern inline void __add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+{
+ wait->next = *p ? : WAIT_QUEUE_HEAD(p);
+ *p = wait;
+}
+
+extern rwlock_t waitqueue_lock;
+
+extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&waitqueue_lock, flags);
+ __add_wait_queue(p, wait);
+ write_unlock_irqrestore(&waitqueue_lock, flags);
+}
+
+extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+{
+ struct wait_queue * next = wait->next;
+ struct wait_queue * head = next;
+ struct wait_queue * tmp;
+
+ while ((tmp = head->next) != wait) {
+ head = tmp;
+ }
+ head->next = next;
+}
+
+extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&waitqueue_lock, flags);
+ __remove_wait_queue(p, wait);
+ write_unlock_irqrestore(&waitqueue_lock, flags);
+}
+
+#define __wait_event(wq, condition) \
+do { \
+ struct wait_queue __wait; \
+ \
+ __wait.task = current; \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ current->state = TASK_UNINTERRUPTIBLE; \
+ if (condition) \
+ break; \
+ schedule(); \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#define wait_event(wq, condition) \
+do { \
+ if (condition) \
+ break; \
+ __wait_event(wq, condition); \
+} while (0)
+
+#define __wait_event_interruptible(wq, condition, ret) \
+do { \
+ struct wait_queue __wait; \
+ \
+ __wait.task = current; \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ current->state = TASK_INTERRUPTIBLE; \
+ if (condition) \
+ break; \
+ if (!signal_pending(current)) { \
+ schedule(); \
+ continue; \
+ } \
+ ret = -ERESTARTSYS; \
+ break; \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#define wait_event_interruptible(wq, condition) \
+({ \
+ int __ret = 0; \
+ if (!(condition)) \
+ __wait_event_interruptible(wq, condition, __ret); \
+ __ret; \
+})
+
+#define REMOVE_LINKS(p) do { \
+ (p)->next_task->prev_task = (p)->prev_task; \
+ (p)->prev_task->next_task = (p)->next_task; \
+ if ((p)->p_osptr) \
+ (p)->p_osptr->p_ysptr = (p)->p_ysptr; \
+ if ((p)->p_ysptr) \
+ (p)->p_ysptr->p_osptr = (p)->p_osptr; \
+ else \
+ (p)->p_pptr->p_cptr = (p)->p_osptr; \
+ } while (0)
+
+#define SET_LINKS(p) do { \
+ (p)->next_task = &init_task; \
+ (p)->prev_task = init_task.prev_task; \
+ init_task.prev_task->next_task = (p); \
+ init_task.prev_task = (p); \
+ (p)->p_ysptr = NULL; \
+ if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
+ (p)->p_osptr->p_ysptr = p; \
+ (p)->p_pptr->p_cptr = p; \
+ } while (0)
+
+#define for_each_task(p) \
+ for (p = &init_task ; (p = p->next_task) != &init_task ; )
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/sdla.h b/pfinet/linux-src/include/linux/sdla.h
new file mode 100644
index 00000000..44ae55b1
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sdla.h
@@ -0,0 +1,339 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the Frame relay interface.
+ *
+ * Version: @(#)if_ifrad.h 0.20 13 Apr 96
+ *
+ * Author: Mike McLagan <mike.mclagan@linux.org>
+ *
+ * Changes:
+ * 0.15 Mike McLagan Structure packing
+ *
+ * 0.20 Mike McLagan New flags for S508 buffer handling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef SDLA_H
+#define SDLA_H
+
+/* adapter type */
+#define SDLA_TYPES
+#define SDLA_S502A 5020
+#define SDLA_S502E 5021
+#define SDLA_S503 5030
+#define SDLA_S507 5070
+#define SDLA_S508 5080
+#define SDLA_S509 5090
+#define SDLA_UNKNOWN -1
+
+/* port selection flags for the S508 */
+#define SDLA_S508_PORT_V35 0x00
+#define SDLA_S508_PORT_RS232 0x02
+
+/* Z80 CPU speeds */
+#define SDLA_CPU_3M 0x00
+#define SDLA_CPU_5M 0x01
+#define SDLA_CPU_7M 0x02
+#define SDLA_CPU_8M 0x03
+#define SDLA_CPU_10M 0x04
+#define SDLA_CPU_16M 0x05
+#define SDLA_CPU_12M 0x06
+
+/* some private IOCTLs */
+#define SDLA_IDENTIFY (FRAD_LAST_IOCTL + 1)
+#define SDLA_CPUSPEED (FRAD_LAST_IOCTL + 2)
+#define SDLA_PROTOCOL (FRAD_LAST_IOCTL + 3)
+
+#define SDLA_CLEARMEM (FRAD_LAST_IOCTL + 4)
+#define SDLA_WRITEMEM (FRAD_LAST_IOCTL + 5)
+#define SDLA_READMEM (FRAD_LAST_IOCTL + 6)
+
+struct sdla_mem {
+ int addr;
+ int len;
+ void *data;
+};
+
+#define SDLA_START (FRAD_LAST_IOCTL + 7)
+#define SDLA_STOP (FRAD_LAST_IOCTL + 8)
+
+/* some offsets in the Z80's memory space */
+#define SDLA_NMIADDR 0x0000
+#define SDLA_CONF_ADDR 0x0010
+#define SDLA_S502A_NMIADDR 0x0066
+#define SDLA_CODE_BASEADDR 0x0100
+#define SDLA_WINDOW_SIZE 0x2000
+#define SDLA_ADDR_MASK 0x1FFF
+
+/* largest handleable block of data */
+#define SDLA_MAX_DATA 4080
+#define SDLA_MAX_MTU 4072 /* MAX_DATA - sizeof(fradhdr) */
+#define SDLA_MAX_DLCI 24
+
+/* this should be the same as frad_conf */
+struct sdla_conf {
+ short station;
+ short config;
+ short kbaud;
+ short clocking;
+ short max_frm;
+ short T391;
+ short T392;
+ short N391;
+ short N392;
+ short N393;
+ short CIR_fwd;
+ short Bc_fwd;
+ short Be_fwd;
+ short CIR_bwd;
+ short Bc_bwd;
+ short Be_bwd;
+};
+
+/* this should be the same as dlci_conf */
+struct sdla_dlci_conf {
+ short config;
+ short CIR_fwd;
+ short Bc_fwd;
+ short Be_fwd;
+ short CIR_bwd;
+ short Bc_bwd;
+ short Be_bwd;
+ short Tc_fwd;
+ short Tc_bwd;
+ short Tf_max;
+ short Tb_max;
+};
+
+#ifndef __KERNEL__
+
+void sdla(void *cfg_info, char *dev, struct frad_conf *conf, int quiet);
+
+#else
+
+/* important Z80 window addresses */
+#define SDLA_CONTROL_WND 0xE000
+
+#define SDLA_502_CMD_BUF 0xEF60
+#define SDLA_502_RCV_BUF 0xA900
+#define SDLA_502_TXN_AVAIL 0xFFF1
+#define SDLA_502_RCV_AVAIL 0xFFF2
+#define SDLA_502_EVENT_FLAGS 0xFFF3
+#define SDLA_502_MDM_STATUS 0xFFF4
+#define SDLA_502_IRQ_INTERFACE 0xFFFD
+#define SDLA_502_IRQ_PERMISSION 0xFFFE
+#define SDLA_502_DATA_OFS 0x0010
+
+#define SDLA_508_CMD_BUF 0xE000
+#define SDLA_508_TXBUF_INFO 0xF100
+#define SDLA_508_RXBUF_INFO 0xF120
+#define SDLA_508_EVENT_FLAGS 0xF003
+#define SDLA_508_MDM_STATUS 0xF004
+#define SDLA_508_IRQ_INTERFACE 0xF010
+#define SDLA_508_IRQ_PERMISSION 0xF011
+#define SDLA_508_TSE_OFFSET 0xF012
+
+/* Event flags */
+#define SDLA_EVENT_STATUS 0x01
+#define SDLA_EVENT_DLCI_STATUS 0x02
+#define SDLA_EVENT_BAD_DLCI 0x04
+#define SDLA_EVENT_LINK_DOWN 0x40
+
+/* IRQ Trigger flags */
+#define SDLA_INTR_RX 0x01
+#define SDLA_INTR_TX 0x02
+#define SDLA_INTR_MODEM 0x04
+#define SDLA_INTR_COMPLETE 0x08
+#define SDLA_INTR_STATUS 0x10
+#define SDLA_INTR_TIMER 0x20
+
+/* DLCI status bits */
+#define SDLA_DLCI_DELETED 0x01
+#define SDLA_DLCI_ACTIVE 0x02
+#define SDLA_DLCI_WAITING 0x04
+#define SDLA_DLCI_NEW 0x08
+#define SDLA_DLCI_INCLUDED 0x40
+
+/* valid command codes */
+#define SDLA_INFORMATION_WRITE 0x01
+#define SDLA_INFORMATION_READ 0x02
+#define SDLA_ISSUE_IN_CHANNEL_SIGNAL 0x03
+#define SDLA_SET_DLCI_CONFIGURATION 0x10
+#define SDLA_READ_DLCI_CONFIGURATION 0x11
+#define SDLA_DISABLE_COMMUNICATIONS 0x12
+#define SDLA_ENABLE_COMMUNICATIONS 0x13
+#define SDLA_READ_DLC_STATUS 0x14
+#define SDLA_READ_DLC_STATISTICS 0x15
+#define SDLA_FLUSH_DLC_STATISTICS 0x16
+#define SDLA_LIST_ACTIVE_DLCI 0x17
+#define SDLA_FLUSH_INFORMATION_BUFFERS 0x18
+#define SDLA_ADD_DLCI 0x20
+#define SDLA_DELETE_DLCI 0x21
+#define SDLA_ACTIVATE_DLCI 0x22
+#define SDLA_DEACTIVATE_DLCI 0x23
+#define SDLA_READ_MODEM_STATUS 0x30
+#define SDLA_SET_MODEM_STATUS 0x31
+#define SDLA_READ_COMMS_ERR_STATS 0x32
+#define SDLA_FLUSH_COMMS_ERR_STATS 0x33
+#define SDLA_READ_CODE_VERSION 0x40
+#define SDLA_SET_IRQ_TRIGGER 0x50
+#define SDLA_GET_IRQ_TRIGGER 0x51
+
+/* In channel signal types */
+#define SDLA_ICS_LINK_VERIFY 0x02
+#define SDLA_ICS_STATUS_ENQ 0x03
+
+/* modem status flags */
+#define SDLA_MODEM_DTR_HIGH 0x01
+#define SDLA_MODEM_RTS_HIGH 0x02
+#define SDLA_MODEM_DCD_HIGH 0x08
+#define SDLA_MODEM_CTS_HIGH 0x20
+
+/* used for RET_MODEM interpretation */
+#define SDLA_MODEM_DCD_LOW 0x01
+#define SDLA_MODEM_CTS_LOW 0x02
+
+/* return codes */
+#define SDLA_RET_OK 0x00
+#define SDLA_RET_COMMUNICATIONS 0x01
+#define SDLA_RET_CHANNEL_INACTIVE 0x02
+#define SDLA_RET_DLCI_INACTIVE 0x03
+#define SDLA_RET_DLCI_CONFIG 0x04
+#define SDLA_RET_BUF_TOO_BIG 0x05
+#define SDLA_RET_NO_DATA 0x05
+#define SDLA_RET_BUF_OVERSIZE 0x06
+#define SDLA_RET_CIR_OVERFLOW 0x07
+#define SDLA_RET_NO_BUFS 0x08
+#define SDLA_RET_TIMEOUT 0x0A
+#define SDLA_RET_MODEM 0x10
+#define SDLA_RET_CHANNEL_OFF 0x11
+#define SDLA_RET_CHANNEL_ON 0x12
+#define SDLA_RET_DLCI_STATUS 0x13
+#define SDLA_RET_DLCI_UNKNOWN 0x14
+#define SDLA_RET_COMMAND_INVALID 0x1F
+
+/* Configuration flags */
+#define SDLA_DIRECT_RECV 0x0080
+#define SDLA_TX_NO_EXCEPT 0x0020
+#define SDLA_NO_ICF_MSGS 0x1000
+#define SDLA_TX50_RX50 0x0000
+#define SDLA_TX70_RX30 0x2000
+#define SDLA_TX30_RX70 0x4000
+
+/* IRQ selection flags */
+#define SDLA_IRQ_RECEIVE 0x01
+#define SDLA_IRQ_TRANSMIT 0x02
+#define SDLA_IRQ_MODEM_STAT 0x04
+#define SDLA_IRQ_COMMAND 0x08
+#define SDLA_IRQ_CHANNEL 0x10
+#define SDLA_IRQ_TIMER 0x20
+
+/* definitions for PC memory mapping */
+#define SDLA_8K_WINDOW 0x01
+#define SDLA_S502_SEG_A 0x10
+#define SDLA_S502_SEG_C 0x20
+#define SDLA_S502_SEG_D 0x00
+#define SDLA_S502_SEG_E 0x30
+#define SDLA_S507_SEG_A 0x00
+#define SDLA_S507_SEG_B 0x40
+#define SDLA_S507_SEG_C 0x80
+#define SDLA_S507_SEG_E 0xC0
+#define SDLA_S508_SEG_A 0x00
+#define SDLA_S508_SEG_C 0x10
+#define SDLA_S508_SEG_D 0x08
+#define SDLA_S508_SEG_E 0x18
+
+/* SDLA adapter port constants */
+#define SDLA_IO_EXTENTS 0x04
+
+#define SDLA_REG_CONTROL 0x00
+#define SDLA_REG_PC_WINDOW 0x01 /* offset for PC window select latch */
+#define SDLA_REG_Z80_WINDOW 0x02 /* offset for Z80 window select latch */
+#define SDLA_REG_Z80_CONTROL 0x03 /* offset for Z80 control latch */
+
+#define SDLA_S502_STS 0x00 /* status reg for 502, 502E, 507 */
+#define SDLA_S508_GNRL 0x00 /* general purp. reg for 508 */
+#define SDLA_S508_STS 0x01 /* status reg for 508 */
+#define SDLA_S508_IDR 0x02 /* ID reg for 508 */
+
+/* control register flags */
+#define SDLA_S502A_START 0x00 /* start the CPU */
+#define SDLA_S502A_INTREQ 0x02
+#define SDLA_S502A_INTEN 0x04
+#define SDLA_S502A_HALT 0x08 /* halt the CPU */
+#define SDLA_S502A_NMI 0x10 /* issue an NMI to the CPU */
+
+#define SDLA_S502E_CPUEN 0x01
+#define SDLA_S502E_ENABLE 0x02
+#define SDLA_S502E_INTACK 0x04
+
+#define SDLA_S507_ENABLE 0x01
+#define SDLA_S507_IRQ3 0x00
+#define SDLA_S507_IRQ4 0x20
+#define SDLA_S507_IRQ5 0x40
+#define SDLA_S507_IRQ7 0x60
+#define SDLA_S507_IRQ10 0x80
+#define SDLA_S507_IRQ11 0xA0
+#define SDLA_S507_IRQ12 0xC0
+#define SDLA_S507_IRQ15 0xE0
+
+#define SDLA_HALT 0x00
+#define SDLA_CPUEN 0x02
+#define SDLA_MEMEN 0x04
+#define SDLA_S507_EPROMWR 0x08
+#define SDLA_S507_EPROMCLK 0x10
+#define SDLA_S508_INTRQ 0x08
+#define SDLA_S508_INTEN 0x10
+
+struct sdla_cmd {
+ char opp_flag __attribute__((packed));
+ char cmd __attribute__((packed));
+ short length __attribute__((packed));
+ char retval __attribute__((packed));
+ short dlci __attribute__((packed));
+ char flags __attribute__((packed));
+ short rxlost_int __attribute__((packed));
+ long rxlost_app __attribute__((packed));
+ char reserve[2] __attribute__((packed));
+ char data[SDLA_MAX_DATA] __attribute__((packed)); /* transfer data buffer */
+};
+
+struct intr_info {
+ char flags __attribute__((packed));
+ short txlen __attribute__((packed));
+ char irq __attribute__((packed));
+ char flags2 __attribute__((packed));
+ short timeout __attribute__((packed));
+};
+
+/* found in the 508's control window at RXBUF_INFO */
+struct buf_info {
+ unsigned short rse_num __attribute__((packed));
+ unsigned long rse_base __attribute__((packed));
+ unsigned long rse_next __attribute__((packed));
+ unsigned long buf_base __attribute__((packed));
+ unsigned short reserved __attribute__((packed));
+ unsigned long buf_top __attribute__((packed));
+};
+
+/* structure pointed to by rse_base in RXBUF_INFO struct */
+struct buf_entry {
+ char opp_flag __attribute__((packed));
+ short length __attribute__((packed));
+ short dlci __attribute__((packed));
+ char flags __attribute__((packed));
+ short timestamp __attribute__((packed));
+ short reserved[2] __attribute__((packed));
+ long buf_addr __attribute__((packed));
+};
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/sdla_fr.h b/pfinet/linux-src/include/linux/sdla_fr.h
new file mode 100644
index 00000000..533f2acb
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sdla_fr.h
@@ -0,0 +1,422 @@
+/*****************************************************************************
+* sdla_fr.h Sangoma frame relay firmware API definitions.
+*
+* Author: Jaspreet Singh <jaspreet@sangoma.com>
+* Gene Kozin <74604.152@compuserve.com>
+*
+* Copyright: (c) 1995-1996 Sangoma Technologies Inc.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version
+* 2 of the License, or (at your option) any later version.
+* ============================================================================
+* Oct 12, 1997 Jaspreet Singh Added FR_READ_DLCI_IB_MAPPING
+* Jul 21, 1997 Jaspreet Singh Changed FRRES_TOO_LONG and FRRES_TOO_MANY to
+* 0x05 and 0x06 respectively.
+* Dec 23, 1996 Gene Kozin v2.0
+* Apr 29, 1996 Gene Kozin v1.0 (merged version S502 & S508 definitions).
+* Sep 26, 1995 Gene Kozin Initial version.
+*****************************************************************************/
+#ifndef _SDLA_FR_H
+#define _SDLA_FR_H
+
+/*----------------------------------------------------------------------------
+ * Notes:
+ * ------
+ * 1. All structures defined in this file are byte-alined. To ensure
+ * portability of this code between different platforms and compilers, one
+ * of the following defines must be defined before including this file:
+ *
+ * Compiler Platform Define Use option
+ * -------- -------- ------ ----------
+ * GNU C Linux _GNUC_ -
+ * Microsoft C DOS/Windows _MSC_ -
+ */
+
+#ifdef _GNUC_
+# ifndef PACKED
+# define PACKED __attribute__((packed))
+# endif /* PACKED */
+#else
+# define PACKED
+#endif
+#ifdef _MSC_
+# pragma pack(1)
+#endif
+
+/* Adapter memory layout */
+#define FR_MB_VECTOR 0xE000 /* mailbox window vector */
+#define FR502_RX_VECTOR 0xA000 /* S502 direct receive window vector */
+#define FR502_MBOX_OFFS 0xF60 /* S502 mailbox offset */
+#define FR508_MBOX_OFFS 0 /* S508 mailbox offset */
+#define FR502_FLAG_OFFS 0x1FF0 /* S502 status flags offset */
+#define FR508_FLAG_OFFS 0x1000 /* S508 status flags offset */
+#define FR502_RXMB_OFFS 0x900 /* S502 direct receive mailbox offset */
+#define FR508_TXBC_OFFS 0x1100 /* S508 Tx buffer info offset */
+#define FR508_RXBC_OFFS 0x1120 /* S508 Rx buffer info offset */
+
+/* Important constants */
+#define FR502_MAX_DATA 4096 /* maximum data buffer length */
+#define FR508_MAX_DATA 4080 /* maximum data buffer length */
+
+/****** Data Structures *****************************************************/
+
+/*----------------------------------------------------------------------------
+ * Frame relay command block.
+ */
+typedef struct fr_cmd
+{
+ unsigned char command PACKED; /* command code */
+ unsigned short length PACKED; /* length of data buffer */
+ unsigned char result PACKED; /* return code */
+ unsigned short dlci PACKED; /* DLCI number */
+ unsigned char attr PACKED; /* FECN, BECN, DE and C/R bits */
+ unsigned short rxlost1 PACKED; /* frames discarded at int. level */
+ unsigned long rxlost2 PACKED; /* frames discarded at app. level */
+ unsigned char rsrv[2] PACKED; /* reserved for future use */
+} fr_cmd_t;
+
+/* 'command' field defines */
+#define FR_WRITE 0x01
+#define FR_READ 0x02
+#define FR_ISSUE_IS_FRAME 0x03
+#define FR_SET_CONFIG 0x10
+#define FR_READ_CONFIG 0x11
+#define FR_COMM_DISABLE 0x12
+#define FR_COMM_ENABLE 0x13
+#define FR_READ_STATUS 0x14
+#define FR_READ_STATISTICS 0x15
+#define FR_FLUSH_STATISTICS 0x16
+#define FR_LIST_ACTIVE_DLCI 0x17
+#define FR_FLUSH_DATA_BUFFERS 0x18
+#define FR_ADD_DLCI 0x20
+#define FR_DELETE_DLCI 0x21
+#define FR_ACTIVATE_DLCI 0x22
+#define FR_DEACTIVATE_DLCI 0x22
+#define FR_READ_MODEM_STATUS 0x30
+#define FR_SET_MODEM_STATUS 0x31
+#define FR_READ_ERROR_STATS 0x32
+#define FR_FLUSH_ERROR_STATS 0x33
+#define FR_READ_DLCI_IB_MAPPING 0x34
+#define FR_READ_CODE_VERSION 0x40
+#define FR_SET_INTR_MODE 0x50
+#define FR_READ_INTR_MODE 0x51
+
+/* 'result' field defines */
+#define FRRES_OK 0x00 /* command executed successfully */
+#define FRRES_DISABLED 0x01 /* communications not enabled */
+#define FRRES_INOPERATIVE 0x02 /* channel inoperative */
+#define FRRES_DLCI_INACTIVE 0x03 /* DLCI is inactive */
+#define FRRES_DLCI_INVALID 0x04 /* DLCI is not configured */
+#define FRRES_TOO_LONG 0x05
+#define FRRES_TOO_MANY 0x06
+#define FRRES_CIR_OVERFLOW 0x07 /* Tx throughput has exceeded CIR */
+#define FRRES_BUFFER_OVERFLOW 0x08
+#define FRRES_MODEM_FAILURE 0x10 /* DCD and/or CTS dropped */
+#define FRRES_CHANNEL_DOWN 0x11 /* channel became inoperative */
+#define FRRES_CHANNEL_UP 0x12 /* channel became operative */
+#define FRRES_DLCI_CHANGE 0x13 /* DLCI status (or number) changed */
+#define FRRES_DLCI_MISMATCH 0x14
+#define FRRES_INVALID_CMD 0x1F /* invalid command */
+
+/* 'attr' field defines */
+#define FRATTR_
+
+/*----------------------------------------------------------------------------
+ * Frame relay mailbox.
+ * This structure is located at offset FR50?_MBOX_OFFS into FR_MB_VECTOR.
+ * For S502 it is also located at offset FR502_RXMB_OFFS into
+ * FR502_RX_VECTOR.
+ */
+typedef struct fr_mbox
+{
+ unsigned char opflag PACKED; /* 00h: execution flag */
+ fr_cmd_t cmd PACKED; /* 01h: command block */
+ unsigned char data[1] PACKED; /* 10h: variable length data buffer */
+} fr_mbox_t;
+
+/*----------------------------------------------------------------------------
+ * S502 frame relay status flags.
+ * This structure is located at offset FR502_FLAG_OFFS into FR_MB_VECTOR.
+ */
+typedef struct fr502_flags
+{
+ unsigned char rsrv1[1] PACKED; /* 00h: */
+ unsigned char tx_ready PACKED; /* 01h: Tx buffer available */
+ unsigned char rx_ready PACKED; /* 02h: Rx frame available */
+ unsigned char event PACKED; /* 03h: asynchronous event */
+ unsigned char mstatus PACKED; /* 04h: modem status */
+ unsigned char rsrv2[8] PACKED; /* 05h: */
+ unsigned char iflag PACKED; /* 0Dh: interrupt flag */
+ unsigned char imask PACKED; /* 0Eh: interrupt mask */
+} fr502_flags_t;
+
+/*----------------------------------------------------------------------------
+ * S508 frame relay status flags.
+ * This structure is located at offset FR508_FLAG_OFFS into FR_MB_VECTOR.
+ */
+typedef struct fr508_flags
+{
+ unsigned char rsrv1[3] PACKED; /* 00h: reserved */
+ unsigned char event PACKED; /* 03h: asynchronous event */
+ unsigned char mstatus PACKED; /* 04h: modem status */
+ unsigned char rsrv2[11] PACKED; /* 05h: reserved */
+ unsigned char iflag PACKED; /* 10h: interrupt flag */
+ unsigned char imask PACKED; /* 11h: interrupt mask */
+ unsigned long tse_offs PACKED; /* 12h: Tx status element */
+ unsigned short dlci PACKED; /* 16h: DLCI NUMBER */
+} fr508_flags_t;
+
+/* 'event' field defines */
+#define FR_EVENT_STATUS 0x01 /* channel status change ??? */
+#define FR_EVENT_DLC_STATUS 0x02 /* DLC status change */
+#define FR_EVENT_BAD_DLCI 0x04 /* FSR included wrong DLCI */
+#define FR_EVENT_LINK_DOWN 0x40 /* DCD or CTS low */
+
+/* 'mstatus' field defines */
+#define FR_MDM_DCD 0x08 /* mdm_status: DCD */
+#define FR_MDM_CTS 0x20 /* mdm_status: CTS */
+
+/* 'iflag' & 'imask' fields defines */
+#define FR_INTR_RXRDY 0x01 /* Rx ready */
+#define FR_INTR_TXRDY 0x02 /* Tx ready */
+#define FR_INTR_MODEM 0x04 /* modem status change (DCD, CTS) */
+#define FR_INTR_READY 0x08 /* interface command completed */
+#define FR_INTR_DLC 0x10 /* DLC status change */
+#define FR_INTR_TIMER 0x20 /* millisecond timer */
+
+/*----------------------------------------------------------------------------
+ * Receive Buffer Configuration Info. S508 only!
+ * This structure is located at offset FR508_RXBC_OFFS into FR_MB_VECTOR.
+ */
+typedef struct fr_buf_info
+{
+ unsigned short rse_num PACKED; /* 00h: number of status elements */
+ unsigned long rse_base PACKED; /* 02h: receive status array base */
+ unsigned long rse_next PACKED; /* 06h: next status element */
+ unsigned long buf_base PACKED; /* 0Ah: rotational buffer base */
+ unsigned short reserved PACKED; /* 0Eh: */
+ unsigned long buf_top PACKED; /* 10h: rotational buffer top */
+} fr_buf_info_t;
+
+/*----------------------------------------------------------------------------
+ * Buffer Status Element. S508 only!
+ * Array of structures of this type is located at offset defined by the
+ * 'rse_base' field of the frBufInfo_t structure into absolute adapter
+ * memory address space.
+ */
+typedef struct fr_buf_ctl
+{
+ unsigned char flag PACKED; /* 00h: ready flag */
+ unsigned short length PACKED; /* 01h: frame length */
+ unsigned short dlci PACKED; /* 03h: DLCI */
+ unsigned char attr PACKED; /* 05h: FECN/BECN/DE/CR */
+ unsigned short tmstamp PACKED; /* 06h: time stamp */
+ unsigned short rsrv[2] PACKED; /* 08h: */
+ unsigned long offset PACKED; /* 0Ch: buffer absolute address */
+} fr_buf_ctl_t;
+
+/*----------------------------------------------------------------------------
+ * Global Configuration Block. Passed to FR_SET_CONFIG command when dlci == 0.
+ */
+typedef struct fr_conf
+{
+ unsigned short station PACKED; /* 00h: CPE/Node */
+ unsigned short options PACKED; /* 02h: configuration options */
+ unsigned short kbps PACKED; /* 04h: baud rate in kbps */
+ unsigned short port PACKED; /* 06h: RS-232/V.35 */
+ unsigned short mtu PACKED; /* 08h: max. transmit length */
+ unsigned short t391 PACKED; /* 0Ah: */
+ unsigned short t392 PACKED; /* 0Ch: */
+ unsigned short n391 PACKED; /* 0Eh: */
+ unsigned short n392 PACKED; /* 10h: */
+ unsigned short n393 PACKED; /* 12h: */
+ unsigned short cir_fwd PACKED; /* 14h: */
+ unsigned short bc_fwd PACKED; /* 16h: */
+ unsigned short be_fwd PACKED; /* 18h: */
+ unsigned short cir_bwd PACKED; /* 1Ah: */
+ unsigned short bc_bwd PACKED; /* 1Ch: */
+ unsigned short be_bwd PACKED; /* 1Eh: */
+ unsigned short dlci[0] PACKED; /* 20h: */
+} fr_conf_t;
+
+/* 'station_type' defines */
+#define FRCFG_STATION_CPE 0
+#define FRCFG_STATION_NODE 1
+
+/* 'conf_flags' defines */
+#define FRCFG_IGNORE_TX_CIR 0x0001
+#define FRCFG_IGNORE_RX_CIR 0x0002
+#define FRCFG_DONT_RETRANSMIT 0x0004
+#define FRCFG_IGNORE_CBS 0x0008
+#define FRCFG_THROUGHPUT 0x0010 /* enable throughput calculation */
+#define FRCFG_DIRECT_RX 0x0080 /* enable direct receive buffer */
+#define FRCFG_AUTO_CONFIG 0x8000 /* enable auto DLCI configuration */
+
+/* 'baud_rate' defines */
+#define FRCFG_BAUD_1200 12
+#define FRCFG_BAUD_2400 24
+#define FRCFG_BAUD_4800 48
+#define FRCFG_BAUD_9600 96
+#define FRCFG_BAUD_19200 19
+#define FRCFG_BAUD_38400 38
+#define FRCFG_BAUD_56000 56
+#define FRCFG_BAUD_64000 64
+#define FRCFG_BAUD_128000 128
+
+/* 'port_mode' defines */
+#define FRCFG_MODE_EXT_CLK 0x0000
+#define FRCFG_MODE_INT_CLK 0x0001
+#define FRCFG_MODE_V35 0x0000 /* S508 only */
+#define FRCFG_MODE_RS232 0x0002 /* S508 only */
+
+/*----------------------------------------------------------------------------
+ * Channel configuration.
+ * This structure is passed to the FR_SET_CONFIG command when dlci != 0.
+ */
+typedef struct fr_dlc_conf
+{
+ unsigned short conf_flags PACKED; /* 00h: configuration bits */
+ unsigned short cir_fwd PACKED; /* 02h: */
+ unsigned short bc_fwd PACKED; /* 04h: */
+ unsigned short be_fwd PACKED; /* 06h: */
+ unsigned short cir_bwd PACKED; /* 08h: */
+ unsigned short bc_bwd PACKED; /* 0Ah: */
+ unsigned short be_bwd PACKED; /* 0Ch: */
+} fr_dlc_conf_t;
+
+/*----------------------------------------------------------------------------
+ * S502 interrupt mode control block.
+ * This structure is passed to the FR_SET_INTR_FLAGS and returned by the
+ * FR_READ_INTR_FLAGS commands.
+ */
+typedef struct fr502_intr_ctl
+{
+ unsigned char mode PACKED; /* 00h: interrupt enable flags */
+ unsigned short tx_len PACKED; /* 01h: required Tx buffer size */
+} fr502_intr_ctl_t;
+
+/*----------------------------------------------------------------------------
+ * S508 interrupt mode control block.
+ * This structure is passed to the FR_SET_INTR_FLAGS and returned by the
+ * FR_READ_INTR_FLAGS commands.
+ */
+typedef struct fr508_intr_ctl
+{
+ unsigned char mode PACKED; /* 00h: interrupt enable flags */
+ unsigned short tx_len PACKED; /* 01h: required Tx buffer size */
+ unsigned char irq PACKED; /* 03h: IRQ level to activate */
+ unsigned char flags PACKED; /* 04h: ?? */
+ unsigned short timeout PACKED; /* 05h: ms, for timer interrupt */
+} fr508_intr_ctl_t;
+
+/*----------------------------------------------------------------------------
+ * Channel status.
+ * This structure is returned by the FR_READ_STATUS command.
+ */
+typedef struct fr_dlc_Status
+{
+ unsigned char status PACKED; /* 00h: link/DLCI status */
+ struct
+ {
+ unsigned short dlci PACKED; /* 01h: DLCI number */
+ unsigned char status PACKED; /* 03h: DLCI status */
+ } circuit[1] PACKED;
+} fr_dlc_status_t;
+
+/* 'status' defines */
+#define FR_LINK_INOPER 0x00 /* for global status (DLCI == 0) */
+#define FR_LINK_OPER 0x01
+#define FR_DLCI_DELETED 0x01 /* for circuit status (DLCI != 0) */
+#define FR_DLCI_ACTIVE 0x02
+#define FR_DLCI_WAITING 0x04
+#define FR_DLCI_NEW 0x08
+#define FR_DLCI_REPORT 0x40
+
+/*----------------------------------------------------------------------------
+ * Global Statistics Block.
+ * This structure is returned by the FR_READ_STATISTICS command when
+ * dcli == 0.
+ */
+typedef struct fr_link_stat
+{
+ unsigned short rx_too_long PACKED; /* 00h: */
+ unsigned short rx_dropped PACKED; /* 02h: */
+ unsigned short rx_dropped2 PACKED; /* 04h: */
+ unsigned short rx_bad_dlci PACKED; /* 06h: */
+ unsigned short rx_bad_format PACKED; /* 08h: */
+ unsigned short retransmitted PACKED; /* 0Ah: */
+ unsigned short cpe_tx_FSE PACKED; /* 0Ch: */
+ unsigned short cpe_tx_LIV PACKED; /* 0Eh: */
+ unsigned short cpe_rx_FSR PACKED; /* 10h: */
+ unsigned short cpe_rx_LIV PACKED; /* 12h: */
+ unsigned short node_rx_FSE PACKED; /* 14h: */
+ unsigned short node_rx_LIV PACKED; /* 16h: */
+ unsigned short node_tx_FSR PACKED; /* 18h: */
+ unsigned short node_tx_LIV PACKED; /* 1Ah: */
+ unsigned short rx_ISF_err PACKED; /* 1Ch: */
+ unsigned short rx_unsolicited PACKED; /* 1Eh: */
+ unsigned short rx_SSN_err PACKED; /* 20h: */
+ unsigned short rx_RSN_err PACKED; /* 22h: */
+ unsigned short T391_timeouts PACKED; /* 24h: */
+ unsigned short T392_timeouts PACKED; /* 26h: */
+ unsigned short N392_reached PACKED; /* 28h: */
+ unsigned short cpe_SSN_RSN PACKED; /* 2Ah: */
+ unsigned short current_SSN PACKED; /* 2Ch: */
+ unsigned short current_RSN PACKED; /* 2Eh: */
+ unsigned short curreny_T391 PACKED; /* 30h: */
+ unsigned short current_T392 PACKED; /* 32h: */
+ unsigned short current_N392 PACKED; /* 34h: */
+ unsigned short current_N393 PACKED; /* 36h: */
+} fr_link_stat_t;
+
+/*----------------------------------------------------------------------------
+ * DLCI statistics.
+ * This structure is returned by the FR_READ_STATISTICS command when
+ * dlci != 0.
+ */
+typedef struct fr_dlci_stat
+{
+ unsigned long tx_frames PACKED; /* 00h: */
+ unsigned long tx_bytes PACKED; /* 04h: */
+ unsigned long rx_frames PACKED; /* 08h: */
+ unsigned long rx_bytes PACKED; /* 0Ch: */
+ unsigned long rx_dropped PACKED; /* 10h: */
+ unsigned long rx_inactive PACKED; /* 14h: */
+ unsigned long rx_exceed_CIR PACKED; /* 18h: */
+ unsigned long rx_DE_set PACKED; /* 1Ch: */
+ unsigned long tx_throughput PACKED; /* 20h: */
+ unsigned long tx_calc_timer PACKED; /* 24h: */
+ unsigned long rx_throughput PACKED; /* 28h: */
+ unsigned long rx_calc_timer PACKED; /* 2Ch: */
+} fr_dlci_stat_t;
+
+/*----------------------------------------------------------------------------
+ * Communications error statistics.
+ * This structure is returned by the FR_READ_ERROR_STATS command.
+ */
+typedef struct fr_comm_stat
+{
+ unsigned char rx_overruns PACKED; /* 00h: */
+ unsigned char rx_bad_crc PACKED; /* 01h: */
+ unsigned char rx_aborts PACKED; /* 02h: */
+ unsigned char rx_too_long PACKED; /* 03h: */
+ unsigned char tx_aborts PACKED; /* 04h: */
+ unsigned char tx_underruns PACKED; /* 05h: */
+ unsigned char tx_missed_undr PACKED; /* 06h: */
+ unsigned char dcd_dropped PACKED; /* 07h: */
+ unsigned char cts_dropped PACKED; /* 08h: */
+} fr_comm_stat_t;
+
+/*----------------------------------------------------------------------------
+ * Defines for the FR_ISSUE_IS_FRAME command.
+ */
+#define FR_ISF_LVE 2 /* issue Link Verification Enquiry */
+#define FR_ISF_FSE 3 /* issue Full Status Enquiry */
+
+#ifdef _MSC_
+# pragma pack()
+#endif
+#endif /* _SDLA_FR_H */
+
diff --git a/pfinet/linux-src/include/linux/sdla_ppp.h b/pfinet/linux-src/include/linux/sdla_ppp.h
new file mode 100644
index 00000000..26798683
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sdla_ppp.h
@@ -0,0 +1,536 @@
+/*****************************************************************************
+* sdla_ppp.h Sangoma PPP firmware API definitions.
+*
+* Author: Gene Kozin <74604.152@compuserve.com>
+*
+* Copyright: (c) 1995-1997 Sangoma Technologies Inc.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version
+* 2 of the License, or (at your option) any later version.
+* ============================================================================
+* Jan 06, 1997 Gene Kozin v2.0
+* Apr 11, 1996 Gene Kozin Initial version.
+*****************************************************************************/
+#ifndef _SDLA_PPP_H
+#define _SDLA_PPP_H
+
+/*----------------------------------------------------------------------------
+ * Notes:
+ * ------
+ * 1. All structures defined in this file are byte-alined. To ensure
+ * portability of this code between different platforms and compilers, one
+ * of the following defines must be defined before including this file:
+ *
+ * Compiler Platform Define Use option
+ * -------- -------- ------ ----------
+ * GNU C Linux _GNUC_ -
+ * Microsoft C DOS/Windows _MSC_ -
+ */
+
+#ifdef _GNUC_
+# ifndef PACKED
+# define PACKED __attribute__((packed))
+# endif /* PACKED */
+#else
+# define PACKED
+#endif
+#ifdef _MSC_
+# pragma pack(1)
+#endif
+
+/* Adapter memory layout and important constants */
+
+#define PPP502_MB_VECT 0xA000 /* mailbox window vector */
+#define PPP502_MB_OFFS 0x1C00 /* mailbox offset */
+#define PPP502_FLG_OFFS 0 /* status flags offset */
+#define PPP502_BUF_OFFS 0x0010 /* buffer info block offset */
+
+#define PPP508_MB_VECT 0xE000 /* mailbox window vector */
+#define PPP508_MB_OFFS 0 /* mailbox offset */
+#define PPP508_FLG_OFFS 0x1000 /* status flags offset */
+#define PPP508_BUF_OFFS 0x1100 /* buffer info block offset */
+
+#define PPP_MAX_DATA 1008 /* command block data buffer length */
+
+/****** Data Structures *****************************************************/
+
+/*----------------------------------------------------------------------------
+ * PPP Command Block.
+ */
+typedef struct ppp_cmd
+{
+ unsigned char command PACKED; /* command code */
+ unsigned short length PACKED; /* length of data buffer */
+ unsigned char result PACKED; /* return code */
+ unsigned char rsrv[11] PACKED; /* reserved for future use */
+} ppp_cmd_t;
+
+/* 'command' field defines */
+#define PPP_READ_CODE_VERSION 0x10 /* configuration commands */
+#define PPP_SET_CONFIG 0x05
+#define PPP_READ_CONFIG 0x06
+#define PPP_SET_INTR_FLAGS 0x20
+#define PPP_READ_INTR_FLAGS 0x21
+#define PPP_SET_INBOUND_AUTH 0x30
+#define PPP_SET_OUTBOUND_AUTH 0x31
+#define PPP_GET_CONNECTION_INFO 0x32
+
+#define PPP_COMM_ENABLE 0x03 /* operational commands */
+#define PPP_COMM_DISABLE 0x04
+#define PPP_SEND_SIGN_FRAME 0x23
+#define PPP_READ_SIGN_RESPONSE 0x24
+#define PPP_DATALINE_MONITOR 0x33
+
+#define PPP_READ_STATISTICS 0x07 /* statistics commands */
+#define PPP_FLUSH_STATISTICS 0x08
+#define PPP_READ_ERROR_STATS 0x09
+#define PPP_FLUSH_ERROR_STATS 0x0A
+#define PPP_READ_PACKET_STATS 0x12
+#define PPP_FLUSH_PACKET_STATS 0x13
+#define PPP_READ_LCP_STATS 0x14
+#define PPP_FLUSH_LCP_STATS 0x15
+#define PPP_READ_LPBK_STATS 0x16
+#define PPP_FLUSH_LPBK_STATS 0x17
+#define PPP_READ_IPCP_STATS 0x18
+#define PPP_FLUSH_IPCP_STATS 0x19
+#define PPP_READ_IPXCP_STATS 0x1A
+#define PPP_FLUSH_IPXCP_STATS 0x1B
+#define PPP_READ_PAP_STATS 0x1C
+#define PPP_FLUSH_PAP_STATS 0x1D
+#define PPP_READ_CHAP_STATS 0x1E
+#define PPP_FLUSH_CHAP_STATS 0x1F
+
+/* 'result' field defines */
+#define PPPRES_OK 0x00 /* command executed successfully */
+#define PPPRES_INVALID_STATE 0x09 /* invalid command in this context */
+
+/*----------------------------------------------------------------------------
+ * PPP Mailbox.
+ * This structure is located at offset PPP???_MB_OFFS into PPP???_MB_VECT
+ */
+typedef struct ppp_mbox
+{
+ unsigned char flag PACKED; /* 00h: command execution flag */
+ ppp_cmd_t cmd PACKED; /* 01h: command block */
+ unsigned char data[1] PACKED; /* 10h: variable length data buffer */
+} ppp_mbox_t;
+
+/*----------------------------------------------------------------------------
+ * PPP Status Flags.
+ * This structure is located at offset PPP???_FLG_OFFS into
+ * PPP???_MB_VECT.
+ */
+typedef struct ppp_flags
+{
+ unsigned char iflag PACKED; /* 00: interrupt flag */
+ unsigned char imask PACKED; /* 01: interrupt mask */
+ unsigned char resrv PACKED;
+ unsigned char mstatus PACKED; /* 03: modem status */
+ unsigned char lcp_state PACKED; /* 04: LCP state */
+ unsigned char ppp_phase PACKED; /* 05: PPP phase */
+ unsigned char ip_state PACKED; /* 06: IPCP state */
+ unsigned char ipx_state PACKED; /* 07: IPXCP state */
+ unsigned char pap_state PACKED; /* 08: PAP state */
+ unsigned char chap_state PACKED; /* 09: CHAP state */
+ unsigned short disc_cause PACKED; /* 0A: disconnection cause */
+} ppp_flags_t;
+
+/* 'iflag' defines */
+#define PPP_INTR_RXRDY 0x01 /* Rx ready */
+#define PPP_INTR_TXRDY 0x02 /* Tx ready */
+#define PPP_INTR_MODEM 0x04 /* modem status change (DCD, CTS) */
+#define PPP_INTR_CMD 0x08 /* interface command completed */
+#define PPP_INTR_DISC 0x10 /* data link disconnected */
+#define PPP_INTR_OPEN 0x20 /* data link open */
+#define PPP_INTR_DROP_DTR 0x40 /* DTR drop timeout expired */
+
+/* 'mstatus' defines */
+#define PPP_MDM_DCD 0x08 /* mdm_status: DCD */
+#define PPP_MDM_CTS 0x20 /* mdm_status: CTS */
+
+/*----------------------------------------------------------------------------
+ * PPP Buffer Info.
+ * This structure is located at offset PPP502_BUF_OFFS into
+ * PPP502_MB_VECT.
+ */
+typedef struct ppp502_buf_info
+{
+ unsigned short txb_num PACKED; /* 00: number of transmit buffers */
+ unsigned short txb_offs PACKED; /* 02: offset of the buffer ctl. */
+ unsigned char rsrv1[4] PACKED;
+ unsigned short rxb_num PACKED; /* 08: number of receive buffers */
+ unsigned short rxb_offs PACKED; /* 0A: offset of the buffer ctl. */
+ unsigned char rsrv2[2] PACKED;
+ unsigned short rxb_next PACKED; /* 0E: index of the next buffer */
+} ppp502_buf_info_t;
+
+/*----------------------------------------------------------------------------
+ * PPP Buffer Info.
+ * This structure is located at offset PPP508_BUF_OFFS into
+ * PPP508_MB_VECT.
+ */
+typedef struct ppp508_buf_info
+{
+ unsigned short txb_num PACKED; /* 00: number of transmit buffers */
+ unsigned long txb_ptr PACKED; /* 02: pointer to the buffer ctl. */
+ unsigned char rsrv1[26] PACKED;
+ unsigned short rxb_num PACKED; /* 20: number of receive buffers */
+ unsigned long rxb_ptr PACKED; /* 22: pointer to the buffer ctl. */
+ unsigned long rxb1_ptr PACKED; /* 26: pointer to the first buf.ctl. */
+ unsigned long rxb_base PACKED; /* 2A: pointer to the buffer base */
+ unsigned char rsrv2[2] PACKED;
+ unsigned long rxb_end PACKED; /* 30: pointer to the buffer end */
+} ppp508_buf_info_t;
+
+/*----------------------------------------------------------------------------
+ * Transmit/Receive Buffer Control Block.
+ */
+typedef struct ppp_buf_ctl
+{
+ unsigned char flag PACKED; /* 00: 'buffer ready' flag */
+ unsigned short length PACKED; /* 01: length of data */
+ unsigned char reserved1[1] PACKED; /* 03: */
+ unsigned char proto PACKED; /* 04: protocol */
+ unsigned short timestamp PACKED; /* 05: time stamp (Rx only) */
+ unsigned char reserved2[5] PACKED; /* 07: */
+ union
+ {
+ unsigned short o_p[2]; /* 1C: buffer offset & page (S502) */
+ unsigned long ptr; /* 1C: buffer pointer (S508) */
+ } buf PACKED;
+} ppp_buf_ctl_t;
+
+/*----------------------------------------------------------------------------
+ * S502 Adapter Configuration Block (passed to the PPP_SET_CONFIG command).
+ */
+typedef struct ppp502_conf
+{
+ unsigned char line_speed PACKED; /* 00: 0 - external clk. */
+ unsigned short txbuf_num PACKED; /* 01: number of Tx buffers */
+ unsigned short conf_flags PACKED; /* 03: configuration bits */
+ unsigned short mtu_local PACKED; /* 05: local MTU */
+ unsigned short mtu_remote PACKED; /* 07: remote MTU */
+ unsigned short restart_tmr PACKED; /* 09: restart timer */
+ unsigned short auth_rsrt_tmr PACKED; /* 0B: authentication timer */
+ unsigned short auth_wait_tmr PACKED; /* 0D: authentication timer */
+ unsigned short mdm_fail_tmr PACKED; /* 0F: modem failure timer */
+ unsigned short dtr_drop_tmr PACKED; /* 11: DTR drop timer */
+ unsigned short connect_tmout PACKED; /* 13: connection timeout */
+ unsigned short conf_retry PACKED; /* 15: max. retry */
+ unsigned short term_retry PACKED; /* 17: max. retry */
+ unsigned short fail_retry PACKED; /* 19: max. retry */
+ unsigned short auth_retry PACKED; /* 1B: max. retry */
+ unsigned char auth_options PACKED; /* 1D: authentication opt. */
+ unsigned char ip_options PACKED; /* 1E: IP options */
+ unsigned char ip_local[4] PACKED; /* 1F: local IP address */
+ unsigned char ip_remote[4] PACKED; /* 23: remote IP address */
+ unsigned char ipx_options PACKED; /* 27: IPX options */
+ unsigned char ipx_netno[4] PACKED; /* 28: IPX net number */
+ unsigned char ipx_local[6] PACKED; /* 2C: local IPX node number*/
+ unsigned char ipx_remote[6] PACKED; /* 32: remote IPX node num.*/
+ unsigned char ipx_router[48] PACKED; /* 38: IPX router name*/
+} ppp502_conf_t;
+
+/*----------------------------------------------------------------------------
+ * S508 Adapter Configuration Block (passed to the PPP_SET_CONFIG command).
+ */
+typedef struct ppp508_conf
+{
+ unsigned long line_speed PACKED; /* 00: baud rate, bps */
+ unsigned short txbuf_percent PACKED; /* 04: % of Tx buffer */
+ unsigned short conf_flags PACKED; /* 06: configuration bits */
+ unsigned short mtu_local PACKED; /* 08: local MTU */
+ unsigned short mtu_remote PACKED; /* 0A: remote MTU */
+ unsigned short restart_tmr PACKED; /* 0C: restart timer */
+ unsigned short auth_rsrt_tmr PACKED; /* 0E: authentication timer */
+ unsigned short auth_wait_tmr PACKED; /* 10: authentication timer */
+ unsigned short mdm_fail_tmr PACKED; /* 12: modem failure timer */
+ unsigned short dtr_drop_tmr PACKED; /* 14: DTR drop timer */
+ unsigned short connect_tmout PACKED; /* 16: connection timeout */
+ unsigned short conf_retry PACKED; /* 18: max. retry */
+ unsigned short term_retry PACKED; /* 1A: max. retry */
+ unsigned short fail_retry PACKED; /* 1C: max. retry */
+ unsigned short auth_retry PACKED; /* 1E: max. retry */
+ unsigned char auth_options PACKED; /* 20: authentication opt. */
+ unsigned char ip_options PACKED; /* 21: IP options */
+ unsigned char ip_local[4] PACKED; /* 22: local IP address */
+ unsigned char ip_remote[4] PACKED; /* 26: remote IP address */
+ unsigned char ipx_options PACKED; /* 2A: IPX options */
+ unsigned char ipx_netno[4] PACKED; /* 2B: IPX net number */
+ unsigned char ipx_local[6] PACKED; /* 2F: local IPX node number*/
+ unsigned char ipx_remote[6] PACKED; /* 35: remote IPX node num.*/
+ unsigned char ipx_router[48] PACKED; /* 3B: IPX router name*/
+ unsigned long alt_cpu_clock PACKED; /* 6B: */
+} ppp508_conf_t;
+
+/* 'line_speed' field */
+#define PPP_BITRATE_1200 0x01
+#define PPP_BITRATE_2400 0x02
+#define PPP_BITRATE_4800 0x03
+#define PPP_BITRATE_9600 0x04
+#define PPP_BITRATE_19200 0x05
+#define PPP_BITRATE_38400 0x06
+#define PPP_BITRATE_45000 0x07
+#define PPP_BITRATE_56000 0x08
+#define PPP_BITRATE_64000 0x09
+#define PPP_BITRATE_74000 0x0A
+#define PPP_BITRATE_112000 0x0B
+#define PPP_BITRATE_128000 0x0C
+#define PPP_BITRATE_156000 0x0D
+
+/* Defines for the 'conf_flags' field */
+#define PPP_IGNORE_TX_ABORT 0x01 /* don't re-transmit aborted frames */
+#define PPP_ENABLE_TX_STATS 0x02 /* enable Tx statistics */
+#define PPP_ENABLE_RX_STATS 0x04 /* enable Rx statistics */
+#define PPP_ENABLE_TIMESTAMP 0x08 /* enable timestamp */
+
+/* 'ip_options' defines */
+#define PPP_LOCAL_IP_LOCAL 0x01
+#define PPP_LOCAL_IP_REMOTE 0x02
+#define PPP_REMOTE_IP_LOCAL 0x04
+#define PPP_REMOTE_IP_REMOTE 0x08
+
+/* 'ipx_options' defines */
+#define PPP_REMOTE_IPX_NETNO 0x01
+#define PPP_REMOTE_IPX_LOCAL 0x02
+#define PPP_REMOTE_IPX_REMOTE 0x04
+#define PPP_IPX_ROUTE_RIP_SAP 0x08
+#define PPP_IPX_ROUTE_NLSP 0x10
+#define PPP_IPX_ROUTE_DEFAULT 0x20
+#define PPP_IPX_CONF_COMPLETE 0x40
+#define PPP_IPX_ENABLE 0x80
+
+/*----------------------------------------------------------------------------
+ * S502 Adapter Configuration Block (returned by the PPP_READ_CONFIG command).
+ */
+typedef struct ppp502_get_conf
+{
+ ppp502_conf_t conf PACKED; /* 00: requested config. */
+ unsigned short txb_num PACKED; /* 68: number of Tx buffers */
+ unsigned short rxb_num PACKED; /* 6A: number of Rx buffers */
+} ppp502_get_conf_t;
+
+/*----------------------------------------------------------------------------
+ * S508 Adapter Configuration Block (returned by the PPP_READ_CONFIG command).
+ */
+typedef struct ppp508_get_conf
+{
+ unsigned long bps PACKED; /* 00: baud rate, bps */
+ ppp508_conf_t conf PACKED; /* 04: requested config. */
+ unsigned short txb_num PACKED; /* 6F: number of Tx buffers */
+ unsigned short rxb_num PACKED; /* 71: number of Rx buffers */
+} ppp508_get_conf_t;
+
+/*----------------------------------------------------------------------------
+ * S502 Operational Statistics (returned by the PPP_READ_STATISTIC command).
+ */
+typedef struct ppp502_Stats
+{
+ unsigned short rx_lost_intr PACKED; /* 00: */
+ unsigned short rx_lost_buff PACKED; /* 02: */
+ unsigned short tx_abort PACKED; /* 04: */
+ unsigned long tx_frames PACKED; /* 06: */
+ unsigned long tx_bytes PACKED; /* 0A: */
+ unsigned long rx_frames PACKED; /* 0E: */
+ unsigned long rx_bytes PACKED; /* 12: */
+} ppp502_Stats_t;
+
+/*----------------------------------------------------------------------------
+ * S508 Operational Statistics (returned by the PPP_READ_STATISTIC command).
+ */
+typedef struct ppp508_stats
+{
+ unsigned short reserved1 PACKED; /* 00: */
+ unsigned short rx_bad_len PACKED; /* 02: */
+ unsigned short reserved2 PACKED; /* 04: */
+ unsigned long tx_frames PACKED; /* 06: */
+ unsigned long tx_bytes PACKED; /* 0A: */
+ unsigned long rx_frames PACKED; /* 0E: */
+ unsigned long rx_bytes PACKED; /* 12: */
+} ppp508_stats_t;
+
+/*----------------------------------------------------------------------------
+ * Adapter Error Statistics (returned by the PPP_READ_ERROR_STATS command).
+ */
+typedef struct ppp_err_stats
+{
+ unsigned char rx_overrun PACKED; /* 00: Rx overrun errors */
+ unsigned char rx_bad_crc PACKED; /* 01: Rx CRC errors */
+ unsigned char rx_abort PACKED; /* 02: Rx aborted frames */
+ unsigned char rx_lost PACKED; /* 03: Rx frames lost */
+ unsigned char tx_abort PACKED; /* 04: Tx aborted frames */
+ unsigned char tx_underrun PACKED; /* 05: Tx underrun errors */
+ unsigned char tx_missed_intr PACKED; /* 06: Tx underruns missed */
+ unsigned char reserved PACKED; /* 07: Tx underruns missed */
+ unsigned char dcd_trans PACKED; /* 08: DCD transitions */
+ unsigned char cts_trans PACKED; /* 09: CTS transitions */
+} ppp_err_stats_t;
+
+/*----------------------------------------------------------------------------
+ * Packet Statistics (returned by the PPP_READ_PACKET_STATS command).
+ */
+typedef struct ppp_pkt_stats
+{
+ unsigned short rx_bad_header PACKED; /* 00: */
+ unsigned short rx_prot_unknwn PACKED; /* 02: */
+ unsigned short rx_too_large PACKED; /* 04: */
+ unsigned short rx_lcp PACKED; /* 06: */
+ unsigned short tx_lcp PACKED; /* 08: */
+ unsigned short rx_ipcp PACKED; /* 0A: */
+ unsigned short tx_ipcp PACKED; /* 0C: */
+ unsigned short rx_ipxcp PACKED; /* 0E: */
+ unsigned short tx_ipxcp PACKED; /* 10: */
+ unsigned short rx_pap PACKED; /* 12: */
+ unsigned short tx_pap PACKED; /* 14: */
+ unsigned short rx_chap PACKED; /* 16: */
+ unsigned short tx_chap PACKED; /* 18: */
+ unsigned short rx_lqr PACKED; /* 1A: */
+ unsigned short tx_lqr PACKED; /* 1C: */
+ unsigned short rx_ip PACKED; /* 1E: */
+ unsigned short tx_ip PACKED; /* 20: */
+ unsigned short rx_ipx PACKED; /* 22: */
+ unsigned short tx_ipx PACKED; /* 24: */
+} ppp_pkt_stats_t;
+
+/*----------------------------------------------------------------------------
+ * LCP Statistics (returned by the PPP_READ_LCP_STATS command).
+ */
+typedef struct ppp_lcp_stats
+{
+ unsigned short rx_unknown PACKED; /* 00: unknown LCP type */
+ unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */
+ unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */
+ unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */
+ unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */
+ unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */
+ unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */
+ unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */
+ unsigned short rx_proto_rej PACKED; /* 10: Protocol-Reject */
+ unsigned short rx_echo_rqst PACKED; /* 12: Echo-Request */
+ unsigned short rx_echo_reply PACKED; /* 14: Echo-Reply */
+ unsigned short rx_disc_rqst PACKED; /* 16: Discard-Request */
+ unsigned short tx_conf_rqst PACKED; /* 18: Configure-Request */
+ unsigned short tx_conf_ack PACKED; /* 1A: Configure-Ack */
+ unsigned short tx_conf_nak PACKED; /* 1C: Configure-Nak */
+ unsigned short tx_conf_rej PACKED; /* 1E: Configure-Reject */
+ unsigned short tx_term_rqst PACKED; /* 20: Terminate-Request */
+ unsigned short tx_term_ack PACKED; /* 22: Terminate-Ack */
+ unsigned short tx_code_rej PACKED; /* 24: Code-Reject */
+ unsigned short tx_proto_rej PACKED; /* 26: Protocol-Reject */
+ unsigned short tx_echo_rqst PACKED; /* 28: Echo-Request */
+ unsigned short tx_echo_reply PACKED; /* 2A: Echo-Reply */
+ unsigned short tx_disc_rqst PACKED; /* 2E: Discard-Request */
+ unsigned short rx_too_large PACKED; /* 30: packets too large */
+ unsigned short rx_ack_inval PACKED; /* 32: invalid Conf-Ack */
+ unsigned short rx_rej_inval PACKED; /* 34: invalid Conf-Reject */
+ unsigned short rx_rej_badid PACKED; /* 36: Conf-Reject w/bad ID */
+} ppp_lcp_stats_t;
+
+/*----------------------------------------------------------------------------
+ * Loopback Error Statistics (returned by the PPP_READ_LPBK_STATS command).
+ */
+typedef struct ppp_lpbk_stats
+{
+ unsigned short conf_magic PACKED; /* 00: */
+ unsigned short loc_echo_rqst PACKED; /* 02: */
+ unsigned short rem_echo_rqst PACKED; /* 04: */
+ unsigned short loc_echo_reply PACKED; /* 06: */
+ unsigned short rem_echo_reply PACKED; /* 08: */
+ unsigned short loc_disc_rqst PACKED; /* 0A: */
+ unsigned short rem_disc_rqst PACKED; /* 0C: */
+ unsigned short echo_tx_collsn PACKED; /* 0E: */
+ unsigned short echo_rx_collsn PACKED; /* 10: */
+} ppp_lpbk_stats_t;
+
+/*----------------------------------------------------------------------------
+ * Protocol Statistics (returned by the PPP_READ_IPCP_STATS and
+ * PPP_READ_IPXCP_STATS commands).
+ */
+typedef struct ppp_prot_stats
+{
+ unsigned short rx_unknown PACKED; /* 00: unknown type */
+ unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */
+ unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */
+ unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */
+ unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */
+ unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */
+ unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */
+ unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */
+ unsigned short reserved PACKED; /* 10: */
+ unsigned short tx_conf_rqst PACKED; /* 12: Configure-Request */
+ unsigned short tx_conf_ack PACKED; /* 14: Configure-Ack */
+ unsigned short tx_conf_nak PACKED; /* 16: Configure-Nak */
+ unsigned short tx_conf_rej PACKED; /* 18: Configure-Reject */
+ unsigned short tx_term_rqst PACKED; /* 1A: Terminate-Request */
+ unsigned short tx_term_ack PACKED; /* 1C: Terminate-Ack */
+ unsigned short tx_code_rej PACKED; /* 1E: Code-Reject */
+ unsigned short rx_too_large PACKED; /* 20: packets too large */
+ unsigned short rx_ack_inval PACKED; /* 22: invalid Conf-Ack */
+ unsigned short rx_rej_inval PACKED; /* 24: invalid Conf-Reject */
+ unsigned short rx_rej_badid PACKED; /* 26: Conf-Reject w/bad ID */
+} ppp_prot_stats_t;
+
+/*----------------------------------------------------------------------------
+ * PAP Statistics (returned by the PPP_READ_PAP_STATS command).
+ */
+typedef struct ppp_pap_stats
+{
+ unsigned short rx_unknown PACKED; /* 00: unknown type */
+ unsigned short rx_auth_rqst PACKED; /* 02: Authenticate-Request */
+ unsigned short rx_auth_ack PACKED; /* 04: Authenticate-Ack */
+ unsigned short rx_auth_nak PACKED; /* 06: Authenticate-Nak */
+ unsigned short reserved PACKED; /* 08: */
+ unsigned short tx_auth_rqst PACKED; /* 0A: Authenticate-Request */
+ unsigned short tx_auth_ack PACKED; /* 0C: Authenticate-Ack */
+ unsigned short tx_auth_nak PACKED; /* 0E: Authenticate-Nak */
+ unsigned short rx_too_large PACKED; /* 10: packets too large */
+ unsigned short rx_bad_peerid PACKED; /* 12: invalid peer ID */
+ unsigned short rx_bad_passwd PACKED; /* 14: invalid password */
+} ppp_pap_stats_t;
+
+/*----------------------------------------------------------------------------
+ * CHAP Statistics (returned by the PPP_READ_CHAP_STATS command).
+ */
+typedef struct ppp_chap_stats
+{
+ unsigned short rx_unknown PACKED; /* 00: unknown type */
+ unsigned short rx_challenge PACKED; /* 02: Authenticate-Request */
+ unsigned short rx_response PACKED; /* 04: Authenticate-Ack */
+ unsigned short rx_success PACKED; /* 06: Authenticate-Nak */
+ unsigned short rx_failure PACKED; /* 08: Authenticate-Nak */
+ unsigned short reserved PACKED; /* 0A: */
+ unsigned short tx_challenge PACKED; /* 0C: Authenticate-Request */
+ unsigned short tx_response PACKED; /* 0E: Authenticate-Ack */
+ unsigned short tx_success PACKED; /* 10: Authenticate-Nak */
+ unsigned short tx_failure PACKED; /* 12: Authenticate-Nak */
+ unsigned short rx_too_large PACKED; /* 14: packets too large */
+ unsigned short rx_bad_peerid PACKED; /* 16: invalid peer ID */
+ unsigned short rx_bad_passwd PACKED; /* 18: invalid password */
+ unsigned short rx_bad_md5 PACKED; /* 1A: invalid MD5 format */
+ unsigned short rx_bad_resp PACKED; /* 1C: invalid response */
+} ppp_chap_stats_t;
+
+/*----------------------------------------------------------------------------
+ * Connection Information (returned by the PPP_GET_CONNECTION_INFO command).
+ */
+typedef struct ppp_conn_info
+{
+ unsigned short remote_mru PACKED; /* 00: */
+ unsigned char ip_options PACKED; /* 02: */
+ unsigned char ip_local[4] PACKED; /* 03: */
+ unsigned char ip_remote[4] PACKED; /* 07: */
+ unsigned char ipx_options PACKED; /* 0B: */
+ unsigned char ipx_network[4] PACKED; /* 0C: */
+ unsigned char ipx_local[6] PACKED; /* 10: */
+ unsigned char ipx_remote[6] PACKED; /* 16: */
+ unsigned char ipx_router[48] PACKED; /* 1C: */
+ unsigned char auth_status PACKED; /* 4C: */
+ unsigned char peer_id[0] PACKED; /* 4D: */
+} ppp_conn_info_t;
+
+#ifdef _MSC_
+# pragma pack()
+#endif
+#endif /* _SDLA_PPP_H */
diff --git a/pfinet/linux-src/include/linux/sdla_x25.h b/pfinet/linux-src/include/linux/sdla_x25.h
new file mode 100644
index 00000000..58214a08
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sdla_x25.h
@@ -0,0 +1,625 @@
+/*****************************************************************************
+* sdla_x25.h Sangoma X.25 firmware API definitions.
+*
+* Author: Gene Kozin <74604.152@compuserve.com>
+*
+* Copyright: (c) 1995-1996 Sangoma Technologies Inc.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version
+* 2 of the License, or (at your option) any later version.
+* ============================================================================
+* Dec 13, 1996 Gene Kozin Initial version
+*****************************************************************************/
+#ifndef _SDLA_X25_H
+#define _SDLA_X25_H
+
+/*----------------------------------------------------------------------------
+ * Notes:
+ * ------
+ * 1. All structures defined in this file are byte-aligned. To ensure
+ * portability of this code between different platforms and compilers, one
+ * of the following defines must be defined before including this file:
+ *
+ * Compiler Platform Define Use option
+ * -------- -------- ------ ----------
+ * GNU C Linux _GNUC_ -
+ * Microsoft C DOS/Windows _MSC_ -
+ *
+ */
+
+#ifdef _GNUC_
+# ifndef PACKED
+# define PACKED __attribute__((packed))
+# endif /* PACKED */
+#else
+# define PACKED
+#endif
+#ifdef _MSC_
+# pragma pack(1)
+#endif
+
+/****** CONSTANTS DEFINITIONS ***********************************************/
+
+#define X25_MAX_CHAN 255 /* max number of open X.25 circuits */
+#define X25_MAX_DATA 1024 /* max length of X.25 data buffer */
+
+/*
+ * X.25 shared memory layout.
+ */
+#define X25_MBOX_OFFS 0x16B0 /* general mailbox block */
+#define X25_RXMBOX_OFFS 0x1AD0 /* receive mailbox */
+#define X25_STATUS_OFFS 0x1EF0 /* X.25 status structure */
+
+/****** DATA STRUCTURES *****************************************************/
+
+/*----------------------------------------------------------------------------
+ * X.25 Command Block.
+ */
+typedef struct X25Cmd
+{
+ unsigned char command PACKED; /* command code */
+ unsigned short length PACKED; /* transfer data length */
+ unsigned char result PACKED; /* return code */
+ unsigned char pf PACKED; /* P/F bit */
+ unsigned short lcn PACKED; /* logical channel */
+ unsigned char qdm PACKED; /* Q/D/M bits */
+ unsigned char cause PACKED; /* cause field */
+ unsigned char diagn PACKED; /* diagnostics */
+ unsigned char pktType PACKED; /* packet type */
+ unsigned char resrv[4] PACKED; /* reserved */
+} TX25Cmd;
+
+/*
+ * Defines for the 'command' field.
+ */
+/*----- General commands --------------*/
+#define X25_SET_GLOBAL_VARS 0x0B /* set global variables */
+#define X25_READ_MODEM_STATUS 0x0C /* read modem status */
+#define X25_READ_CODE_VERSION 0x15 /* read firmware version number */
+#define X25_TRACE_CONFIGURE 0x14 /* configure trace facility */
+#define X25_READ_TRACE_DATA 0x16 /* read trace data */
+#define X25_SET_INTERRUPT_MODE 0x17 /* set interrupt generation mode */
+#define X25_READ_INTERRUPT_MODE 0x18 /* read interrupt generation mode */
+/*----- HDLC-level commands -----------*/
+#define X25_HDLC_LINK_CONFIGURE 0x01 /* configure HDLC link level */
+#define X25_HDLC_LINK_OPEN 0x02 /* open HDLC link */
+#define X25_HDLC_LINK_CLOSE 0x03 /* close HDLC link */
+#define X25_HDLC_LINK_SETUP 0x04 /* set up HDLC link */
+#define X25_HDLC_LINK_DISC 0x05 /* disconnect DHLC link */
+#define X25_HDLC_LINK_STATUS 0x06 /* read DHLC link status */
+#define X25_HDLC_READ_STATS 0x07 /* read operational statistics */
+#define X25_HDLC_FLUSH_STATS 0x08 /* flush operational statistics */
+#define X25_HDLC_READ_COMM_ERR 0x09 /* read error statistics */
+#define X25_HDLC_FLUSH_COMM_ERR 0x0A /* flush error statistics */
+#define X25_HDLC_FLUSH_BUFFERS 0x0D /* flush HDLC-level data buffers */
+#define X25_HDLC_SPRVS_CNT_STAT 0x0F /* read surervisory count status */
+#define X25_HDLC_SEND_UI_FRAME 0x10 /* send unnumbered information frame */
+#define X25_HDLC_WRITE 0x11 /* send HDLC information frame */
+#define X25_HDLC_READ 0x21 /* read HDLC information frame */
+#define X25_HDLC_READ_CONFIG 0x12 /* read HDLC configuration */
+#define X25_HDLC_SET_CONFIG 0x13 /* set HDLC configuration */
+/*----- X.25-level commands -----------*/
+#define X25_READ 0x22 /* read X.25 packet */
+#define X25_WRITE 0x23 /* send X.25 packet */
+#define X25_PLACE_CALL 0x30 /* place a call on SVC */
+#define X25_ACCEPT_CALL 0x31 /* accept incoming call */
+#define X25_CLEAR_CALL 0x32 /* clear call */
+#define X25_CLEAR_CONFRM 0x33 /* send clear confirmation packet */
+#define X25_RESET 0x34 /* send reset request packet */
+#define X25_RESET_CONFRM 0x35 /* send reset confirmation packet */
+#define X25_RESTART 0x36 /* send restart request packet */
+#define X25_RESTART_CONFRM 0x37 /* send restart confirmation packet */
+#define X25_INTERRUPT 0x38 /* send interrupt request packet */
+#define X25_INTERRUPT_CONFRM 0x39 /* send interrupt confirmation pkt */
+#define X25_REGISTRATION_RQST 0x3A /* send registration request packet */
+#define X25_REGISTRATION_CONFRM 0x3B /* send registration confirmation */
+#define X25_IS_DATA_AVAILABLE 0x40 /* querry receive queue */
+#define X25_INCOMING_CALL_CTL 0x41 /* select incoming call options */
+#define X25_CONFIGURE_PVC 0x42 /* configure PVC */
+#define X25_GET_ACTIVE_CHANNELS 0x43 /* get a list of active circuits */
+#define X25_READ_CHANNEL_CONFIG 0x44 /* read virt. circuit configuration */
+#define X25_FLUSH_DATA_BUFFERS 0x45 /* flush X.25-level data buffers */
+#define X25_READ_HISTORY_TABLE 0x46 /* read asynchronous event log */
+#define X25_HISTORY_TABLE_CTL 0x47 /* control asynchronous event log */
+#define X25_GET_TX_D_BIT_STATUS 0x48 /* is packet with D-bit acknowledged */
+#define X25_READ_STATISTICS 0x49 /* read X.25-level statistics */
+#define X25_FLUSH_STATISTICS 0x4A /* flush X.25-level statistics */
+#define X25_READ_CONFIGURATION 0x50 /* read HDLC & X.25 configuration */
+#define X25_SET_CONFIGURATION 0x51 /* set HDLC & X.25 configuration */
+
+/*
+ * Defines for the 'result' field.
+ */
+/*----- General results ---------------*/
+#define X25RES_OK 0x00
+#define X25RES_ERROR 0x01
+#define X25RES_LINK_NOT_IN_ABM 0x02 /* link is not in ABM mode */
+#define X25RES_LINK_CLOSED 0x03
+#define X25RES_INVAL_LENGTH 0x04
+#define X25RES_INVAL_CMD 0x05
+#define X25RES_UNNUMBERED_FRAME 0x06 /* unnumbered frame received */
+#define X25RES_FRM_REJECT_MODE 0x07 /* link is in Frame Reject mode */
+#define X25RES_MODEM_FAILURE 0x08 /* DCD and/or CTS dropped */
+#define X25RES_N2_RETRY_LIMIT 0x09 /* N2 retry limit has been exceeded */
+#define X25RES_INVAL_LCN 0x30 /* invalid logical channel number */
+#define X25RES_INVAL_STATE 0x31 /* channel is not in data xfer mode */
+#define X25RES_INVAL_DATA_LEN 0x32 /* invalid data length */
+#define X25RES_NOT_READY 0x33 /* no data available / buffers full */
+#define X25RES_NETWORK_DOWN 0x34
+#define X25RES_CHANNEL_IN_USE 0x35 /* there is data queued on this LCN */
+#define X25RES_REGST_NOT_SUPPRT 0x36 /* registration not supported */
+#define X25RES_INVAL_FORMAT 0x37 /* invalid packet format */
+#define X25RES_D_BIT_NOT_SUPPRT 0x38 /* D-bit pragmatics not supported */
+#define X25RES_FACIL_NOT_SUPPRT 0x39 /* Call facility not supported */
+#define X25RES_INVAL_CALL_ARG 0x3A /* erroneous call arguments */
+#define X25RES_INVAL_CALL_DATA 0x3B /* erroneous call user data */
+#define X25RES_ASYNC_PACKET 0x40 /* asynchronous packet received */
+#define X25RES_PROTO_VIOLATION 0x41 /* protocol violation occurred */
+#define X25RES_PKT_TIMEOUT 0x42 /* X.25 packet time out */
+#define X25RES_PKT_RETRY_LIMIT 0x43 /* X.25 packet retry limit exceeded */
+/*----- Command-dependent results -----*/
+#define X25RES_LINK_DISC 0x00 /* HDLC_LINK_STATUS */
+#define X25RES_LINK_IN_ABM 0x01 /* HDLC_LINK_STATUS */
+#define X25RES_NO_DATA 0x01 /* HDLC_READ/READ_TRACE_DATA*/
+#define X25RES_TRACE_INACTIVE 0x02 /* READ_TRACE_DATA */
+#define X25RES_LINK_IS_OPEN 0x01 /* HDLC_LINK_OPEN */
+#define X25RES_LINK_IS_DISC 0x02 /* HDLC_LINK_DISC */
+#define X25RES_LINK_IS_CLOSED 0x03 /* HDLC_LINK_CLOSE */
+#define X25RES_INVAL_PARAM 0x31 /* INCOMING_CALL_CTL */
+#define X25RES_INVAL_CONFIG 0x35 /* REGISTR_RQST/CONFRM */
+
+/*
+ * Defines for the 'qdm_bits' field.
+ */
+#define X25CMD_Q_BIT_MASK 0x04
+#define X25CMD_D_BIT_MASK 0x02
+#define X25CMD_M_BIT_MASK 0x01
+
+/*
+ * Defines for the 'pkt_type' field.
+ */
+/*----- Asynchronous events ------*/
+#define ASE_CLEAR_RQST 0x02
+#define ASE_RESET_RQST 0x04
+#define ASE_RESTART_RQST 0x08
+#define ASE_INTERRUPT 0x10
+#define ASE_DTE_REGISTR_RQST 0x20
+#define ASE_CALL_RQST 0x30
+#define ASE_CALL_ACCEPTED 0x31
+#define ASE_CLEAR_CONFRM 0x32
+#define ASE_RESET_CONFRM 0x33
+#define ASE_RESTART_CONFRM 0x34
+#define ASE_INTERRUPT_CONFRM 0x35
+#define ASE_DCE_REGISTR_CONFRM 0x36
+#define ASE_DIAGNOSTIC 0x37
+#define ASE_CALL_AUTO_CLEAR 0x38
+#define AUTO_RESPONSE_FLAG 0x80
+/*----- Time-Out events ----------*/
+#define TOE_RESTART_RQST 0x03
+#define TOE_CALL_RQST 0x05
+#define TOE_CLEAR_RQST 0x08
+#define TOE_RESET_RQST 0x0A
+/*----- Protocol Violation events */
+#define PVE_CLEAR_RQST 0x32
+#define PVE_RESET_RQST 0x33
+#define PVE_RESTART_RQST 0x34
+#define PVE_DIAGNOSTIC 0x37
+
+/*----------------------------------------------------------------------------
+ * X.25 Mailbox.
+ * This structure is located at offsets X25_MBOX_OFFS and X25_RXMBOX_OFFS
+ * into shared memory window.
+ */
+typedef struct X25Mbox
+{
+ unsigned char opflag PACKED; /* 00h: execution flag */
+ TX25Cmd cmd PACKED; /* 01h: command block */
+ unsigned char data[1] PACKED; /* 10h: data buffer */
+} TX25Mbox;
+
+/*----------------------------------------------------------------------------
+ * X.25 Time Stamp Structure.
+ */
+typedef struct X25TimeStamp
+{
+ unsigned char month PACKED;
+ unsigned char date PACKED;
+ unsigned char sec PACKED;
+ unsigned char min PACKED;
+ unsigned char hour PACKED;
+} TX25TimeStamp;
+
+/*----------------------------------------------------------------------------
+ * X.25 Status Block.
+ * This structure is located at offset X25_STATUS_OFF into shared memory
+ * window.
+ */
+typedef struct X25Status
+{
+ unsigned short pvc_map PACKED; /* 00h: PVC map */
+ unsigned short icc_map PACKED; /* 02h: Incoming Chan. map */
+ unsigned short twc_map PACKED; /* 04h: Two-way Cnan. map */
+ unsigned short ogc_map PACKED; /* 06h: Outgoing Chan. map */
+ TX25TimeStamp tstamp PACKED; /* 08h: timestamp (BCD) */
+ unsigned char iflags PACKED; /* 0Dh: interrupt flags */
+ unsigned char imask PACKED; /* 0Eh: interrupt mask */
+ unsigned char resrv PACKED; /* 0Eh: */
+ unsigned char gflags PACKED; /* 10h: misc. HDLC/X25 flags */
+ unsigned char cflags[X25_MAX_CHAN] PACKED; /* channel status bytes */
+} TX25Status;
+
+/*
+ * Bitmasks for the 'iflags' field.
+ */
+#define X25_RX_INTR 0x01 /* receive interrupt */
+#define X25_TX_INTR 0x02 /* transmit interrupt */
+#define X25_MODEM_INTR 0x04 /* modem status interrupt (CTS/DCD) */
+#define X25_EVENT_INTR 0x10 /* asynchronous event encountered */
+#define X25_CMD_INTR 0x08 /* interface command complete */
+
+/*
+ * Bitmasks for the 'gflags' field.
+ */
+#define X25_HDLC_ABM 0x01 /* HDLC is in ABM mode */
+#define X25_RX_READY 0x02 /* X.25 data available */
+#define X25_TRACE_READY 0x08 /* trace data available */
+#define X25_EVENT_IND 0x20 /* asynchronous event indicator */
+#define X25_TX_READY 0x40 /* space is available in Tx buf.*/
+
+/*
+ * Bitmasks for the 'cflags' field.
+ */
+#define X25_XFER_MODE 0x80 /* channel is in data transfer mode */
+#define X25_TXWIN_OPEN 0x40 /* transmit window open */
+#define X25_RXBUF_MASK 0x3F /* number of data buffers available */
+
+/*****************************************************************************
+ * Following definitions structurize contents of the TX25Mbox.data field for
+ * different X.25 interface commands.
+ ****************************************************************************/
+
+/* ---------------------------------------------------------------------------
+ * X25_SET_GLOBAL_VARS Command.
+ */
+typedef struct X25GlobalVars
+{
+ unsigned char resrv PACKED; /* 00h: reserved */
+ unsigned char dtrCtl PACKED; /* 01h: DTR control code */
+ unsigned char resErr PACKED; /* 01h: '1' - reset modem error */
+} TX25GlobalVars;
+
+/*
+ * Defines for the 'dtrCtl' field.
+ */
+#define X25_RAISE_DTR 0x01
+#define X25_DROP_DTR 0x02
+
+/* ---------------------------------------------------------------------------
+ * X25_READ_MODEM_STATUS Command.
+ */
+typedef struct X25ModemStatus
+{
+ unsigned char status PACKED; /* 00h: modem status */
+} TX25ModemStatus;
+
+/*
+ * Defines for the 'status' field.
+ */
+#define X25_CTS_MASK 0x20
+#define X25_DCD_MASK 0x08
+
+/* ---------------------------------------------------------------------------
+ * X25_HDLC_LINK_STATUS Command.
+ */
+typedef struct X25LinkStatus
+{
+ unsigned char txQueued PACKED; /* 00h: queued Tx I-frames*/
+ unsigned char rxQueued PACKED; /* 01h: queued Rx I-frames*/
+ unsigned char station PACKED; /* 02h: DTE/DCE config. */
+ unsigned char reserved PACKED; /* 03h: reserved */
+ unsigned char sfTally PACKED; /* 04h: supervisory frame tally */
+} TX25LinkStatus;
+
+/*
+ * Defines for the 'station' field.
+ */
+#define X25_STATION_DTE 0x01 /* station configured as DTE */
+#define X25_STATION_DCE 0x02 /* station configured as DCE */
+
+/* ---------------------------------------------------------------------------
+ * X25_HDLC_READ_STATS Command.
+ */
+typedef struct HdlcStats
+{ /* a number of ... */
+ unsigned short rxIFrames PACKED; /* 00h: ready Rx I-frames */
+ unsigned short rxNoseq PACKED; /* 02h: frms out-of-sequence */
+ unsigned short rxNodata PACKED; /* 04h: I-frms without data */
+ unsigned short rxDiscarded PACKED; /* 06h: discarded frames */
+ unsigned short rxTooLong PACKED; /* 08h: frames too long */
+ unsigned short rxBadAddr PACKED; /* 0Ah: frms with inval.addr*/
+ unsigned short txAcked PACKED; /* 0Ch: acknowledged I-frms */
+ unsigned short txRetransm PACKED; /* 0Eh: re-transmit. I-frms */
+ unsigned short t1Timeout PACKED; /* 10h: T1 timeouts */
+ unsigned short rxSABM PACKED; /* 12h: received SABM frames */
+ unsigned short rxDISC PACKED; /* 14h: received DISC frames */
+ unsigned short rxDM PACKED; /* 16h: received DM frames */
+ unsigned short rxFRMR PACKED; /* 18h: FRMR frames received */
+ unsigned short txSABM PACKED; /* 1Ah: transm. SABM frames*/
+ unsigned short txDISC PACKED; /* 1Ch: transm. DISC frames*/
+ unsigned short txDM PACKED; /* 1Eh: transm. DM frames */
+ unsigned short txFRMR PACKED; /* 20h: transm. FRMR frames*/
+} THdlcStats;
+
+/* ---------------------------------------------------------------------------
+ * X25_HDLC_READ_COMM_ERR Command.
+ */
+typedef struct HdlcCommErr
+{ /* a number of ... */
+ unsigned char rxOverrun PACKED; /* 00h: Rx overrun errors */
+ unsigned char rxBadCrc PACKED; /* 01h: Rx CRC errors */
+ unsigned char rxAborted PACKED; /* 02h: Rx aborted frames */
+ unsigned char rxDropped PACKED; /* 03h: frames lost */
+ unsigned char txAborted PACKED; /* 04h: Tx aborted frames */
+ unsigned char txUnderrun PACKED; /* 05h: Tx underrun errors */
+ unsigned char txMissIntr PACKED; /* 06h: missed underrun ints */
+ unsigned char reserved PACKED; /* 07h: reserved */
+ unsigned char droppedDCD PACKED; /* 08h: times DCD dropped */
+ unsigned char droppedCTS PACKED; /* 09h: times CTS dropped */
+} THdlcCommErr;
+
+/* ---------------------------------------------------------------------------
+ * X25_SET_CONFIGURATION & X25_READ_CONFIGURATION Commands.
+ */
+typedef struct X25Config
+{
+ unsigned char baudRate PACKED; /* 00h: */
+ unsigned char t1 PACKED; /* 01h: */
+ unsigned char t2 PACKED; /* 02h: */
+ unsigned char n2 PACKED; /* 03h: */
+ unsigned short hdlcMTU PACKED; /* 04h: */
+ unsigned char hdlcWindow PACKED; /* 06h: */
+ unsigned char t4 PACKED; /* 07h: */
+ unsigned char autoModem PACKED; /* 08h: */
+ unsigned char autoHdlc PACKED; /* 09h: */
+ unsigned char hdlcOptions PACKED; /* 0Ah: */
+ unsigned char station PACKED; /* 0Bh: */
+ unsigned char pktWindow PACKED; /* 0Ch: */
+ unsigned short defPktSize PACKED; /* 0Dh: */
+ unsigned short pktMTU PACKED; /* 0Fh: */
+ unsigned short loPVC PACKED; /* 11h: */
+ unsigned short hiPVC PACKED; /* 13h: */
+ unsigned short loIncomingSVC PACKED; /* 15h: */
+ unsigned short hiIncomingSVC PACKED; /* 17h: */
+ unsigned short loTwoWaySVC PACKED; /* 19h: */
+ unsigned short hiTwoWaySVC PACKED; /* 1Bh: */
+ unsigned short loOutgoingSVC PACKED; /* 1Dh: */
+ unsigned short hiOutgoingSVC PACKED; /* 1Fh: */
+ unsigned short options PACKED; /* 21h: */
+ unsigned char responseOpt PACKED; /* 23h: */
+ unsigned short facil1 PACKED; /* 24h: */
+ unsigned short facil2 PACKED; /* 26h: */
+ unsigned short ccittFacil PACKED; /* 28h: */
+ unsigned short otherFacil PACKED; /* 2Ah: */
+ unsigned short ccittCompat PACKED; /* 2Ch: */
+ unsigned char t10t20 PACKED; /* 2Eh: */
+ unsigned char t11t21 PACKED; /* 2Fh: */
+ unsigned char t12t22 PACKED; /* 30h: */
+ unsigned char t13t23 PACKED; /* 31h: */
+ unsigned char t16t26 PACKED; /* 32H: */
+ unsigned char t28 PACKED; /* 33h: */
+ unsigned char r10r20 PACKED; /* 34h: */
+ unsigned char r12r22 PACKED; /* 35h: */
+ unsigned char r13r23 PACKED; /* 36h: */
+} TX25Config;
+
+/* ---------------------------------------------------------------------------
+ * X25_READ_CHANNEL_CONFIG Command.
+ */
+typedef struct X25ChanAlloc /*----- Channel allocation -*/
+{
+ unsigned short loPVC PACKED; /* 00h: lowest PVC number */
+ unsigned short hiPVC PACKED; /* 02h: highest PVC number */
+ unsigned short loIncomingSVC PACKED; /* 04h: lowest incoming SVC */
+ unsigned short hiIncomingSVC PACKED; /* 06h: highest incoming SVC */
+ unsigned short loTwoWaySVC PACKED; /* 08h: lowest two-way SVC */
+ unsigned short hiTwoWaySVC PACKED; /* 0Ah: highest two-way SVC */
+ unsigned short loOutgoingSVC PACKED; /* 0Ch: lowest outgoing SVC */
+ unsigned short hiOutgoingSVC PACKED; /* 0Eh: highest outgoing SVC */
+} TX25ChanAlloc;
+
+typedef struct X25ChanCfg /*------ Channel configuration -----*/
+{
+ unsigned char type PACKED; /* 00h: channel type */
+ unsigned char txConf PACKED; /* 01h: Tx packet and window sizes */
+ unsigned char rxConf PACKED; /* 01h: Rx packet and window sizes */
+} TX25ChanCfg;
+
+/*
+ * Defines for the 'type' field.
+ */
+#define X25_PVC 0x01 /* PVC */
+#define X25_SVC_IN 0x03 /* Incoming SVC */
+#define X25_SVC_TWOWAY 0x07 /* Two-way SVC */
+#define X25_SVC_OUT 0x0B /* Outgoing SVC */
+
+/*----------------------------------------------------------------------------
+ * X25_READ_STATISTICS Command.
+ */
+typedef struct X25Stats
+{ /* number of packets Tx/Rx'ed */
+ unsigned short txRestartRqst PACKED; /* 00h: Restart Request */
+ unsigned short rxRestartRqst PACKED; /* 02h: Restart Request */
+ unsigned short txRestartConf PACKED; /* 04h: Restart Confirmation */
+ unsigned short rxRestartConf PACKED; /* 06h: Restart Confirmation */
+ unsigned short txResetRqst PACKED; /* 08h: Reset Request */
+ unsigned short rxResetRqst PACKED; /* 0Ah: Reset Request */
+ unsigned short txResetConf PACKED; /* 0Ch: Reset Confirmation */
+ unsigned short rxResetConf PACKED; /* 0Eh: Reset Confirmation */
+ unsigned short txCallRequest PACKED; /* 10h: Call Request */
+ unsigned short rxCallRequest PACKED; /* 12h: Call Request */
+ unsigned short txCallAccept PACKED; /* 14h: Call Accept */
+ unsigned short rxCallAccept PACKED; /* 16h: Call Accept */
+ unsigned short txClearRqst PACKED; /* 18h: Clear Request */
+ unsigned short rxClearRqst PACKED; /* 1Ah: Clear Request */
+ unsigned short txClearConf PACKED; /* 1Ch: Clear Confirmation */
+ unsigned short rxClearConf PACKED; /* 1Eh: Clear Confirmation */
+ unsigned short txDiagnostic PACKED; /* 20h: Diagnostic */
+ unsigned short rxDiagnostic PACKED; /* 22h: Diagnostic */
+ unsigned short txRegRqst PACKED; /* 24h: Registration Request */
+ unsigned short rxRegRqst PACKED; /* 26h: Registration Request */
+ unsigned short txRegConf PACKED; /* 28h: Registration Confirm.*/
+ unsigned short rxRegConf PACKED; /* 2Ah: Registration Confirm.*/
+ unsigned short txInterrupt PACKED; /* 2Ch: Interrupt */
+ unsigned short rxInterrupt PACKED; /* 2Eh: Interrupt */
+ unsigned short txIntrConf PACKED; /* 30h: Interrupt Confirm. */
+ unsigned short rxIntrConf PACKED; /* 32h: Interrupt Confirm. */
+ unsigned short txData PACKED; /* 34h: Data */
+ unsigned short rxData PACKED; /* 36h: Data */
+ unsigned short txRR PACKED; /* 38h: RR */
+ unsigned short rxRR PACKED; /* 3Ah: RR */
+ unsigned short txRNR PACKED; /* 3Ch: RNR */
+ unsigned short rxRNR PACKED; /* 3Eh: RNR */
+} TX25Stats;
+
+/*----------------------------------------------------------------------------
+ * X25_READ_HISTORY_TABLE Command.
+ */
+typedef struct X25EventLog
+{
+ unsigned char type PACKED; /* 00h: transaction type */
+ unsigned short lcn PACKED; /* 01h: logical channel num */
+ unsigned char packet PACKED; /* 03h: async packet type */
+ unsigned char cause PACKED; /* 04h: X.25 cause field */
+ unsigned char diag PACKED; /* 05h: X.25 diag field */
+ TX25TimeStamp ts PACKED; /* 06h: time stamp */
+} TX25EventLog;
+
+/*
+ * Defines for the 'type' field.
+ */
+#define X25LOG_INCOMING 0x00
+#define X25LOG_APPLICATION 0x01
+#define X25LOG_AUTOMATIC 0x02
+#define X25LOG_ERROR 0x04
+#define X25LOG_TIMEOUT 0x08
+#define X25LOG_RECOVERY 0x10
+
+/*
+ * Defines for the 'packet' field.
+ */
+#define X25LOG_CALL_RQST 0x0B
+#define X25LOG_CALL_ACCEPTED 0x0F
+#define X25LOG_CLEAR_RQST 0x13
+#define X25LOG_CLEAR_CONFRM 0x17
+#define X25LOG_RESET_RQST 0x1B
+#define X25LOG_RESET_CONFRM 0x1F
+#define X25LOG_RESTART_RQST 0xFB
+#define X25LOG_RESTART_COMFRM 0xFF
+#define X25LOG_DIAGNOSTIC 0xF1
+#define X25LOG_DTE_REG_RQST 0xF3
+#define X25LOG_DTE_REG_COMFRM 0xF7
+
+/* ---------------------------------------------------------------------------
+ * X25_TRACE_CONFIGURE Command.
+ */
+typedef struct X25TraceCfg
+{
+ unsigned char flags PACKED; /* 00h: trace configuration flags */
+ unsigned char timeout PACKED; /* 01h: timeout for trace delay mode*/
+} TX25TraceCfg;
+
+/*
+ * Defines for the 'flags' field.
+ */
+#define X25_TRC_ENABLE 0x01 /* bit0: '1' - trace enabled */
+#define X25_TRC_TIMESTAMP 0x02 /* bit1: '1' - time stamping enabled*/
+#define X25_TRC_DELAY 0x04 /* bit2: '1' - trace delay enabled */
+#define X25_TRC_DATA 0x08 /* bit3: '1' - trace data packets */
+#define X25_TRC_SUPERVISORY 0x10 /* bit4: '1' - trace suprvisory pkts*/
+#define X25_TRC_ASYNCHRONOUS 0x20 /* bit5: '1' - trace asynch. packets*/
+#define X25_TRC_HDLC 0x40 /* bit6: '1' - trace all packets */
+#define X25_TRC_READ 0x80 /* bit7: '1' - get current config. */
+
+/* ---------------------------------------------------------------------------
+ * X25_READ_TRACE_DATA Command.
+ */
+typedef struct X25Trace /*----- Trace data structure -------*/
+{
+ unsigned short length PACKED; /* 00h: trace data length */
+ unsigned char type PACKED; /* 02h: trace type */
+ unsigned char lost_cnt PACKED; /* 03h: N of traces lost */
+ TX25TimeStamp tstamp PACKED; /* 04h: mon/date/sec/min/hour */
+ unsigned short millisec PACKED; /* 09h: ms time stamp */
+ unsigned char data[0] PACKED; /* 0Bh: traced frame */
+} TX25Trace;
+
+/*
+ * Defines for the 'type' field.
+ */
+#define X25_TRC_TYPE_MASK 0x0F /* bits 0..3: trace type */
+#define X25_TRC_TYPE_RX_FRAME 0x00 /* received frame trace */
+#define X25_TRC_TYPE_TX_FRAME 0x01 /* transmitted frame */
+#define X25_TRC_TYPE_ERR_FRAME 0x02 /* error frame */
+
+#define X25_TRC_ERROR_MASK 0xF0 /* bits 4..7: error code */
+#define X25_TRCERR_RX_ABORT 0x10 /* receive abort error */
+#define X25_TRCERR_RX_BADCRC 0x20 /* receive CRC error */
+#define X25_TRCERR_RX_OVERRUN 0x30 /* receiver overrun error */
+#define X25_TRCERR_RX_TOO_LONG 0x40 /* excessive frame length error */
+#define X25_TRCERR_TX_ABORT 0x70 /* aborted frame transmission error */
+#define X25_TRCERR_TX_UNDERRUN 0x80 /* transmit underrun error */
+
+/*****************************************************************************
+ * Following definitions describe HDLC frame and X.25 packet formats.
+ ****************************************************************************/
+
+typedef struct HDLCFrame /*----- DHLC Frame Format ----------*/
+{
+ unsigned char addr PACKED; /* address field */
+ unsigned char cntl PACKED; /* control field */
+ unsigned char data[0] PACKED;
+} THDLCFrame;
+
+typedef struct X25Pkt /*----- X.25 Packet Format ----------*/
+{
+ unsigned char lcn_hi PACKED; /* 4 MSB of Logical Channel Number */
+ unsigned char lcn_lo PACKED; /* 8 LSB of Logical Channel Number */
+ unsigned char type PACKED;
+ unsigned char data[0] PACKED;
+} TX25Pkt;
+
+/*
+ * Defines for the 'lcn_hi' field.
+ */
+#define X25_Q_BIT_MASK 0x80 /* Data Qualifier Bit mask */
+#define X25_D_BIT_MASK 0x40 /* Delivery Confirmation Bit mask */
+#define X25_M_BITS_MASK 0x30 /* Modulo Bits mask */
+#define X25_LCN_MSB_MASK 0x0F /* LCN most significant bits mask */
+
+/*
+ * Defines for the 'type' field.
+ */
+#define X25PKT_DATA 0x01 /* Data packet mask */
+#define X25PKT_SUPERVISORY 0x02 /* Supervisory packet mask */
+#define X25PKT_CALL_RQST 0x0B /* Call Request/Incoming */
+#define X25PKT_CALL_ACCEPTED 0x0F /* Call Accepted/Connected */
+#define X25PKT_CLEAR_RQST 0x13 /* Clear Request/Indication */
+#define X25PKT_CLEAR_CONFRM 0x17 /* Clear Confirmation */
+#define X25PKT_RESET_RQST 0x1B /* Reset Request/Indication */
+#define X25PKT_RESET_CONFRM 0x1F /* Reset Confirmation */
+#define X25PKT_RESTART_RQST 0xFB /* Restart Request/Indication */
+#define X25PKT_RESTART_CONFRM 0xFF /* Restart Confirmation */
+#define X25PKT_INTERRUPT 0x23 /* Interrupt */
+#define X25PKT_INTERRUPT_CONFRM 0x27 /* Interrupt Confirmation */
+#define X25PKT_DIAGNOSTIC 0xF1 /* Diagnostic */
+#define X25PKT_REGISTR_RQST 0xF3 /* Registration Request */
+#define X25PKT_REGISTR_CONFRM 0xF7 /* Registration Confirmation */
+#define X25PKT_RR_MASKED 0x01 /* Receive Ready packet after masking */
+#define X25PKT_RNR_MASKED 0x05 /* Receive Not Ready after masking */
+
+#ifdef _MSC_
+# pragma pack()
+#endif
+#endif /* _SDLA_X25_H */
diff --git a/pfinet/linux-src/include/linux/sdladrv.h b/pfinet/linux-src/include/linux/sdladrv.h
new file mode 100644
index 00000000..23ae8a1e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sdladrv.h
@@ -0,0 +1,61 @@
+/*****************************************************************************
+* sdladrv.h SDLA Support Module. Kernel API Definitions.
+*
+* Author: Gene Kozin <genek@compuserve.com>
+*
+* Copyright: (c) 1995-1996 Sangoma Technologies Inc.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version
+* 2 of the License, or (at your option) any later version.
+* ============================================================================
+* Dec 11, 1996 Gene Kozin Complete overhaul.
+* Oct 17, 1996 Gene Kozin Minor bug fixes.
+* Jun 12, 1996 Gene Kozin Added support for S503 card.
+* Dec 06, 1995 Gene Kozin Initial version.
+*****************************************************************************/
+#ifndef _SDLADRV_H
+#define _SDLADRV_H
+
+#define SDLA_MAXIORANGE 4 /* maximum I/O port range */
+#define SDLA_WINDOWSIZE 0x2000 /* default dual-port memory window size */
+
+/****** Data Structures *****************************************************/
+
+/*----------------------------------------------------------------------------
+ * Adapter hardware configuration. Pointer to this structure is passed to all
+ * APIs.
+ */
+typedef struct sdlahw
+{
+ unsigned type; /* adapter type */
+ unsigned fwid; /* firmware ID */
+ unsigned port; /* adapter I/O port base */
+ int irq; /* interrupt request level */
+ void * dpmbase; /* dual-port memory base */
+ unsigned dpmsize; /* dual-port memory size */
+ unsigned pclk; /* CPU clock rate, kHz */
+ unsigned long memory; /* memory size */
+ unsigned long vector; /* local offset of the DPM window */
+ unsigned io_range; /* I/O port range */
+ unsigned char regs[SDLA_MAXIORANGE]; /* was written to registers */
+ unsigned reserved[5];
+} sdlahw_t;
+
+/****** Function Prototypes *************************************************/
+
+extern int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len);
+extern int sdla_down (sdlahw_t* hw);
+extern int sdla_inten (sdlahw_t* hw);
+extern int sdla_intde (sdlahw_t* hw);
+extern int sdla_intack (sdlahw_t* hw);
+extern int sdla_intr (sdlahw_t* hw);
+extern int sdla_mapmem (sdlahw_t* hw, unsigned long addr);
+extern int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf,
+ unsigned len);
+extern int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf,
+ unsigned len);
+extern int sdla_exec (void* opflag);
+
+#endif /* _SDLADRV_H */
diff --git a/pfinet/linux-src/include/linux/sdlasfm.h b/pfinet/linux-src/include/linux/sdlasfm.h
new file mode 100644
index 00000000..65e7f30a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sdlasfm.h
@@ -0,0 +1,92 @@
+/*****************************************************************************
+* sdlasfm.h WANPIPE(tm) Multiprotocol WAN Link Driver.
+* Definitions for the SDLA Firmware Module (SFM).
+*
+* Author: Gene Kozin <74604.152@compuserve.com>
+*
+* Copyright: (c) 1995-1996 Sangoma Technologies Inc.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version
+* 2 of the License, or (at your option) any later version.
+* ============================================================================
+* Dec 11, 1996 Gene Kozin Cosmetic changes
+* Apr 16, 1996 Gene Kozin Changed adapter & firmware IDs. Version 2
+* Dec 15, 1995 Gene Kozin Structures chaned
+* Nov 09, 1995 Gene Kozin Initial version.
+*****************************************************************************/
+#ifndef _SDLASFM_H
+#define _SDLASFM_H
+
+/****** Defines *************************************************************/
+
+#define SFM_VERSION 2
+#define SFM_SIGNATURE "SFM - Sangoma SDLA Firmware Module"
+
+/* min/max */
+#define SFM_IMAGE_SIZE 0x8000 /* max size of SDLA code image file */
+#define SFM_DESCR_LEN 256 /* max length of description string */
+#define SFM_MAX_SDLA 16 /* max number of compatible adapters */
+
+/* Adapter types */
+#define SDLA_S502A 5020
+#define SDLA_S502E 5021
+#define SDLA_S503 5030
+#define SDLA_S508 5080
+#define SDLA_S507 5070
+#define SDLA_S509 5090
+
+/* Firmware identification numbers:
+ * 0 .. 999 Test & Diagnostics
+ * 1000 .. 1999 Streaming HDLC
+ * 2000 .. 2999 Bisync
+ * 3000 .. 3999 SDLC
+ * 4000 .. 4999 HDLC
+ * 5000 .. 5999 X.25
+ * 6000 .. 6999 Frame Relay
+ * 7000 .. 7999 PPP
+ */
+#define SFID_CALIB502 200
+#define SFID_STRM502 1200
+#define SFID_STRM508 1800
+#define SFID_BSC502 2200
+#define SFID_SDLC502 3200
+#define SFID_HDLC502 4200
+#define SFID_X25_502 5200
+#define SFID_X25_508 5800
+#define SFID_FR502 6200
+#define SFID_FR508 6800
+#define SFID_PPP502 7200
+#define SFID_PPP508 7800
+
+/****** Data Types **********************************************************/
+
+typedef struct sfm_info /* firmware module information */
+{
+ unsigned short codeid; /* firmware ID */
+ unsigned short version; /* firmaware version number */
+ unsigned short adapter[SFM_MAX_SDLA]; /* compatible adapter types */
+ unsigned long memsize; /* minimum memory size */
+ unsigned short reserved[2]; /* reserved */
+ unsigned short startoffs; /* entry point offset */
+ unsigned short winoffs; /* dual-port memory window offset */
+ unsigned short codeoffs; /* code load offset */
+ unsigned short codesize; /* code size */
+ unsigned short dataoffs; /* configuration data load offset */
+ unsigned short datasize; /* configuration data size */
+} sfm_info_t;
+
+typedef struct sfm /* SDLA firmware file structire */
+{
+ char signature[80]; /* SFM file signature */
+ unsigned short version; /* file format version */
+ unsigned short checksum; /* info + image */
+ unsigned short reserved[6]; /* reserved */
+ char descr[SFM_DESCR_LEN]; /* description string */
+ sfm_info_t info; /* firmware module info */
+ unsigned char image[1]; /* code image (variable size) */
+} sfm_t;
+
+#endif /* _SDLASFM_H */
+
diff --git a/pfinet/linux-src/include/linux/securebits.h b/pfinet/linux-src/include/linux/securebits.h
new file mode 100644
index 00000000..1e10badc
--- /dev/null
+++ b/pfinet/linux-src/include/linux/securebits.h
@@ -0,0 +1,30 @@
+#ifndef _LINUX_SECUREBITS_H
+#define _LINUX_SECUREBITS_H 1
+
+#define SECUREBITS_DEFAULT 0x00000000
+
+extern unsigned securebits;
+
+/* When set UID 0 has no special privileges. When unset, we support
+ inheritance of root-permissions and suid-root executablew under
+ compatibility mode. We raise the effective and inheritable bitmasks
+ *of the executable file* if the effective uid of the new process is
+ 0. If the real uid is 0, we raise the inheritable bitmask of the
+ executable file. */
+#define SECURE_NOROOT 0
+
+/* When set, setuid to/from uid 0 does not trigger capability-"fixes"
+ to be compatible with old programs relying on set*uid to loose
+ privileges. When unset, setuid doesn't change privileges. */
+#define SECURE_NO_SETUID_FIXUP 2
+
+/* Each securesetting is implemented using two bits. One bit specify
+ whether the setting is on or off. The other bit specify whether the
+ setting is fixed or not. A setting which is fixed cannot be changed
+ from user-level. */
+
+#define issecure(X) ( (1 << (X+1)) & SECUREBITS_DEFAULT ? \
+ (1 << (X)) & SECUREBITS_DEFAULT : \
+ (1 << (X)) & securebits )
+
+#endif /* !_LINUX_SECUREBITS_H */
diff --git a/pfinet/linux-src/include/linux/selection.h b/pfinet/linux-src/include/linux/selection.h
new file mode 100644
index 00000000..74d1b24d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/selection.h
@@ -0,0 +1,44 @@
+/*
+ * selection.h
+ *
+ * Interface between console.c, tty_io.c, vt.c, vc_screen.c and selection.c
+ */
+
+#ifndef _LINUX_SELECTION_H_
+#define _LINUX_SELECTION_H_
+
+#include <linux/vt_buffer.h>
+
+extern int sel_cons;
+
+extern void clear_selection(void);
+extern int set_selection(const unsigned long arg, struct tty_struct *tty, int user);
+extern int paste_selection(struct tty_struct *tty);
+extern int sel_loadlut(const unsigned long arg);
+extern int mouse_reporting(void);
+extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry);
+
+#define video_num_columns (vc_cons[currcons].d->vc_cols)
+#define video_num_lines (vc_cons[currcons].d->vc_rows)
+#define video_size_row (vc_cons[currcons].d->vc_size_row)
+#define can_do_color (vc_cons[currcons].d->vc_can_do_color)
+
+extern int console_blanked;
+
+extern unsigned char color_table[];
+extern int default_red[];
+extern int default_grn[];
+extern int default_blu[];
+
+extern unsigned short *screen_pos(int currcons, int w_offset, int viewed);
+extern u16 screen_glyph(int currcons, int offset);
+extern void complement_pos(int currcons, int offset);
+extern void invert_screen(int currcons, int offset, int count, int shift);
+
+extern void getconsxy(int currcons, char *p);
+extern void putconsxy(int currcons, char *p);
+
+extern u16 vcs_scr_readw(int currcons, const u16 *org);
+extern void vcs_scr_writew(int currcons, u16 val, u16 *org);
+
+#endif
diff --git a/pfinet/linux-src/include/linux/sem.h b/pfinet/linux-src/include/linux/sem.h
new file mode 100644
index 00000000..3fb2a48f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sem.h
@@ -0,0 +1,114 @@
+#ifndef _LINUX_SEM_H
+#define _LINUX_SEM_H
+
+#include <linux/ipc.h>
+
+/* semop flags */
+#define SEM_UNDO 0x1000 /* undo the operation on exit */
+
+/* semctl Command Definitions. */
+#define GETPID 11 /* get sempid */
+#define GETVAL 12 /* get semval */
+#define GETALL 13 /* get all semval's */
+#define GETNCNT 14 /* get semncnt */
+#define GETZCNT 15 /* get semzcnt */
+#define SETVAL 16 /* set semval */
+#define SETALL 17 /* set all semval's */
+
+/* ipcs ctl cmds */
+#define SEM_STAT 18
+#define SEM_INFO 19
+
+/* One semid data structure for each set of semaphores in the system. */
+struct semid_ds {
+ struct ipc_perm sem_perm; /* permissions .. see ipc.h */
+ __kernel_time_t sem_otime; /* last semop time */
+ __kernel_time_t sem_ctime; /* last change time */
+ struct sem *sem_base; /* ptr to first semaphore in array */
+ struct sem_queue *sem_pending; /* pending operations to be processed */
+ struct sem_queue **sem_pending_last; /* last pending operation */
+ struct sem_undo *undo; /* undo requests on this array */
+ unsigned short sem_nsems; /* no. of semaphores in array */
+};
+
+/* semop system calls takes an array of these. */
+struct sembuf {
+ unsigned short sem_num; /* semaphore index in array */
+ short sem_op; /* semaphore operation */
+ short sem_flg; /* operation flags */
+};
+
+/* arg for semctl system calls. */
+union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
+ unsigned short *array; /* array for GETALL & SETALL */
+ struct seminfo *__buf; /* buffer for IPC_INFO */
+ void *__pad;
+};
+
+struct seminfo {
+ int semmap;
+ int semmni;
+ int semmns;
+ int semmnu;
+ int semmsl;
+ int semopm;
+ int semume;
+ int semusz;
+ int semvmx;
+ int semaem;
+};
+
+#define SEMMNI 128 /* ? max # of semaphore identifiers */
+#define SEMMSL 32 /* <= 512 max num of semaphores per id */
+#define SEMMNS (SEMMNI*SEMMSL) /* ? max # of semaphores in system */
+#define SEMOPM 32 /* ~ 100 max num of ops per semop call */
+#define SEMVMX 32767 /* semaphore maximum value */
+
+/* unused */
+#define SEMUME SEMOPM /* max num of undo entries per process */
+#define SEMMNU SEMMNS /* num of undo structures system wide */
+#define SEMAEM (SEMVMX >> 1) /* adjust on exit max value */
+#define SEMMAP SEMMNS /* # of entries in semaphore map */
+#define SEMUSZ 20 /* sizeof struct sem_undo */
+
+#ifdef __KERNEL__
+
+/* One semaphore structure for each semaphore in the system. */
+struct sem {
+ int semval; /* current value */
+ int sempid; /* pid of last operation */
+};
+
+/* One queue for each semaphore set in the system. */
+struct sem_queue {
+ struct sem_queue * next; /* next entry in the queue */
+ struct sem_queue ** prev; /* previous entry in the queue, *(q->prev) == q */
+ struct wait_queue * sleeper; /* sleeping process */
+ struct sem_undo * undo; /* undo structure */
+ int pid; /* process id of requesting process */
+ int status; /* completion status of operation */
+ struct semid_ds * sma; /* semaphore array for operations */
+ struct sembuf * sops; /* array of pending operations */
+ int nsops; /* number of operations */
+ int alter; /* operation will alter semaphore */
+};
+
+/* Each task has a list of undo requests. They are executed automatically
+ * when the process exits.
+ */
+struct sem_undo {
+ struct sem_undo * proc_next; /* next entry on this process */
+ struct sem_undo * id_next; /* next entry on this semaphore set */
+ int semid; /* semaphore set identifier */
+ short * semadj; /* array of adjustments, one per semaphore */
+};
+
+asmlinkage int sys_semget (key_t key, int nsems, int semflg);
+asmlinkage int sys_semop (int semid, struct sembuf *sops, unsigned nsops);
+asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SEM_H */
diff --git a/pfinet/linux-src/include/linux/serial.h b/pfinet/linux-src/include/linux/serial.h
new file mode 100644
index 00000000..929618dd
--- /dev/null
+++ b/pfinet/linux-src/include/linux/serial.h
@@ -0,0 +1,142 @@
+/*
+ * include/linux/serial.h
+ *
+ * Copyright (C) 1992 by Theodore Ts'o.
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+#ifndef _LINUX_SERIAL_H
+#define _LINUX_SERIAL_H
+
+struct serial_struct {
+ int type;
+ int line;
+ int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int baud_base;
+ unsigned short close_delay;
+ char reserved_char[2];
+ int hub6;
+ unsigned short closing_wait; /* time to wait before closing */
+ unsigned short closing_wait2; /* no longer used... */
+ int reserved[4];
+};
+
+/*
+ * For the close wait times, 0 means wait forever for serial port to
+ * flush its output. 65535 means don't wait at all.
+ */
+#define ASYNC_CLOSING_WAIT_INF 0
+#define ASYNC_CLOSING_WAIT_NONE 65535
+
+/*
+ * These are the supported serial types.
+ */
+#define PORT_UNKNOWN 0
+#define PORT_8250 1
+#define PORT_16450 2
+#define PORT_16550 3
+#define PORT_16550A 4
+#define PORT_CIRRUS 5 /* usurped by cyclades.c */
+#define PORT_16650 6
+#define PORT_16650V2 7
+#define PORT_16750 8
+#define PORT_STARTECH 9 /* usurped by cyclades.c */
+#define PORT_MAX 9
+
+struct serial_uart_config {
+ char *name;
+ int dfl_xmit_fifo_size;
+ int flags;
+};
+
+#define UART_CLEAR_FIFO 0x01
+#define UART_USE_FIFO 0x02
+#define UART_STARTECH 0x04
+
+/*
+ * Definitions for async_struct (and serial_struct) flags field
+ */
+#define ASYNC_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
+ on the callout port */
+#define ASYNC_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
+#define ASYNC_SAK 0x0004 /* Secure Attention Key (Orange book) */
+#define ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
+
+#define ASYNC_SPD_MASK 0x1030
+#define ASYNC_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
+
+#define ASYNC_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
+#define ASYNC_SPD_CUST 0x0030 /* Use user-specified divisor */
+
+#define ASYNC_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */
+#define ASYNC_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */
+#define ASYNC_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+#define ASYNC_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
+#define ASYNC_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */
+
+#define ASYNC_HARDPPS_CD 0x0800 /* Call hardpps when CD goes high */
+
+#define ASYNC_SPD_SHI 0x1000 /* Use 230400 instead of 38400 bps */
+#define ASYNC_SPD_WARP 0x1010 /* Use 460800 instead of 38400 bps */
+
+#define ASYNC_LOW_LATENCY 0x2000 /* Request low latency behaviour */
+
+#define ASYNC_FLAGS 0x3FFF /* Possible legal async flags */
+#define ASYNC_USR_MASK 0x3430 /* Legal flags that non-privileged
+ * users can set or reset */
+
+/* Internal flags used only by kernel/chr_drv/serial.c */
+#define ASYNC_INITIALIZED 0x80000000 /* Serial port was initialized */
+#define ASYNC_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
+#define ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
+#define ASYNC_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */
+#define ASYNC_CLOSING 0x08000000 /* Serial port is closing */
+#define ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */
+#define ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */
+#define ASYNC_SHARE_IRQ 0x01000000 /* for multifunction cards */
+
+#define ASYNC_INTERNAL_FLAGS 0xFF000000 /* Internal flags */
+
+/*
+ * Multiport serial configuration structure --- external structure
+ */
+struct serial_multiport_struct {
+ int irq;
+ int port1;
+ unsigned char mask1, match1;
+ int port2;
+ unsigned char mask2, match2;
+ int port3;
+ unsigned char mask3, match3;
+ int port4;
+ unsigned char mask4, match4;
+ int port_monitor;
+ int reserved[32];
+};
+
+/*
+ * Serial input interrupt line counters -- external structure
+ * Four lines can interrupt: CTS, DSR, RI, DCD
+ */
+struct serial_icounter_struct {
+ int cts, dsr, rng, dcd;
+ int rx, tx;
+ int frame, overrun, parity, brk;
+ int buf_overrun;
+ int reserved[9];
+};
+
+
+#ifdef __KERNEL__
+/* Export to allow PCMCIA to use this - Dave Hinds */
+extern int register_serial(struct serial_struct *req);
+extern void unregister_serial(int line);
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_SERIAL_H */
diff --git a/pfinet/linux-src/include/linux/serial167.h b/pfinet/linux-src/include/linux/serial167.h
new file mode 100644
index 00000000..9f01f361
--- /dev/null
+++ b/pfinet/linux-src/include/linux/serial167.h
@@ -0,0 +1,175 @@
+/*
+ * serial167.h
+ *
+ * Richard Hirst [richard@sleepie.demon.co.uk]
+ *
+ * Based on cyclades.h
+ */
+
+struct cyclades_monitor {
+ unsigned long int_count;
+ unsigned long char_count;
+ unsigned long char_max;
+ unsigned long char_last;
+};
+
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+struct cyclades_port {
+ int magic;
+ int type;
+ int card;
+ int line;
+ int flags; /* defined in tty.h */
+ struct tty_struct *tty;
+ int read_status_mask;
+ int timeout;
+ int xmit_fifo_size;
+ int cor1,cor2,cor3,cor4,cor5,cor6,cor7;
+ int tbpr,tco,rbpr,rco;
+ int ignore_status_mask;
+ int close_delay;
+ int IER; /* Interrupt Enable Register */
+ int event;
+ unsigned long last_active;
+ int count; /* # of fd on device */
+ int x_char; /* to be pushed out ASAP */
+ int x_break;
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ int default_threshold;
+ int default_timeout;
+ struct tq_struct tqueue;
+ struct termios normal_termios;
+ struct termios callout_termios;
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+ struct cyclades_monitor mon;
+};
+
+#define CYCLADES_MAGIC 0x4359
+
+#define CYGETMON 0x435901
+#define CYGETTHRESH 0x435902
+#define CYSETTHRESH 0x435903
+#define CYGETDEFTHRESH 0x435904
+#define CYSETDEFTHRESH 0x435905
+#define CYGETTIMEOUT 0x435906
+#define CYSETTIMEOUT 0x435907
+#define CYGETDEFTIMEOUT 0x435908
+#define CYSETDEFTIMEOUT 0x435909
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at cy interrupt time.
+ */
+#define Cy_EVENT_READ_PROCESS 0
+#define Cy_EVENT_WRITE_WAKEUP 1
+#define Cy_EVENT_HANGUP 2
+#define Cy_EVENT_BREAK 3
+#define Cy_EVENT_OPEN_WAKEUP 4
+
+
+
+#define CyMaxChipsPerCard 1
+
+/**** cd2401 registers ****/
+
+#define CyGFRCR (0x81)
+#define CyCCR (0x13)
+#define CyCLR_CHAN (0x40)
+#define CyINIT_CHAN (0x20)
+#define CyCHIP_RESET (0x10)
+#define CyENB_XMTR (0x08)
+#define CyDIS_XMTR (0x04)
+#define CyENB_RCVR (0x02)
+#define CyDIS_RCVR (0x01)
+#define CyCAR (0xee)
+#define CyIER (0x11)
+#define CyMdmCh (0x80)
+#define CyRxExc (0x20)
+#define CyRxData (0x08)
+#define CyTxMpty (0x02)
+#define CyTxRdy (0x01)
+#define CyLICR (0x26)
+#define CyRISR (0x89)
+#define CyTIMEOUT (0x80)
+#define CySPECHAR (0x70)
+#define CyOVERRUN (0x08)
+#define CyPARITY (0x04)
+#define CyFRAME (0x02)
+#define CyBREAK (0x01)
+#define CyREOIR (0x84)
+#define CyTEOIR (0x85)
+#define CyMEOIR (0x86)
+#define CyNOTRANS (0x08)
+#define CyRFOC (0x30)
+#define CyRDR (0xf8)
+#define CyTDR (0xf8)
+#define CyMISR (0x8b)
+#define CyRISR (0x89)
+#define CyTISR (0x8a)
+#define CyMSVR1 (0xde)
+#define CyMSVR2 (0xdf)
+#define CyDSR (0x80)
+#define CyDCD (0x40)
+#define CyCTS (0x20)
+#define CyDTR (0x02)
+#define CyRTS (0x01)
+#define CyRTPRL (0x25)
+#define CyRTPRH (0x24)
+#define CyCOR1 (0x10)
+#define CyPARITY_NONE (0x00)
+#define CyPARITY_E (0x40)
+#define CyPARITY_O (0xC0)
+#define Cy_5_BITS (0x04)
+#define Cy_6_BITS (0x05)
+#define Cy_7_BITS (0x06)
+#define Cy_8_BITS (0x07)
+#define CyCOR2 (0x17)
+#define CyETC (0x20)
+#define CyCtsAE (0x02)
+#define CyCOR3 (0x16)
+#define Cy_1_STOP (0x02)
+#define Cy_2_STOP (0x04)
+#define CyCOR4 (0x15)
+#define CyREC_FIFO (0x0F) /* Receive FIFO threshold */
+#define CyCOR5 (0x14)
+#define CyCOR6 (0x18)
+#define CyCOR7 (0x07)
+#define CyRBPR (0xcb)
+#define CyRCOR (0xc8)
+#define CyTBPR (0xc3)
+#define CyTCOR (0xc0)
+#define CySCHR1 (0x1f)
+#define CySCHR2 (0x1e)
+#define CyTPR (0xda)
+#define CyPILR1 (0xe3)
+#define CyPILR2 (0xe0)
+#define CyPILR3 (0xe1)
+#define CyCMR (0x1b)
+#define CyASYNC (0x02)
+#define CyLICR (0x26)
+#define CyLIVR (0x09)
+#define CySCRL (0x23)
+#define CySCRH (0x22)
+#define CyTFTC (0x80)
+
+
+/* max number of chars in the FIFO */
+
+#define CyMAX_CHAR_FIFO 12
+
+/***************************************************************************/
diff --git a/pfinet/linux-src/include/linux/serialP.h b/pfinet/linux-src/include/linux/serialP.h
new file mode 100644
index 00000000..6bf0746e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/serialP.h
@@ -0,0 +1,119 @@
+/*
+ * Private header file for the (dumb) serial driver
+ *
+ * Copyright (C) 1997 by Theodore Ts'o.
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+#ifndef _LINUX_SERIALP_H
+#define _LINUX_SERIALP_H
+
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+#include <linux/termios.h>
+#include <linux/tqueue.h>
+
+/*
+ * Counters of the input lines (CTS, DSR, RI, CD) interrupts
+ */
+struct async_icount {
+ __u32 cts, dsr, rng, dcd, tx, rx;
+ __u32 frame, parity, overrun, brk;
+ __u32 buf_overrun;
+};
+
+struct serial_state {
+ int magic;
+ int baud_base;
+ int port;
+ int irq;
+ int flags;
+ int hub6;
+ int type;
+ int line;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int count;
+ unsigned short close_delay;
+ unsigned short closing_wait; /* time to wait before closing */
+ struct async_icount icount;
+ struct termios normal_termios;
+ struct termios callout_termios;
+ struct async_struct *info;
+};
+
+struct async_struct {
+ int magic;
+ int port;
+ int hub6;
+ int flags;
+ int xmit_fifo_size;
+ struct serial_state *state;
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int quot;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ int IER; /* Interrupt Enable Register */
+ int MCR; /* Modem control register */
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ struct tq_struct tqueue;
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+ struct wait_queue *delta_msr_wait;
+ struct async_struct *next_port; /* For the linked list */
+ struct async_struct *prev_port;
+};
+
+#define SERIAL_MAGIC 0x5301
+#define SSTATE_MAGIC 0x5302
+
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP 0
+
+/*
+ * Multiport serial configuration structure --- internal structure
+ */
+struct rs_multiport_struct {
+ int port1;
+ unsigned char mask1, match1;
+ int port2;
+ unsigned char mask2, match2;
+ int port3;
+ unsigned char mask3, match3;
+ int port4;
+ unsigned char mask4, match4;
+ int port_monitor;
+};
+
+#endif /* _LINUX_SERIAL_H */
diff --git a/pfinet/linux-src/include/linux/serial_reg.h b/pfinet/linux-src/include/linux/serial_reg.h
new file mode 100644
index 00000000..713227a5
--- /dev/null
+++ b/pfinet/linux-src/include/linux/serial_reg.h
@@ -0,0 +1,144 @@
+/*
+ * include/linux/serial_reg.h
+ *
+ * Copyright (C) 1992, 1994 by Theodore Ts'o.
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ *
+ * These are the UART port assignments, expressed as offsets from the base
+ * register. These assignments should hold for any serial port based on
+ * a 8250, 16450, or 16550(A).
+ */
+
+#ifndef _LINUX_SERIAL_REG_H
+#define _LINUX_SERIAL_REG_H
+
+#define UART_RX 0 /* In: Receive buffer (DLAB=0) */
+#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */
+#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
+#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */
+#define UART_IER 1 /* Out: Interrupt Enable Register */
+#define UART_IIR 2 /* In: Interrupt ID Register */
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_EFR 2 /* I/O: Extended Features Register */
+ /* (DLAB=1, 16C660 only) */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+
+/*
+ * These are the definitions for the FIFO Control Register
+ * (16650 only)
+ */
+#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
+#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
+#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
+#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
+#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
+#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
+#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
+#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
+#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
+/* 16650 redefinitions */
+#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */
+#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */
+#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */
+#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */
+#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */
+#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */
+#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */
+#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
+/* TI 16750 definitions */
+#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode */
+
+/*
+ * These are the definitions for the Line Control Register
+ *
+ * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
+ * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
+ */
+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
+#define UART_LCR_SBC 0x40 /* Set break control */
+#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
+#define UART_LCR_EPAR 0x10 /* Even parity select */
+#define UART_LCR_PARITY 0x08 /* Parity Enable */
+#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
+#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
+#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
+#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
+#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
+
+/*
+ * These are the definitions for the Line Status Register
+ */
+#define UART_LSR_TEMT 0x40 /* Transmitter empty */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_BI 0x10 /* Break interrupt indicator */
+#define UART_LSR_FE 0x08 /* Frame error indicator */
+#define UART_LSR_PE 0x04 /* Parity error indicator */
+#define UART_LSR_OE 0x02 /* Overrun error indicator */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+
+/*
+ * These are the definitions for the Interrupt Identification Register
+ */
+#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
+#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
+
+#define UART_IIR_MSI 0x00 /* Modem status interrupt */
+#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
+#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
+#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
+
+/*
+ * These are the definitions for the Interrupt Enable Register
+ */
+#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
+#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
+#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
+#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
+/*
+ * Sleep mode for ST16650 and TI16750.
+ * Note that for 16650, EFR-bit 4 must be selected as well.
+ */
+#define UART_IERX_SLEEP 0x10 /* Enable sleep mode */
+
+/*
+ * These are the definitions for the Modem Control Register
+ */
+#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
+#define UART_MCR_OUT2 0x08 /* Out2 complement */
+#define UART_MCR_OUT1 0x04 /* Out1 complement */
+#define UART_MCR_RTS 0x02 /* RTS complement */
+#define UART_MCR_DTR 0x01 /* DTR complement */
+
+/*
+ * These are the definitions for the Modem Status Register
+ */
+#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
+#define UART_MSR_RI 0x40 /* Ring Indicator */
+#define UART_MSR_DSR 0x20 /* Data Set Ready */
+#define UART_MSR_CTS 0x10 /* Clear to Send */
+#define UART_MSR_DDCD 0x08 /* Delta DCD */
+#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
+#define UART_MSR_DDSR 0x02 /* Delta DSR */
+#define UART_MSR_DCTS 0x01 /* Delta CTS */
+#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
+
+/*
+ * These are the definitions for the Extended Features Register
+ * (StarTech 16C660 only, when DLAB=1)
+ */
+#define UART_EFR_CTS 0x80 /* CTS flow control */
+#define UART_EFR_RTS 0x40 /* RTS flow control */
+#define UART_EFR_SCD 0x20 /* Special character detect */
+#define UART_EFR_ECB 0x10 /* Enhanced control bit */
+/*
+ * the low four bits control software flow control
+ */
+
+#endif /* _LINUX_SERIAL_REG_H */
+
diff --git a/pfinet/linux-src/include/linux/shm.h b/pfinet/linux-src/include/linux/shm.h
new file mode 100644
index 00000000..a6d13e8d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/shm.h
@@ -0,0 +1,79 @@
+#ifndef _LINUX_SHM_H_
+#define _LINUX_SHM_H_
+
+#include <linux/ipc.h>
+
+#include <asm/shmparam.h>
+
+struct shmid_ds {
+ struct ipc_perm shm_perm; /* operation perms */
+ int shm_segsz; /* size of segment (bytes) */
+ __kernel_time_t shm_atime; /* last attach time */
+ __kernel_time_t shm_dtime; /* last detach time */
+ __kernel_time_t shm_ctime; /* last change time */
+ __kernel_ipc_pid_t shm_cpid; /* pid of creator */
+ __kernel_ipc_pid_t shm_lpid; /* pid of last operator */
+ unsigned short shm_nattch; /* no. of current attaches */
+ unsigned short shm_unused; /* compatibility */
+ void *shm_unused2; /* ditto - used by DIPC */
+ void *shm_unused3; /* unused */
+};
+
+struct shmid_kernel
+{
+ struct shmid_ds u;
+ /* the following are private */
+ unsigned long shm_npages; /* size of segment (pages) */
+ unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */
+ struct vm_area_struct *attaches; /* descriptors for attaches */
+};
+
+/* permission flag for shmget */
+#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */
+#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */
+
+/* mode for attach */
+#define SHM_RDONLY 010000 /* read-only access */
+#define SHM_RND 020000 /* round attach address to SHMLBA boundary */
+#define SHM_REMAP 040000 /* take-over region on attach */
+
+/* super user shmctl commands */
+#define SHM_LOCK 11
+#define SHM_UNLOCK 12
+
+/* ipcs ctl commands */
+#define SHM_STAT 13
+#define SHM_INFO 14
+
+struct shminfo {
+ int shmmax;
+ int shmmin;
+ int shmmni;
+ int shmseg;
+ int shmall;
+};
+
+struct shm_info {
+ int used_ids;
+ unsigned long shm_tot; /* total allocated shm */
+ unsigned long shm_rss; /* total resident shm */
+ unsigned long shm_swp; /* total swapped shm */
+ unsigned long swap_attempts;
+ unsigned long swap_successes;
+};
+
+#ifdef __KERNEL__
+
+/* shm_mode upper byte flags */
+#define SHM_DEST 01000 /* segment will be destroyed on last detach */
+#define SHM_LOCKED 02000 /* segment will not be swapped */
+
+asmlinkage int sys_shmget (key_t key, int size, int flag);
+asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, unsigned long *addr);
+asmlinkage int sys_shmdt (char *shmaddr);
+asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
+extern void shm_unuse(unsigned long entry, unsigned long page);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SHM_H_ */
diff --git a/pfinet/linux-src/include/linux/signal.h b/pfinet/linux-src/include/linux/signal.h
new file mode 100644
index 00000000..d6e82ae0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/signal.h
@@ -0,0 +1,212 @@
+#ifndef _LINUX_SIGNAL_H
+#define _LINUX_SIGNAL_H
+
+#include <asm/signal.h>
+#include <asm/siginfo.h>
+
+#ifdef __KERNEL__
+/*
+ * Real Time signals may be queued.
+ */
+
+struct signal_queue
+{
+ struct signal_queue *next;
+ siginfo_t info;
+};
+
+/*
+ * Define some primitives to manipulate sigset_t.
+ */
+
+#ifndef __HAVE_ARCH_SIG_BITOPS
+#include <asm/bitops.h>
+
+/* We don't use <asm/bitops.h> for these because there is no need to
+ be atomic. */
+extern inline void sigaddset(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ if (_NSIG_WORDS == 1)
+ set->sig[0] |= 1UL << sig;
+ else
+ set->sig[sig / _NSIG_BPW] |= 1UL << (sig % _NSIG_BPW);
+}
+
+extern inline void sigdelset(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ if (_NSIG_WORDS == 1)
+ set->sig[0] &= ~(1UL << sig);
+ else
+ set->sig[sig / _NSIG_BPW] &= ~(1UL << (sig % _NSIG_BPW));
+}
+
+extern inline int sigismember(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ if (_NSIG_WORDS == 1)
+ return 1 & (set->sig[0] >> sig);
+ else
+ return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
+}
+
+extern inline int sigfindinword(unsigned long word)
+{
+ return ffz(~word);
+}
+
+#define sigmask(sig) (1UL << ((sig) - 1))
+
+#endif /* __HAVE_ARCH_SIG_BITOPS */
+
+#ifndef __HAVE_ARCH_SIG_SETOPS
+#include <linux/string.h>
+
+#define _SIG_SET_BINOP(name, op) \
+extern inline void name(sigset_t *r, const sigset_t *a, const sigset_t *b) \
+{ \
+ unsigned long a0, a1, a2, a3, b0, b1, b2, b3; \
+ unsigned long i; \
+ \
+ for (i = 0; i < _NSIG_WORDS/4; ++i) { \
+ a0 = a->sig[4*i+0]; a1 = a->sig[4*i+1]; \
+ a2 = a->sig[4*i+2]; a3 = a->sig[4*i+3]; \
+ b0 = b->sig[4*i+0]; b1 = b->sig[4*i+1]; \
+ b2 = b->sig[4*i+2]; b3 = b->sig[4*i+3]; \
+ r->sig[4*i+0] = op(a0, b0); \
+ r->sig[4*i+1] = op(a1, b1); \
+ r->sig[4*i+2] = op(a2, b2); \
+ r->sig[4*i+3] = op(a3, b3); \
+ } \
+ switch (_NSIG_WORDS % 4) { \
+ case 3: \
+ a0 = a->sig[4*i+0]; a1 = a->sig[4*i+1]; a2 = a->sig[4*i+2]; \
+ b0 = b->sig[4*i+0]; b1 = b->sig[4*i+1]; b2 = b->sig[4*i+2]; \
+ r->sig[4*i+0] = op(a0, b0); \
+ r->sig[4*i+1] = op(a1, b1); \
+ r->sig[4*i+2] = op(a2, b2); \
+ break; \
+ case 2: \
+ a0 = a->sig[4*i+0]; a1 = a->sig[4*i+1]; \
+ b0 = b->sig[4*i+0]; b1 = b->sig[4*i+1]; \
+ r->sig[4*i+0] = op(a0, b0); \
+ r->sig[4*i+1] = op(a1, b1); \
+ break; \
+ case 1: \
+ a0 = a->sig[4*i+0]; b0 = b->sig[4*i+0]; \
+ r->sig[4*i+0] = op(a0, b0); \
+ break; \
+ } \
+}
+
+#define _sig_or(x,y) ((x) | (y))
+_SIG_SET_BINOP(sigorsets, _sig_or)
+
+#define _sig_and(x,y) ((x) & (y))
+_SIG_SET_BINOP(sigandsets, _sig_and)
+
+#define _sig_nand(x,y) ((x) & ~(y))
+_SIG_SET_BINOP(signandsets, _sig_nand)
+
+#undef _SIG_SET_BINOP
+#undef _sig_or
+#undef _sig_and
+#undef _sig_nand
+
+#define _SIG_SET_OP(name, op) \
+extern inline void name(sigset_t *set) \
+{ \
+ unsigned long i; \
+ \
+ for (i = 0; i < _NSIG_WORDS/4; ++i) { \
+ set->sig[4*i+0] = op(set->sig[4*i+0]); \
+ set->sig[4*i+1] = op(set->sig[4*i+1]); \
+ set->sig[4*i+2] = op(set->sig[4*i+2]); \
+ set->sig[4*i+3] = op(set->sig[4*i+3]); \
+ } \
+ switch (_NSIG_WORDS % 4) { \
+ case 3: set->sig[4*i+2] = op(set->sig[4*i+2]); \
+ case 2: set->sig[4*i+1] = op(set->sig[4*i+1]); \
+ case 1: set->sig[4*i+0] = op(set->sig[4*i+0]); \
+ } \
+}
+
+#define _sig_not(x) (~(x))
+_SIG_SET_OP(signotset, _sig_not)
+
+#undef _SIG_SET_OP
+#undef _sig_not
+
+extern inline void sigemptyset(sigset_t *set)
+{
+ switch (_NSIG_WORDS) {
+ default:
+ memset(set, 0, sizeof(sigset_t));
+ break;
+ case 2: set->sig[1] = 0;
+ case 1: set->sig[0] = 0;
+ break;
+ }
+}
+
+extern inline void sigfillset(sigset_t *set)
+{
+ switch (_NSIG_WORDS) {
+ default:
+ memset(set, -1, sizeof(sigset_t));
+ break;
+ case 2: set->sig[1] = -1;
+ case 1: set->sig[0] = -1;
+ break;
+ }
+}
+
+extern char * render_sigset_t(sigset_t *set, char *buffer);
+
+/* Some extensions for manipulating the low 32 signals in particular. */
+
+extern inline void sigaddsetmask(sigset_t *set, unsigned long mask)
+{
+ set->sig[0] |= mask;
+}
+
+extern inline void sigdelsetmask(sigset_t *set, unsigned long mask)
+{
+ set->sig[0] &= ~mask;
+}
+
+extern inline int sigtestsetmask(sigset_t *set, unsigned long mask)
+{
+ return (set->sig[0] & mask) != 0;
+}
+
+extern inline void siginitset(sigset_t *set, unsigned long mask)
+{
+ set->sig[0] = mask;
+ switch (_NSIG_WORDS) {
+ default:
+ memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1));
+ break;
+ case 2: set->sig[1] = 0;
+ case 1:
+ }
+}
+
+extern inline void siginitsetinv(sigset_t *set, unsigned long mask)
+{
+ set->sig[0] = ~mask;
+ switch (_NSIG_WORDS) {
+ default:
+ memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1));
+ break;
+ case 2: set->sig[1] = -1;
+ case 1:
+ }
+}
+
+#endif /* __HAVE_ARCH_SIG_SETOPS */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SIGNAL_H */
diff --git a/pfinet/linux-src/include/linux/skbuff.h b/pfinet/linux-src/include/linux/skbuff.h
new file mode 100644
index 00000000..82d5da6e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/skbuff.h
@@ -0,0 +1,584 @@
+/*
+ * Definitions for the 'struct sk_buff' memory handlers.
+ *
+ * Authors:
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Florian La Roche, <rzsfl@rz.uni-sb.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_SKBUFF_H
+#define _LINUX_SKBUFF_H
+
+#include <linux/config.h>
+#include <linux/time.h>
+
+#include <asm/atomic.h>
+#include <asm/types.h>
+#include <asm/spinlock.h>
+
+#define HAVE_ALLOC_SKB /* For the drivers to know */
+#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
+#define SLAB_SKB /* Slabified skbuffs */
+
+#define CHECKSUM_NONE 0
+#define CHECKSUM_HW 1
+#define CHECKSUM_UNNECESSARY 2
+
+struct sk_buff_head {
+ struct sk_buff * next;
+ struct sk_buff * prev;
+ __u32 qlen; /* Must be same length as a pointer
+ for using debugging */
+};
+
+struct sk_buff {
+ struct sk_buff * next; /* Next buffer in list */
+ struct sk_buff * prev; /* Previous buffer in list */
+ struct sk_buff_head * list; /* List we are on */
+ struct sock *sk; /* Socket we are owned by */
+ struct timeval stamp; /* Time we arrived */
+ struct device *dev; /* Device we arrived on/are leaving by */
+
+ /* Transport layer header */
+ union
+ {
+ struct tcphdr *th;
+ struct udphdr *uh;
+ struct icmphdr *icmph;
+ struct igmphdr *igmph;
+ struct iphdr *ipiph;
+ struct spxhdr *spxh;
+ unsigned char *raw;
+ } h;
+
+ /* Network layer header */
+ union
+ {
+ struct iphdr *iph;
+ struct ipv6hdr *ipv6h;
+ struct arphdr *arph;
+ struct ipxhdr *ipxh;
+ unsigned char *raw;
+ } nh;
+
+ /* Link layer header */
+ union
+ {
+ struct ethhdr *ethernet;
+ unsigned char *raw;
+ } mac;
+
+ struct dst_entry *dst;
+
+ char cb[48];
+
+ unsigned int len; /* Length of actual data */
+ unsigned int csum; /* Checksum */
+ volatile char used; /* Data moved to user and not MSG_PEEK */
+ unsigned char is_clone, /* We are a clone */
+ cloned, /* head may be cloned (check refcnt to be sure). */
+ pkt_type, /* Packet class */
+ pkt_bridged, /* Tracker for bridging */
+ ip_summed; /* Driver fed us an IP checksum */
+ __u32 priority; /* Packet queueing priority */
+ atomic_t users; /* User count - see datagram.c,tcp.c */
+ unsigned short protocol; /* Packet protocol from driver. */
+ unsigned short security; /* Security level of packet */
+ unsigned int truesize; /* Buffer size */
+
+ unsigned char *head; /* Head of buffer */
+ unsigned char *data; /* Data head pointer */
+ unsigned char *tail; /* Tail pointer */
+ unsigned char *end; /* End pointer */
+ void (*destructor)(struct sk_buff *); /* Destruct function */
+#ifdef CONFIG_IP_FIREWALL
+ __u32 fwmark; /* Label made by fwchains, used by pktsched */
+#endif
+#if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE)
+ __u32 shapelatency; /* Latency on frame */
+ __u32 shapeclock; /* Time it should go out */
+ __u32 shapelen; /* Frame length in clocks */
+ __u32 shapestamp; /* Stamp for shaper */
+ __u16 shapepend; /* Pending */
+#endif
+
+#if defined(CONFIG_HIPPI)
+ union{
+ __u32 ifield;
+ } private;
+#endif
+};
+
+/* These are just the default values. This is run time configurable.
+ * FIXME: Probably the config option should go away. -- erics
+ */
+#ifdef CONFIG_SKB_LARGE
+#define SK_WMEM_MAX 65535
+#define SK_RMEM_MAX 65535
+#else
+#define SK_WMEM_MAX 32767
+#define SK_RMEM_MAX 32767
+#endif
+
+#ifdef __KERNEL__
+/*
+ * Handling routines are only of interest to the kernel
+ */
+#include <linux/malloc.h>
+
+#include <asm/system.h>
+
+extern void __kfree_skb(struct sk_buff *skb);
+extern void skb_queue_head_init(struct sk_buff_head *list);
+extern void skb_queue_head(struct sk_buff_head *list,struct sk_buff *buf);
+extern void skb_queue_tail(struct sk_buff_head *list,struct sk_buff *buf);
+extern struct sk_buff * skb_dequeue(struct sk_buff_head *list);
+extern void skb_insert(struct sk_buff *old,struct sk_buff *newsk);
+extern void skb_append(struct sk_buff *old,struct sk_buff *newsk);
+extern void skb_unlink(struct sk_buff *buf);
+extern __u32 skb_queue_len(struct sk_buff_head *list);
+extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list);
+extern struct sk_buff * alloc_skb(unsigned int size, int priority);
+extern struct sk_buff * dev_alloc_skb(unsigned int size);
+extern void kfree_skbmem(struct sk_buff *skb);
+extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
+extern struct sk_buff * skb_copy(struct sk_buff *skb, int priority);
+extern struct sk_buff * skb_realloc_headroom(struct sk_buff *skb, int newheadroom);
+#define dev_kfree_skb(a) kfree_skb(a)
+extern unsigned char * skb_put(struct sk_buff *skb, unsigned int len);
+extern unsigned char * skb_push(struct sk_buff *skb, unsigned int len);
+extern unsigned char * skb_pull(struct sk_buff *skb, unsigned int len);
+extern int skb_headroom(struct sk_buff *skb);
+extern int skb_tailroom(struct sk_buff *skb);
+extern void skb_reserve(struct sk_buff *skb, unsigned int len);
+extern void skb_trim(struct sk_buff *skb, unsigned int len);
+extern void skb_over_panic(struct sk_buff *skb, int len, void *here);
+extern void skb_under_panic(struct sk_buff *skb, int len, void *here);
+
+/* Internal */
+extern __inline__ atomic_t *skb_datarefp(struct sk_buff *skb)
+{
+ return (atomic_t *)(skb->end);
+}
+
+extern __inline__ int skb_queue_empty(struct sk_buff_head *list)
+{
+ return (list->next == (struct sk_buff *) list);
+}
+
+extern __inline__ void kfree_skb(struct sk_buff *skb)
+{
+ if (atomic_dec_and_test(&skb->users))
+ __kfree_skb(skb);
+}
+
+/* Use this if you didn't touch the skb state [for fast switching] */
+extern __inline__ void kfree_skb_fast(struct sk_buff *skb)
+{
+ if (atomic_dec_and_test(&skb->users))
+ kfree_skbmem(skb);
+}
+
+extern __inline__ int skb_cloned(struct sk_buff *skb)
+{
+ return skb->cloned && atomic_read(skb_datarefp(skb)) != 1;
+}
+
+extern __inline__ int skb_shared(struct sk_buff *skb)
+{
+ return (atomic_read(&skb->users) != 1);
+}
+
+/*
+ * Copy shared buffers into a new sk_buff. We effectively do COW on
+ * packets to handle cases where we have a local reader and forward
+ * and a couple of other messy ones. The normal one is tcpdumping
+ * a packet thats being forwarded.
+ */
+
+extern __inline__ struct sk_buff *skb_unshare(struct sk_buff *skb, int pri)
+{
+ struct sk_buff *nskb;
+ if(!skb_cloned(skb))
+ return skb;
+ nskb=skb_copy(skb, pri);
+ kfree_skb(skb); /* Free our shared copy */
+ return nskb;
+}
+
+/*
+ * Peek an sk_buff. Unlike most other operations you _MUST_
+ * be careful with this one. A peek leaves the buffer on the
+ * list and someone else may run off with it. For an interrupt
+ * type system cli() peek the buffer copy the data and sti();
+ */
+
+extern __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_)
+{
+ struct sk_buff *list = ((struct sk_buff *)list_)->next;
+ if (list == (struct sk_buff *)list_)
+ list = NULL;
+ return list;
+}
+
+extern __inline__ struct sk_buff *skb_peek_tail(struct sk_buff_head *list_)
+{
+ struct sk_buff *list = ((struct sk_buff *)list_)->prev;
+ if (list == (struct sk_buff *)list_)
+ list = NULL;
+ return list;
+}
+
+/*
+ * Return the length of an sk_buff queue
+ */
+
+extern __inline__ __u32 skb_queue_len(struct sk_buff_head *list_)
+{
+ return(list_->qlen);
+}
+
+extern __inline__ void skb_queue_head_init(struct sk_buff_head *list)
+{
+ list->prev = (struct sk_buff *)list;
+ list->next = (struct sk_buff *)list;
+ list->qlen = 0;
+}
+
+/*
+ * Insert an sk_buff at the start of a list.
+ *
+ * The "__skb_xxxx()" functions are the non-atomic ones that
+ * can only be called with interrupts disabled.
+ */
+
+extern __inline__ void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+ struct sk_buff *prev, *next;
+
+ newsk->list = list;
+ list->qlen++;
+ prev = (struct sk_buff *)list;
+ next = prev->next;
+ newsk->next = next;
+ newsk->prev = prev;
+ next->prev = newsk;
+ prev->next = newsk;
+}
+
+extern spinlock_t skb_queue_lock;
+
+extern __inline__ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ __skb_queue_head(list, newsk);
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
+}
+
+/*
+ * Insert an sk_buff at the end of a list.
+ */
+
+extern __inline__ void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+ struct sk_buff *prev, *next;
+
+ newsk->list = list;
+ list->qlen++;
+ next = (struct sk_buff *)list;
+ prev = next->prev;
+ newsk->next = next;
+ newsk->prev = prev;
+ next->prev = newsk;
+ prev->next = newsk;
+}
+
+extern __inline__ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ __skb_queue_tail(list, newsk);
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
+}
+
+/*
+ * Remove an sk_buff from a list.
+ */
+
+extern __inline__ struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
+{
+ struct sk_buff *next, *prev, *result;
+
+ prev = (struct sk_buff *) list;
+ next = prev->next;
+ result = NULL;
+ if (next != prev) {
+ result = next;
+ next = next->next;
+ list->qlen--;
+ next->prev = prev;
+ prev->next = next;
+ result->next = NULL;
+ result->prev = NULL;
+ result->list = NULL;
+ }
+ return result;
+}
+
+extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list)
+{
+ long flags;
+ struct sk_buff *result;
+
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ result = __skb_dequeue(list);
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
+ return result;
+}
+
+/*
+ * Insert a packet on a list.
+ */
+
+extern __inline__ void __skb_insert(struct sk_buff *newsk,
+ struct sk_buff * prev, struct sk_buff *next,
+ struct sk_buff_head * list)
+{
+ newsk->next = next;
+ newsk->prev = prev;
+ next->prev = newsk;
+ prev->next = newsk;
+ newsk->list = list;
+ list->qlen++;
+}
+
+/*
+ * Place a packet before a given packet in a list
+ */
+extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ __skb_insert(newsk, old->prev, old, old->list);
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
+}
+
+/*
+ * Place a packet after a given packet in a list.
+ */
+
+extern __inline__ void __skb_append(struct sk_buff *old, struct sk_buff *newsk)
+{
+ __skb_insert(newsk, old, old->next, old->list);
+}
+
+extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ __skb_append(old, newsk);
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
+}
+
+/*
+ * remove sk_buff from list. _Must_ be called atomically, and with
+ * the list known..
+ */
+extern __inline__ void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
+{
+ struct sk_buff * next, * prev;
+
+ list->qlen--;
+ next = skb->next;
+ prev = skb->prev;
+ skb->next = NULL;
+ skb->prev = NULL;
+ skb->list = NULL;
+ next->prev = prev;
+ prev->next = next;
+}
+
+/*
+ * Remove an sk_buff from its list. Works even without knowing the list it
+ * is sitting on, which can be handy at times. It also means that THE LIST
+ * MUST EXIST when you unlink. Thus a list must have its contents unlinked
+ * _FIRST_.
+ */
+
+extern __inline__ void skb_unlink(struct sk_buff *skb)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ if(skb->list)
+ __skb_unlink(skb, skb->list);
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
+}
+
+/* XXX: more streamlined implementation */
+extern __inline__ struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list)
+{
+ struct sk_buff *skb = skb_peek_tail(list);
+ if (skb)
+ __skb_unlink(skb, list);
+ return skb;
+}
+
+extern __inline__ struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
+{
+ long flags;
+ struct sk_buff *result;
+
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ result = __skb_dequeue_tail(list);
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
+ return result;
+}
+
+/*
+ * Add data to an sk_buff
+ */
+
+extern __inline__ unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+{
+ unsigned char *tmp=skb->tail;
+ skb->tail+=len;
+ skb->len+=len;
+ return tmp;
+}
+
+extern __inline__ unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
+{
+ unsigned char *tmp=skb->tail;
+ skb->tail+=len;
+ skb->len+=len;
+ if(skb->tail>skb->end)
+ {
+ __label__ here;
+ skb_over_panic(skb, len, &&here);
+here: ;
+ }
+ return tmp;
+}
+
+extern __inline__ unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+{
+ skb->data-=len;
+ skb->len+=len;
+ return skb->data;
+}
+
+extern __inline__ unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
+{
+ skb->data-=len;
+ skb->len+=len;
+ if(skb->data<skb->head)
+ {
+ __label__ here;
+ skb_under_panic(skb, len, &&here);
+here: ;
+ }
+ return skb->data;
+}
+
+extern __inline__ char *__skb_pull(struct sk_buff *skb, unsigned int len)
+{
+ skb->len-=len;
+ return skb->data+=len;
+}
+
+extern __inline__ unsigned char * skb_pull(struct sk_buff *skb, unsigned int len)
+{
+ if (len > skb->len)
+ return NULL;
+ return __skb_pull(skb,len);
+}
+
+extern __inline__ int skb_headroom(struct sk_buff *skb)
+{
+ return skb->data-skb->head;
+}
+
+extern __inline__ int skb_tailroom(struct sk_buff *skb)
+{
+ return skb->end-skb->tail;
+}
+
+extern __inline__ void skb_reserve(struct sk_buff *skb, unsigned int len)
+{
+ skb->data+=len;
+ skb->tail+=len;
+}
+
+extern __inline__ void __skb_trim(struct sk_buff *skb, unsigned int len)
+{
+ skb->len = len;
+ skb->tail = skb->data+len;
+}
+
+extern __inline__ void skb_trim(struct sk_buff *skb, unsigned int len)
+{
+ if (skb->len > len) {
+ __skb_trim(skb, len);
+ }
+}
+
+extern __inline__ void skb_orphan(struct sk_buff *skb)
+{
+ if (skb->destructor)
+ skb->destructor(skb);
+ skb->destructor = NULL;
+ skb->sk = NULL;
+}
+
+extern __inline__ void skb_queue_purge(struct sk_buff_head *list)
+{
+ struct sk_buff *skb;
+ while ((skb=skb_dequeue(list))!=NULL)
+ kfree_skb(skb);
+}
+
+extern __inline__ struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(length+16, GFP_ATOMIC);
+ if (skb)
+ skb_reserve(skb,16);
+ return skb;
+}
+
+extern __inline__ struct sk_buff *
+skb_cow(struct sk_buff *skb, unsigned int headroom)
+{
+ headroom = (headroom+15)&~15;
+
+ if ((unsigned)skb_headroom(skb) < headroom || skb_cloned(skb)) {
+ struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
+ kfree_skb(skb);
+ skb = skb2;
+ }
+ return skb;
+}
+
+extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
+extern unsigned int datagram_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait);
+extern int skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
+extern int skb_copy_datagram_iovec(struct sk_buff *from, int offset, struct iovec *to,int size);
+extern void skb_free_datagram(struct sock * sk, struct sk_buff *skb);
+
+extern void skb_init(void);
+extern void skb_add_mtu(int mtu);
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_SKBUFF_H */
diff --git a/pfinet/linux-src/include/linux/slab.h b/pfinet/linux-src/include/linux/slab.h
new file mode 100644
index 00000000..0b46d3b7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/slab.h
@@ -0,0 +1,71 @@
+/*
+ * linux/mm/slab.h
+ * Written by Mark Hemment, 1996.
+ * (markhe@nextd.demon.co.uk)
+ */
+
+#if !defined(_LINUX_SLAB_H)
+#define _LINUX_SLAB_H
+
+#if defined(__KERNEL__)
+
+typedef struct kmem_cache_s kmem_cache_t;
+
+#include <linux/mm.h>
+#include <asm/cache.h>
+
+/* flags for kmem_cache_alloc() */
+#define SLAB_BUFFER GFP_BUFFER
+#define SLAB_ATOMIC GFP_ATOMIC
+#define SLAB_USER GFP_USER
+#define SLAB_KERNEL GFP_KERNEL
+#define SLAB_NFS GFP_NFS
+#define SLAB_DMA GFP_DMA
+
+#define SLAB_LEVEL_MASK 0x0000007fUL
+#define SLAB_NO_GROW 0x00001000UL /* don't grow a cache */
+
+/* flags to pass to kmem_cache_create().
+ * The first 3 are only valid when the allocator as been build
+ * SLAB_DEBUG_SUPPORT.
+ */
+#define SLAB_DEBUG_FREE 0x00000100UL /* Peform (expensive) checks on free */
+#define SLAB_DEBUG_INITIAL 0x00000200UL /* Call constructor (as verifier) */
+#define SLAB_RED_ZONE 0x00000400UL /* Red zone objs in a cache */
+#define SLAB_POISON 0x00000800UL /* Poison objects */
+#define SLAB_NO_REAP 0x00001000UL /* never reap from the cache */
+#define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */
+#if 0
+#define SLAB_HIGH_PACK 0x00004000UL /* XXX */
+#endif
+
+/* flags passed to a constructor func */
+#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */
+#define SLAB_CTOR_ATOMIC 0x002UL /* tell constructor it can't sleep */
+#define SLAB_CTOR_VERIFY 0x004UL /* tell constructor it's a verify call */
+
+/* prototypes */
+extern long kmem_cache_init(long, long);
+extern void kmem_cache_sizes_init(void);
+extern kmem_cache_t *kmem_find_general_cachep(size_t);
+extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
+ void (*)(void *, kmem_cache_t *, unsigned long),
+ void (*)(void *, kmem_cache_t *, unsigned long));
+extern int kmem_cache_shrink(kmem_cache_t *);
+extern void *kmem_cache_alloc(kmem_cache_t *, int);
+extern void kmem_cache_free(kmem_cache_t *, void *);
+
+extern void *kmalloc(size_t, int);
+extern void kfree(const void *);
+extern void kfree_s(const void *, size_t);
+
+extern void kmem_cache_reap(int);
+extern int get_slabinfo(char *);
+
+/* System wide caches */
+extern kmem_cache_t *vm_area_cachep;
+extern kmem_cache_t *mm_cachep;
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SLAB_H */
diff --git a/pfinet/linux-src/include/linux/smb.h b/pfinet/linux-src/include/linux/smb.h
new file mode 100644
index 00000000..852d5b0d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/smb.h
@@ -0,0 +1,123 @@
+/*
+ * smb.h
+ *
+ * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
+ * Copyright (C) 1997 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_SMB_H
+#define _LINUX_SMB_H
+
+#include <linux/types.h>
+
+enum smb_protocol {
+ SMB_PROTOCOL_NONE,
+ SMB_PROTOCOL_CORE,
+ SMB_PROTOCOL_COREPLUS,
+ SMB_PROTOCOL_LANMAN1,
+ SMB_PROTOCOL_LANMAN2,
+ SMB_PROTOCOL_NT1
+};
+
+enum smb_case_hndl {
+ SMB_CASE_DEFAULT,
+ SMB_CASE_LOWER,
+ SMB_CASE_UPPER
+};
+
+struct smb_dskattr {
+ __u16 total;
+ __u16 allocblocks;
+ __u16 blocksize;
+ __u16 free;
+};
+
+struct smb_conn_opt {
+
+ /* The socket */
+ unsigned int fd;
+
+ enum smb_protocol protocol;
+ enum smb_case_hndl case_handling;
+
+ /* Connection-Options */
+
+ __u32 max_xmit;
+ __u16 server_uid;
+ __u16 tid;
+
+ /* The following are LANMAN 1.0 options */
+ __u16 secmode;
+ __u16 maxmux;
+ __u16 maxvcs;
+ __u16 rawmode;
+ __u32 sesskey;
+
+ /* The following are NT LM 0.12 options */
+ __u32 maxraw;
+ __u32 capabilities;
+ __s16 serverzone;
+};
+
+#ifdef __KERNEL__
+
+#define SMB_MAXNAMELEN 255
+#define SMB_MAXPATHLEN 1024
+
+/*
+ * Contains all relevant data on a SMB networked file.
+ */
+struct smb_fattr {
+
+ __u16 attr;
+
+ unsigned long f_ino;
+ umode_t f_mode;
+ nlink_t f_nlink;
+ uid_t f_uid;
+ gid_t f_gid;
+ kdev_t f_rdev;
+ off_t f_size;
+ time_t f_atime;
+ time_t f_mtime;
+ time_t f_ctime;
+ unsigned long f_blksize;
+ unsigned long f_blocks;
+};
+
+struct smb_dirent {
+ struct smb_fattr attr;
+
+ int f_pos;
+ int len;
+ __u8 name[SMB_MAXNAMELEN];
+};
+
+enum smb_conn_state {
+ CONN_VALID, /* everything's fine */
+ CONN_INVALID, /* Something went wrong, but did not
+ try to reconnect yet. */
+ CONN_RETRIED /* Tried a reconnection, but was refused */
+};
+
+/*
+ * The readdir cache size controls how many directory entries are cached.
+ */
+#define SMB_READDIR_CACHE_SIZE 64
+
+#define SMB_SUPER_MAGIC 0x517B
+
+#define SMB_SERVER(inode) (&(inode->i_sb->u.smbfs_sb))
+#define SMB_INOP(inode) (&(inode->u.smbfs_i))
+
+#define SMB_HEADER_LEN 37 /* includes everything up to, but not
+ * including smb_bcc */
+#define SMB_DEF_MAX_XMIT 32768
+#define SMB_INITIAL_PACKET_SIZE 4000
+
+/* Allocate max. 1 page */
+#define TRANS2_MAX_TRANSFER (4096-17)
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/smb_fs.h b/pfinet/linux-src/include/linux/smb_fs.h
new file mode 100644
index 00000000..11dfce7d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/smb_fs.h
@@ -0,0 +1,240 @@
+/*
+ * smb_fs.h
+ *
+ * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
+ * Copyright (C) 1997 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_SMB_FS_H
+#define _LINUX_SMB_FS_H
+
+#include <linux/smb.h>
+
+/*
+ * ioctl commands
+ */
+#define SMB_IOC_GETMOUNTUID _IOR('u', 1, __kernel_uid_t)
+#define SMB_IOC_NEWCONN _IOW('u', 2, struct smb_conn_opt)
+
+#ifdef __KERNEL__
+
+#include <asm/unaligned.h>
+
+#define WVAL(buf,pos) \
+(le16_to_cpu(get_unaligned((__u16 *)((__u8 *)(buf) + (pos)))))
+#define DVAL(buf,pos) \
+(le32_to_cpu(get_unaligned((__u32 *)((__u8 *)(buf) + (pos)))))
+#define WSET(buf,pos,val) \
+put_unaligned(cpu_to_le16((__u16)(val)), (__u16 *)((__u8 *)(buf) + (pos)))
+#define DSET(buf,pos,val) \
+put_unaligned(cpu_to_le32((__u32)(val)), (__u32 *)((__u8 *)(buf) + (pos)))
+
+/* where to find the base of the SMB packet proper */
+#define smb_base(buf) ((__u8 *)(((__u8 *)(buf))+4))
+
+#include <linux/vmalloc.h>
+
+#ifdef DEBUG_SMB_MALLOC
+
+extern int smb_malloced;
+extern int smb_current_vmalloced;
+
+static inline void *
+smb_vmalloc(unsigned int size)
+{
+ smb_malloced += 1;
+ smb_current_vmalloced += 1;
+ return vmalloc(size);
+}
+
+static inline void
+smb_vfree(void *obj)
+{
+ smb_current_vmalloced -= 1;
+ vfree(obj);
+}
+
+#else /* DEBUG_SMB_MALLOC */
+
+#define smb_kmalloc(s,p) kmalloc(s,p)
+#define smb_kfree_s(o,s) kfree_s(o,s)
+#define smb_vmalloc(s) vmalloc(s)
+#define smb_vfree(o) vfree(o)
+
+#endif /* DEBUG_SMB_MALLOC */
+
+/*
+ * Flags for the in-memory inode
+ */
+#define SMB_F_CACHEVALID 0x01 /* directory cache valid */
+#define SMB_F_LOCALWRITE 0x02 /* file modified locally */
+
+/*
+ * Bug fix flags
+ */
+#define SMB_FIX_WIN95 0x0001 /* Win 95 server */
+#define SMB_FIX_OLDATTR 0x0002 /* Use core getattr (Win 95 speedup) */
+#define SMB_FIX_DIRATTR 0x0004 /* Use find_first for getattr */
+
+
+/* NT1 protocol capability bits */
+#define SMB_CAP_RAW_MODE 0x0001
+#define SMB_CAP_MPX_MODE 0x0002
+#define SMB_CAP_UNICODE 0x0004
+#define SMB_CAP_LARGE_FILES 0x0008
+#define SMB_CAP_NT_SMBS 0x0010
+#define SMB_CAP_RPC_REMOTE_APIS 0x0020
+#define SMB_CAP_STATUS32 0x0040
+#define SMB_CAP_LEVEL_II_OPLOCKS 0x0080
+#define SMB_CAP_LOCK_AND_READ 0x0100
+#define SMB_CAP_NT_FIND 0x0200
+#define SMB_CAP_DFS 0x1000
+#define SMB_CAP_LARGE_READX 0x4000
+
+
+/* linux/fs/smbfs/mmap.c */
+int smb_mmap(struct file *, struct vm_area_struct *);
+
+/* linux/fs/smbfs/file.c */
+extern struct inode_operations smb_file_inode_operations;
+
+/* linux/fs/smbfs/dir.c */
+extern struct inode_operations smb_dir_inode_operations;
+void smb_renew_times(struct dentry *);
+
+/* linux/fs/smbfs/ioctl.c */
+int smb_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
+
+/* linux/fs/smbfs/inode.c */
+struct super_block *smb_read_super(struct super_block *, void *, int);
+void smb_get_inode_attr(struct inode *, struct smb_fattr *);
+void smb_invalidate_inodes(struct smb_sb_info *);
+int smb_revalidate_inode(struct dentry *);
+int smb_notify_change(struct dentry *, struct iattr *);
+unsigned long smb_invent_inos(unsigned long);
+struct inode *smb_iget(struct super_block *, struct smb_fattr *);
+extern int init_smb_fs(void);
+
+/* linux/fs/smbfs/proc.c */
+__u32 smb_len(unsigned char *);
+__u8 *smb_encode_smb_length(__u8 *, __u32);
+__u8 *smb_setup_header(struct smb_sb_info *, __u8, __u16, __u16);
+int smb_get_rsize(struct smb_sb_info *);
+int smb_get_wsize(struct smb_sb_info *);
+int smb_newconn(struct smb_sb_info *, struct smb_conn_opt *);
+int smb_errno(struct smb_sb_info *);
+int smb_close(struct inode *);
+void smb_close_dentry(struct dentry *);
+int smb_close_fileid(struct dentry *, __u16);
+int smb_open(struct dentry *, int);
+int smb_proc_read(struct dentry *, off_t, int, char *);
+int smb_proc_write(struct dentry *, off_t, int, const char *);
+int smb_proc_create(struct dentry *, __u16, time_t, __u16 *);
+int smb_proc_mv(struct dentry *, struct dentry *);
+int smb_proc_mkdir(struct dentry *);
+int smb_proc_rmdir(struct dentry *);
+int smb_proc_unlink(struct dentry *);
+int smb_proc_readdir(struct dentry *, int, void *);
+int smb_proc_getattr(struct dentry *, struct smb_fattr *);
+int smb_proc_setattr(struct dentry *, struct smb_fattr *);
+int smb_proc_settime(struct dentry *, struct smb_fattr *);
+int smb_proc_dskattr(struct super_block *, struct statfs *);
+int smb_proc_reconnect(struct smb_sb_info *);
+int smb_proc_connect(struct smb_sb_info *);
+int smb_proc_disconnect(struct smb_sb_info *);
+int smb_proc_trunc(struct smb_sb_info *, __u16, __u32);
+void smb_init_root_dirent(struct smb_sb_info *, struct smb_fattr *);
+
+static inline int
+smb_is_open(struct inode *i)
+{
+ return (i->u.smbfs_i.open == SMB_SERVER(i)->generation);
+}
+
+/* linux/fs/smbfs/sock.c */
+int smb_round_length(int);
+int smb_valid_socket(struct inode *);
+void smb_close_socket(struct smb_sb_info *);
+int smb_release(struct smb_sb_info *server);
+int smb_connect(struct smb_sb_info *server);
+int smb_request(struct smb_sb_info *server);
+int smb_request_read_raw(struct smb_sb_info *, unsigned char *, int);
+int smb_request_write_raw(struct smb_sb_info *, unsigned const char *, int);
+int smb_catch_keepalive(struct smb_sb_info *server);
+int smb_dont_catch_keepalive(struct smb_sb_info *server);
+int smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command,
+ int ldata, unsigned char *data,
+ int lparam, unsigned char *param,
+ int *lrdata, unsigned char **rdata,
+ int *lrparam, unsigned char **rparam);
+
+/* fs/smbfs/cache.c */
+
+/*
+ * The cache index describes the pages mapped starting
+ * at offset PAGE_SIZE. We keep only a minimal amount
+ * of information here.
+ */
+struct cache_index {
+ unsigned short num_entries;
+ unsigned short space;
+ struct cache_block * block;
+};
+
+#define NINDEX (PAGE_SIZE-64)/sizeof(struct cache_index)
+/*
+ * The cache head is mapped as the page at offset 0.
+ */
+struct cache_head {
+ int valid;
+ int status; /* error code or 0 */
+ int entries; /* total entries */
+ int pages; /* number of data pages */
+ int idx; /* index of current data page */
+ struct cache_index index[NINDEX];
+};
+
+/*
+ * An array of cache_entry structures holds information
+ * for each object in the cache_block.
+ */
+struct cache_entry {
+ ino_t ino;
+ unsigned short namelen;
+ unsigned short offset;
+};
+
+/*
+ * The cache blocks hold the actual data. The entry table grows up
+ * while the names grow down, and we have space until they meet.
+ */
+struct cache_block {
+ union {
+ struct cache_entry table[1];
+ char names[PAGE_SIZE];
+ } cb_data;
+};
+
+/*
+ * To return an entry, we can pass a reference to the
+ * name instead of having to copy it.
+ */
+struct cache_dirent {
+ ino_t ino;
+ unsigned long pos;
+ int len;
+ char * name;
+};
+
+struct cache_head * smb_get_dircache(struct dentry *);
+void smb_init_dircache(struct cache_head *);
+void smb_free_dircache(struct cache_head *);
+int smb_refill_dircache(struct cache_head *, struct dentry *);
+void smb_add_to_cache(struct cache_head *, struct cache_dirent *, off_t);
+int smb_find_in_cache(struct cache_head *, off_t, struct cache_dirent *);
+void smb_invalid_dir_cache(struct inode *);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SMB_FS_H */
diff --git a/pfinet/linux-src/include/linux/smb_fs_i.h b/pfinet/linux-src/include/linux/smb_fs_i.h
new file mode 100644
index 00000000..4aea02c3
--- /dev/null
+++ b/pfinet/linux-src/include/linux/smb_fs_i.h
@@ -0,0 +1,35 @@
+/*
+ * smb_fs_i.h
+ *
+ * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
+ * Copyright (C) 1997 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_SMB_FS_I
+#define _LINUX_SMB_FS_I
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+
+/*
+ * smb fs inode data (in memory only)
+ */
+struct smb_inode_info {
+
+ /*
+ * file handles are local to a connection. A file is open if
+ * (open == generation).
+ */
+ unsigned int open; /* open generation */
+ __u16 fileid; /* What id to handle a file with? */
+ __u16 attr; /* Attribute fields, DOS value */
+
+ __u16 access; /* Access mode */
+ __u16 cache_valid; /* dircache valid? */
+ unsigned long oldmtime; /* last time refreshed */
+ unsigned long closed; /* timestamp when closed */
+};
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/smb_fs_sb.h b/pfinet/linux-src/include/linux/smb_fs_sb.h
new file mode 100644
index 00000000..cedbb5ab
--- /dev/null
+++ b/pfinet/linux-src/include/linux/smb_fs_sb.h
@@ -0,0 +1,50 @@
+/*
+ * smb_fs_sb.h
+ *
+ * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
+ * Copyright (C) 1997 by Volker Lendecke
+ *
+ */
+
+#ifndef _SMB_FS_SB
+#define _SMB_FS_SB
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/smb.h>
+
+/* Get the server for the specified dentry */
+#define server_from_dentry(dentry) &dentry->d_sb->u.smbfs_sb
+#define SB_of(server) ((struct super_block *) ((char *)(server) - \
+ (unsigned long)(&((struct super_block *)0)->u.smbfs_sb)))
+
+struct smb_sb_info {
+ enum smb_conn_state state;
+ struct file * sock_file;
+
+ struct smb_mount_data *mnt;
+ unsigned char *temp_buf;
+
+ /* Connections are counted. Each time a new socket arrives,
+ * generation is incremented.
+ */
+ unsigned int generation;
+ pid_t conn_pid;
+ struct smb_conn_opt opt;
+
+ struct semaphore sem;
+ struct wait_queue * wait;
+
+ __u32 packet_size;
+ unsigned char * packet;
+ unsigned short rcls; /* The error codes we received */
+ unsigned short err;
+
+ /* We use our on data_ready callback, but need the original one */
+ void *data_ready;
+};
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/smb_mount.h b/pfinet/linux-src/include/linux/smb_mount.h
new file mode 100644
index 00000000..886d945d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/smb_mount.h
@@ -0,0 +1,25 @@
+/*
+ * smb_mount.h
+ *
+ * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
+ * Copyright (C) 1997 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_SMB_MOUNT_H
+#define _LINUX_SMB_MOUNT_H
+
+#include <linux/types.h>
+
+#define SMB_MOUNT_VERSION 6
+
+struct smb_mount_data {
+ int version;
+ __kernel_uid_t mounted_uid; /* Who may umount() this filesystem? */
+ __kernel_uid_t uid;
+ __kernel_gid_t gid;
+ __kernel_mode_t file_mode;
+ __kernel_mode_t dir_mode;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/smbno.h b/pfinet/linux-src/include/linux/smbno.h
new file mode 100644
index 00000000..0f25e026
--- /dev/null
+++ b/pfinet/linux-src/include/linux/smbno.h
@@ -0,0 +1,278 @@
+#ifndef _SMBNO_H_
+#define _SMBNO_H_
+
+/* these define the attribute byte as seen by DOS */
+#define aRONLY (1L<<0)
+#define aHIDDEN (1L<<1)
+#define aSYSTEM (1L<<2)
+#define aVOLID (1L<<3)
+#define aDIR (1L<<4)
+#define aARCH (1L<<5)
+
+/* error classes */
+#define SUCCESS 0 /* The request was successful. */
+#define ERRDOS 0x01 /* Error is from the core DOS operating system set. */
+#define ERRSRV 0x02 /* Error is generated by the server network file manager.*/
+#define ERRHRD 0x03 /* Error is an hardware error. */
+#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
+
+/* SMB X/Open error codes for the ERRdos error class */
+
+#define ERRbadfunc 1 /* Invalid function (or system call) */
+#define ERRbadfile 2 /* File not found (pathname error) */
+#define ERRbadpath 3 /* Directory not found */
+#define ERRnofids 4 /* Too many open files */
+#define ERRnoaccess 5 /* Access denied */
+#define ERRbadfid 6 /* Invalid fid */
+#define ERRbadmcb 7 /* Memory control blocks destroyed */
+#define ERRnomem 8 /* Out of memory */
+#define ERRbadmem 9 /* Invalid memory block address */
+#define ERRbadenv 10 /* Invalid environment */
+#define ERRbadformat 11 /* Invalid format */
+#define ERRbadaccess 12 /* Invalid open mode */
+#define ERRbaddata 13 /* Invalid data (only from ioctl call) */
+#define ERRres 14 /* reserved */
+#define ERRbaddrive 15 /* Invalid drive */
+#define ERRremcd 16 /* Attempt to delete current directory */
+#define ERRdiffdevice 17 /* rename/move across different filesystems */
+#define ERRnofiles 18 /* no more files found in file search */
+#define ERRbadshare 32 /* Share mode on file conflict with open mode */
+#define ERRlock 33 /* Lock request conflicts with existing lock */
+#define ERRfilexists 80 /* File in operation already exists */
+#define ERRundocumented1 123 /* Invalid name?? e.g. .tmp* */
+#define ERRbadpipe 230 /* Named pipe invalid */
+#define ERRpipebusy 231 /* All instances of pipe are busy */
+#define ERRpipeclosing 232 /* named pipe close in progress */
+#define ERRnotconnected 233 /* No process on other end of named pipe */
+#define ERRmoredata 234 /* More data to be returned */
+#define ERROR_EAS_DIDNT_FIT 275 /* Extended attributes didn't fit */
+#define ERROR_EAS_NOT_SUPPORTED 282 /* Extended attributes not supported */
+
+/* Error codes for the ERRSRV class */
+
+#define ERRerror 1 /* Non specific error code */
+#define ERRbadpw 2 /* Bad password */
+#define ERRbadtype 3 /* reserved */
+#define ERRaccess 4 /* No permissions to do the requested operation */
+#define ERRinvnid 5 /* tid invalid */
+#define ERRinvnetname 6 /* Invalid servername */
+#define ERRinvdevice 7 /* Invalid device */
+#define ERRqfull 49 /* Print queue full */
+#define ERRqtoobig 50 /* Queued item too big */
+#define ERRinvpfid 52 /* Invalid print file in smb_fid */
+#define ERRsmbcmd 64 /* Unrecognised command */
+#define ERRsrverror 65 /* smb server internal error */
+#define ERRfilespecs 67 /* fid and pathname invalid combination */
+#define ERRbadlink 68 /* reserved */
+#define ERRbadpermits 69 /* Access specified for a file is not valid */
+#define ERRbadpid 70 /* reserved */
+#define ERRsetattrmode 71 /* attribute mode invalid */
+#define ERRpaused 81 /* Message server paused */
+#define ERRmsgoff 82 /* Not receiving messages */
+#define ERRnoroom 83 /* No room for message */
+#define ERRrmuns 87 /* too many remote usernames */
+#define ERRtimeout 88 /* operation timed out */
+#define ERRnoresource 89 /* No resources currently available for request. */
+#define ERRtoomanyuids 90 /* too many userids */
+#define ERRbaduid 91 /* bad userid */
+#define ERRuseMPX 250 /* temporarily unable to use raw mode, use MPX mode */
+#define ERRuseSTD 251 /* temporarily unable to use raw mode, use std.mode */
+#define ERRcontMPX 252 /* resume MPX mode */
+#define ERRbadPW /* reserved */
+#define ERRnosupport 0xFFFF
+
+/* Error codes for the ERRHRD class */
+
+#define ERRnowrite 19 /* read only media */
+#define ERRbadunit 20 /* Unknown device */
+#define ERRnotready 21 /* Drive not ready */
+#define ERRbadcmd 22 /* Unknown command */
+#define ERRdata 23 /* Data (CRC) error */
+#define ERRbadreq 24 /* Bad request structure length */
+#define ERRseek 25
+#define ERRbadmedia 26
+#define ERRbadsector 27
+#define ERRnopaper 28
+#define ERRwrite 29 /* write fault */
+#define ERRread 30 /* read fault */
+#define ERRgeneral 31 /* General hardware failure */
+#define ERRwrongdisk 34
+#define ERRFCBunavail 35
+#define ERRsharebufexc 36 /* share buffer exceeded */
+#define ERRdiskfull 39
+
+/*
+ * Access modes when opening a file
+ */
+#define SMB_ACCMASK 0x0003
+#define SMB_O_RDONLY 0x0000
+#define SMB_O_WRONLY 0x0001
+#define SMB_O_RDWR 0x0002
+
+/* offsets into message for common items */
+#define smb_com 8
+#define smb_rcls 9
+#define smb_reh 10
+#define smb_err 11
+#define smb_flg 13
+#define smb_flg2 14
+#define smb_reb 13
+#define smb_tid 28
+#define smb_pid 30
+#define smb_uid 32
+#define smb_mid 34
+#define smb_wct 36
+#define smb_vwv 37
+#define smb_vwv0 37
+#define smb_vwv1 39
+#define smb_vwv2 41
+#define smb_vwv3 43
+#define smb_vwv4 45
+#define smb_vwv5 47
+#define smb_vwv6 49
+#define smb_vwv7 51
+#define smb_vwv8 53
+#define smb_vwv9 55
+#define smb_vwv10 57
+#define smb_vwv11 59
+#define smb_vwv12 61
+#define smb_vwv13 63
+#define smb_vwv14 65
+
+/* these are the trans2 sub fields for primary requests */
+#define smb_tpscnt smb_vwv0
+#define smb_tdscnt smb_vwv1
+#define smb_mprcnt smb_vwv2
+#define smb_mdrcnt smb_vwv3
+#define smb_msrcnt smb_vwv4
+#define smb_flags smb_vwv5
+#define smb_timeout smb_vwv6
+#define smb_pscnt smb_vwv9
+#define smb_psoff smb_vwv10
+#define smb_dscnt smb_vwv11
+#define smb_dsoff smb_vwv12
+#define smb_suwcnt smb_vwv13
+#define smb_setup smb_vwv14
+#define smb_setup0 smb_setup
+#define smb_setup1 (smb_setup+2)
+#define smb_setup2 (smb_setup+4)
+
+/* these are for the secondary requests */
+#define smb_spscnt smb_vwv2
+#define smb_spsoff smb_vwv3
+#define smb_spsdisp smb_vwv4
+#define smb_sdscnt smb_vwv5
+#define smb_sdsoff smb_vwv6
+#define smb_sdsdisp smb_vwv7
+#define smb_sfid smb_vwv8
+
+/* and these for responses */
+#define smb_tprcnt smb_vwv0
+#define smb_tdrcnt smb_vwv1
+#define smb_prcnt smb_vwv3
+#define smb_proff smb_vwv4
+#define smb_prdisp smb_vwv5
+#define smb_drcnt smb_vwv6
+#define smb_droff smb_vwv7
+#define smb_drdisp smb_vwv8
+
+/* the complete */
+#define SMBmkdir 0x00 /* create directory */
+#define SMBrmdir 0x01 /* delete directory */
+#define SMBopen 0x02 /* open file */
+#define SMBcreate 0x03 /* create file */
+#define SMBclose 0x04 /* close file */
+#define SMBflush 0x05 /* flush file */
+#define SMBunlink 0x06 /* delete file */
+#define SMBmv 0x07 /* rename file */
+#define SMBgetatr 0x08 /* get file attributes */
+#define SMBsetatr 0x09 /* set file attributes */
+#define SMBread 0x0A /* read from file */
+#define SMBwrite 0x0B /* write to file */
+#define SMBlock 0x0C /* lock byte range */
+#define SMBunlock 0x0D /* unlock byte range */
+#define SMBctemp 0x0E /* create temporary file */
+#define SMBmknew 0x0F /* make new file */
+#define SMBchkpth 0x10 /* check directory path */
+#define SMBexit 0x11 /* process exit */
+#define SMBlseek 0x12 /* seek */
+#define SMBtcon 0x70 /* tree connect */
+#define SMBtconX 0x75 /* tree connect and X*/
+#define SMBtdis 0x71 /* tree disconnect */
+#define SMBnegprot 0x72 /* negotiate protocol */
+#define SMBdskattr 0x80 /* get disk attributes */
+#define SMBsearch 0x81 /* search directory */
+#define SMBsplopen 0xC0 /* open print spool file */
+#define SMBsplwr 0xC1 /* write to print spool file */
+#define SMBsplclose 0xC2 /* close print spool file */
+#define SMBsplretq 0xC3 /* return print queue */
+#define SMBsends 0xD0 /* send single block message */
+#define SMBsendb 0xD1 /* send broadcast message */
+#define SMBfwdname 0xD2 /* forward user name */
+#define SMBcancelf 0xD3 /* cancel forward */
+#define SMBgetmac 0xD4 /* get machine name */
+#define SMBsendstrt 0xD5 /* send start of multi-block message */
+#define SMBsendend 0xD6 /* send end of multi-block message */
+#define SMBsendtxt 0xD7 /* send text of multi-block message */
+
+/* Core+ protocol */
+#define SMBlockread 0x13 /* Lock a range and read */
+#define SMBwriteunlock 0x14 /* Unlock a range then write */
+#define SMBreadbraw 0x1a /* read a block of data with no smb header */
+#define SMBwritebraw 0x1d /* write a block of data with no smb header */
+#define SMBwritec 0x20 /* secondary write request */
+#define SMBwriteclose 0x2c /* write a file then close it */
+
+/* dos extended protocol */
+#define SMBreadBraw 0x1A /* read block raw */
+#define SMBreadBmpx 0x1B /* read block multiplexed */
+#define SMBreadBs 0x1C /* read block (secondary response) */
+#define SMBwriteBraw 0x1D /* write block raw */
+#define SMBwriteBmpx 0x1E /* write block multiplexed */
+#define SMBwriteBs 0x1F /* write block (secondary request) */
+#define SMBwriteC 0x20 /* write complete response */
+#define SMBsetattrE 0x22 /* set file attributes expanded */
+#define SMBgetattrE 0x23 /* get file attributes expanded */
+#define SMBlockingX 0x24 /* lock/unlock byte ranges and X */
+#define SMBtrans 0x25 /* transaction - name, bytes in/out */
+#define SMBtranss 0x26 /* transaction (secondary request/response) */
+#define SMBioctl 0x27 /* IOCTL */
+#define SMBioctls 0x28 /* IOCTL (secondary request/response) */
+#define SMBcopy 0x29 /* copy */
+#define SMBmove 0x2A /* move */
+#define SMBecho 0x2B /* echo */
+#define SMBopenX 0x2D /* open and X */
+#define SMBreadX 0x2E /* read and X */
+#define SMBwriteX 0x2F /* write and X */
+#define SMBsesssetupX 0x73 /* Session Set Up & X (including User Logon) */
+#define SMBtconX 0x75 /* tree connect and X */
+#define SMBffirst 0x82 /* find first */
+#define SMBfunique 0x83 /* find unique */
+#define SMBfclose 0x84 /* find close */
+#define SMBinvalid 0xFE /* invalid command */
+
+
+/* Extended 2.0 protocol */
+#define SMBtrans2 0x32 /* TRANS2 protocol set */
+#define SMBtranss2 0x33 /* TRANS2 protocol set, secondary command */
+#define SMBfindclose 0x34 /* Terminate a TRANSACT2_FINDFIRST */
+#define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
+#define SMBulogoffX 0x74 /* user logoff */
+
+/* these are the TRANS2 sub commands */
+#define TRANSACT2_OPEN 0
+#define TRANSACT2_FINDFIRST 1
+#define TRANSACT2_FINDNEXT 2
+#define TRANSACT2_QFSINFO 3
+#define TRANSACT2_SETFSINFO 4
+#define TRANSACT2_QPATHINFO 5
+#define TRANSACT2_SETPATHINFO 6
+#define TRANSACT2_QFILEINFO 7
+#define TRANSACT2_SETFILEINFO 8
+#define TRANSACT2_FSCTL 9
+#define TRANSACT2_IOCTL 10
+#define TRANSACT2_FINDNOTIFYFIRST 11
+#define TRANSACT2_FINDNOTIFYNEXT 12
+#define TRANSACT2_MKDIR 13
+
+#endif /* _SMBNO_H_ */
diff --git a/pfinet/linux-src/include/linux/smp.h b/pfinet/linux-src/include/linux/smp.h
new file mode 100644
index 00000000..eae12907
--- /dev/null
+++ b/pfinet/linux-src/include/linux/smp.h
@@ -0,0 +1,86 @@
+#ifndef __LINUX_SMP_H
+#define __LINUX_SMP_H
+
+/*
+ * Generic SMP support
+ * Alan Cox. <alan@redhat.com>
+ */
+
+#ifdef __SMP__
+
+#include <asm/smp.h>
+
+/*
+ * main cross-CPU interfaces, handles INIT, TLB flush, STOP, etc.
+ * (defined in asm header):
+ */
+
+/*
+ * stops all CPUs but the current one:
+ */
+extern void smp_send_stop(void);
+
+/*
+ * sends a 'reschedule' event to another CPU:
+ */
+extern void FASTCALL(smp_send_reschedule(int cpu));
+
+
+/*
+ * Boot processor call to load the other CPU's
+ */
+extern void smp_boot_cpus(void);
+
+/*
+ * Processor call in. Must hold processors until ..
+ */
+extern void smp_callin(void);
+
+/*
+ * Multiprocessors may now schedule
+ */
+extern void smp_commence(void);
+
+/*
+ * Call a function on all other processors
+ */
+extern int smp_call_function (void (*func) (void *info), void *info,
+ int retry, int wait);
+
+/*
+ * True once the per process idle is forked
+ */
+extern int smp_threads_ready;
+
+extern int smp_num_cpus;
+
+extern volatile unsigned long smp_msg_data;
+extern volatile int smp_src_cpu;
+extern volatile int smp_msg_id;
+
+#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */
+#define MSG_ALL 0x8001
+
+#define MSG_INVALIDATE_TLB 0x0001 /* Remote processor TLB invalidate */
+#define MSG_STOP_CPU 0x0002 /* Sent to shut down slave CPU's
+ * when rebooting
+ */
+#define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU*/
+#define MSG_CALL_FUNCTION 0x0004 /* Call function on all other CPUs */
+
+#else
+
+/*
+ * These macros fold the SMP functionality into a single CPU system
+ */
+
+#define smp_num_cpus 1
+#define smp_processor_id() 0
+#define hard_smp_processor_id() 0
+#define smp_threads_ready 1
+#define kernel_lock()
+#define cpu_logical_map(cpu) 0
+#define smp_call_function(func,info,retry,wait)
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/smp_lock.h b/pfinet/linux-src/include/linux/smp_lock.h
new file mode 100644
index 00000000..4583e2f5
--- /dev/null
+++ b/pfinet/linux-src/include/linux/smp_lock.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_SMPLOCK_H
+#define __LINUX_SMPLOCK_H
+
+#ifndef __SMP__
+
+#define lock_kernel() do { } while(0)
+#define unlock_kernel() do { } while(0)
+#define release_kernel_lock(task, cpu) do { } while(0)
+#define reacquire_kernel_lock(task) do { } while(0)
+
+#else
+
+#include <asm/smplock.h>
+
+#endif /* __SMP__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/socket.h b/pfinet/linux-src/include/linux/socket.h
new file mode 100644
index 00000000..d681aa5b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/socket.h
@@ -0,0 +1,280 @@
+#ifndef _LINUX_SOCKET_H
+#define _LINUX_SOCKET_H
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#include <asm/socket.h> /* arch-dependent defines */
+#include <linux/sockios.h> /* the SIOCxxx I/O controls */
+#include <linux/uio.h> /* iovec support */
+#include <linux/types.h> /* pid_t */
+
+typedef unsigned short sa_family_t;
+
+/*
+ * 1003.1g requires sa_family_t and that sa_data is char.
+ */
+
+struct sockaddr {
+ sa_family_t sa_family; /* address family, AF_xxx */
+ char sa_data[14]; /* 14 bytes of protocol address */
+};
+
+struct linger {
+ int l_onoff; /* Linger active */
+ int l_linger; /* How long to linger for */
+};
+
+/*
+ * As we do 4.4BSD message passing we use a 4.4BSD message passing
+ * system, not 4.3. Thus msg_accrights(len) are now missing. They
+ * belong in an obscure libc emulation or the bin.
+ */
+
+struct msghdr {
+ void * msg_name; /* Socket name */
+ int msg_namelen; /* Length of name */
+ struct iovec * msg_iov; /* Data blocks */
+ __kernel_size_t msg_iovlen; /* Number of blocks */
+ void * msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
+ __kernel_size_t msg_controllen; /* Length of cmsg list */
+ unsigned msg_flags;
+};
+
+/*
+ * POSIX 1003.1g - ancillary data object information
+ * Ancillary data consits of a sequence of pairs of
+ * (cmsghdr, cmsg_data[])
+ */
+
+struct cmsghdr {
+ __kernel_size_t cmsg_len; /* data byte count, including hdr */
+ int cmsg_level; /* originating protocol */
+ int cmsg_type; /* protocol-specific type */
+};
+
+/*
+ * Ancilliary data object information MACROS
+ * Table 5-14 of POSIX 1003.1g
+ */
+
+#define __CMSG_NXTHDR(ctl, len, cmsg) __cmsg_nxthdr((ctl),(len),(cmsg))
+#define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg))
+
+#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
+
+#define CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
+#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
+#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
+
+#define __CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr) ? \
+ (struct cmsghdr *)(ctl) : \
+ (struct cmsghdr *)NULL)
+#define CMSG_FIRSTHDR(msg) __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+/*
+ * This mess will go away with glibc
+ */
+
+#ifdef __KERNEL__
+#define __KINLINE extern __inline__
+#elif defined(__GNUC__)
+#define __KINLINE static __inline__
+#elif defined(__cplusplus)
+#define __KINLINE static inline
+#else
+#define __KINLINE static
+#endif
+
+
+/*
+ * Get the next cmsg header
+ *
+ * PLEASE, do not touch this function. If you think, that it is
+ * incorrect, grep kernel sources and think about consequences
+ * before trying to improve it.
+ *
+ * Now it always returns valid, not truncated ancillary object
+ * HEADER. But caller still MUST check, that cmsg->cmsg_len is
+ * inside range, given by msg->msg_controllen before using
+ * ansillary object DATA. --ANK (980731)
+ */
+
+__KINLINE struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size,
+ struct cmsghdr *__cmsg)
+{
+ struct cmsghdr * __ptr;
+
+ __ptr = (struct cmsghdr*)(((unsigned char *) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len));
+ if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+ return NULL;
+
+ return __ptr;
+}
+
+__KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__cmsg)
+{
+ return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg);
+}
+
+/* "Socket"-level control message types: */
+
+#define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */
+#define SCM_CREDENTIALS 0x02 /* rw: struct ucred */
+#define SCM_CONNECT 0x03 /* rw: struct scm_connect */
+
+struct ucred {
+ __u32 pid;
+ __u32 uid;
+ __u32 gid;
+};
+
+
+/* Supported address families. */
+#define AF_UNSPEC 0
+#define AF_UNIX 1 /* Unix domain sockets */
+#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
+#define AF_INET 2 /* Internet IP Protocol */
+#define AF_AX25 3 /* Amateur Radio AX.25 */
+#define AF_IPX 4 /* Novell IPX */
+#define AF_APPLETALK 5 /* AppleTalk DDP */
+#define AF_NETROM 6 /* Amateur Radio NET/ROM */
+#define AF_BRIDGE 7 /* Multiprotocol bridge */
+#define AF_ATMPVC 8 /* ATM PVCs */
+#define AF_X25 9 /* Reserved for X.25 project */
+#define AF_INET6 10 /* IP version 6 */
+#define AF_ROSE 11 /* Amateur Radio X.25 PLP */
+#define AF_DECnet 12 /* Reserved for DECnet project */
+#define AF_NETBEUI 13 /* Reserved for 802.2LLC project*/
+#define AF_SECURITY 14 /* Security callback pseudo AF */
+#define AF_KEY 15 /* PF_KEY key management API */
+#define AF_NETLINK 16
+#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */
+#define AF_PACKET 17 /* Packet family */
+#define AF_ASH 18 /* Ash */
+#define AF_ECONET 19 /* Acorn Econet */
+#define AF_ATMSVC 20 /* ATM SVCs */
+#define AF_SNA 22 /* Linux SNA Project (nutters!) */
+#define AF_IRDA 23 /* IRDA sockets */
+#define AF_MAX 32 /* For now.. */
+
+/* Protocol families, same as address families. */
+#define PF_UNSPEC AF_UNSPEC
+#define PF_UNIX AF_UNIX
+#define PF_LOCAL AF_LOCAL
+#define PF_INET AF_INET
+#define PF_AX25 AF_AX25
+#define PF_IPX AF_IPX
+#define PF_APPLETALK AF_APPLETALK
+#define PF_NETROM AF_NETROM
+#define PF_BRIDGE AF_BRIDGE
+#define PF_ATMPVC AF_ATMPVC
+#define PF_X25 AF_X25
+#define PF_INET6 AF_INET6
+#define PF_ROSE AF_ROSE
+#define PF_DECnet AF_DECnet
+#define PF_NETBEUI AF_NETBEUI
+#define PF_SECURITY AF_SECURITY
+#define PF_KEY AF_KEY
+#define PF_NETLINK AF_NETLINK
+#define PF_ROUTE AF_ROUTE
+#define PF_PACKET AF_PACKET
+#define PF_ASH AF_ASH
+#define PF_ECONET AF_ECONET
+#define PF_ATMSVC AF_ATMSVC
+#define PF_SNA AF_SNA
+#define PF_IRDA AF_IRDA
+
+#define PF_MAX AF_MAX
+
+/* Maximum queue length specifiable by listen. */
+#define SOMAXCONN 128
+
+/* Flags we can use with send/ and recv.
+ Added those for 1003.1g not all are supported yet
+ */
+
+#define MSG_OOB 1
+#define MSG_PEEK 2
+#define MSG_DONTROUTE 4
+#define MSG_TRYHARD 4 /* Synonym for MSG_DONTROUTE for DECnet */
+#define MSG_CTRUNC 8
+#define MSG_PROXY 0x10 /* Supply or ask second address. */
+#define MSG_TRUNC 0x20
+#define MSG_DONTWAIT 0x40 /* Nonblocking io */
+#define MSG_EOR 0x80 /* End of record */
+#define MSG_WAITALL 0x100 /* Wait for a full request */
+#define MSG_FIN 0x200
+#define MSG_SYN 0x400
+#define MSG_URG 0x800
+#define MSG_RST 0x1000
+#define MSG_ERRQUEUE 0x2000
+#define MSG_NOSIGNAL 0x4000
+
+#define MSG_CTLIGNORE 0x80000000
+
+#define MSG_EOF MSG_FIN
+#define MSG_CTLFLAGS (MSG_OOB|MSG_URG|MSG_FIN|MSG_SYN|MSG_RST)
+
+
+/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
+#define SOL_IP 0
+/* #define SOL_ICMP 1 No-no-no! Due to Linux :-) we cannot use SOL_ICMP=1 */
+#define SOL_TCP 6
+#define SOL_UDP 17
+#define SOL_IPV6 41
+#define SOL_ICMPV6 58
+#define SOL_RAW 255
+#define SOL_IPX 256
+#define SOL_AX25 257
+#define SOL_ATALK 258
+#define SOL_NETROM 259
+#define SOL_ROSE 260
+#define SOL_DECNET 261
+#define SOL_X25 262
+#define SOL_PACKET 263
+#define SOL_ATM 264 /* ATM layer (cell level) */
+#define SOL_AAL 265 /* ATM Adaption Layer (packet level) */
+#define SOL_IRDA 266
+
+/* IPX options */
+#define IPX_TYPE 1
+
+/* TCP options - this way around because someone left a set in the c library includes */
+#define TCP_NODELAY 1
+#define TCP_MAXSEG 2
+#define TCP_CORK 3 /* Linux specific (for use with sendfile) */
+
+#ifdef __KERNEL__
+extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
+extern int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov,
+ int offset, int len);
+extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
+ struct iovec *iov,
+ int offset,
+ unsigned int len, int *csump);
+
+extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
+extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
+extern void memcpy_tokerneliovec(struct iovec *iov, unsigned char *kdata, int len);
+extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
+extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
+extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
+#endif
+#endif /* not kernel and not glibc */
+
+#if !defined(__KERNEL__) && (!defined(__GLIBC__) || (__GLIBC__ < 2))
+
+/* Socket types for libc5 compatibility -- KTK */
+
+#define SOCK_STREAM 1 /* stream (connection) socket */
+#define SOCK_DGRAM 2 /* datagram (conn.less) socket */
+#define SOCK_RAW 3 /* raw socket */
+#define SOCK_RDM 4 /* reliably-delivered message */
+#define SOCK_SEQPACKET 5 /* sequential packet socket */
+#define SOCK_PACKET 10 /* linux specific way of */
+ /* getting packets at the dev */
+ /* level. For writing rarp and */
+ /* other similar things on the */
+ /* user level. */
+#endif /* libc<=5 && !kernel */
+#endif /* _LINUX_SOCKET_H */
diff --git a/pfinet/linux-src/include/linux/sockios.h b/pfinet/linux-src/include/linux/sockios.h
new file mode 100644
index 00000000..995e43e9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sockios.h
@@ -0,0 +1,109 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions of the socket-level I/O control calls.
+ *
+ * Version: @(#)sockios.h 1.0.2 03/09/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_SOCKIOS_H
+#define _LINUX_SOCKIOS_H
+
+#include <asm/sockios.h>
+
+/* Routing table calls. */
+#define SIOCADDRT 0x890B /* add routing table entry */
+#define SIOCDELRT 0x890C /* delete routing table entry */
+#define SIOCRTMSG 0x890D /* call to routing system */
+
+/* Socket configuration controls. */
+#define SIOCGIFNAME 0x8910 /* get iface name */
+#define SIOCSIFLINK 0x8911 /* set iface channel */
+#define SIOCGIFCONF 0x8912 /* get iface list */
+#define SIOCGIFFLAGS 0x8913 /* get flags */
+#define SIOCSIFFLAGS 0x8914 /* set flags */
+#define SIOCGIFADDR 0x8915 /* get PA address */
+#define SIOCSIFADDR 0x8916 /* set PA address */
+#define SIOCGIFDSTADDR 0x8917 /* get remote PA address */
+#define SIOCSIFDSTADDR 0x8918 /* set remote PA address */
+#define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */
+#define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */
+#define SIOCGIFNETMASK 0x891b /* get network PA mask */
+#define SIOCSIFNETMASK 0x891c /* set network PA mask */
+#define SIOCGIFMETRIC 0x891d /* get metric */
+#define SIOCSIFMETRIC 0x891e /* set metric */
+#define SIOCGIFMEM 0x891f /* get memory address (BSD) */
+#define SIOCSIFMEM 0x8920 /* set memory address (BSD) */
+#define SIOCGIFMTU 0x8921 /* get MTU size */
+#define SIOCSIFMTU 0x8922 /* set MTU size */
+#define SIOCSIFNAME 0x8923 /* set interface name */
+#define SIOCSIFHWADDR 0x8924 /* set hardware address */
+#define SIOCGIFENCAP 0x8925 /* get/set encapsulations */
+#define SIOCSIFENCAP 0x8926
+#define SIOCGIFHWADDR 0x8927 /* Get hardware address */
+#define SIOCGIFSLAVE 0x8929 /* Driver slaving support */
+#define SIOCSIFSLAVE 0x8930
+#define SIOCADDMULTI 0x8931 /* Multicast address lists */
+#define SIOCDELMULTI 0x8932
+#define SIOCGIFINDEX 0x8933 /* name -> if_index mapping */
+#define SIOGIFINDEX SIOCGIFINDEX /* misprint compatibility :-) */
+#define SIOCSIFPFLAGS 0x8934 /* set/get extended flags set */
+#define SIOCGIFPFLAGS 0x8935
+#define SIOCDIFADDR 0x8936 /* delete PA address */
+#define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */
+#define SIOCGIFCOUNT 0x8938 /* get number of devices */
+
+#define SIOCGIFBR 0x8940 /* Bridging support */
+#define SIOCSIFBR 0x8941 /* Set bridging options */
+
+#define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */
+#define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */
+
+
+/* ARP cache control calls. */
+ /* 0x8950 - 0x8952 * obsolete calls, don't re-use */
+#define SIOCDARP 0x8953 /* delete ARP table entry */
+#define SIOCGARP 0x8954 /* get ARP table entry */
+#define SIOCSARP 0x8955 /* set ARP table entry */
+
+/* RARP cache control calls. */
+#define SIOCDRARP 0x8960 /* delete RARP table entry */
+#define SIOCGRARP 0x8961 /* get RARP table entry */
+#define SIOCSRARP 0x8962 /* set RARP table entry */
+
+/* Driver configuration calls */
+
+#define SIOCGIFMAP 0x8970 /* Get device parameters */
+#define SIOCSIFMAP 0x8971 /* Set device parameters */
+
+/* DLCI configuration calls */
+
+#define SIOCADDDLCI 0x8980 /* Create new DLCI device */
+#define SIOCDELDLCI 0x8981 /* Delete DLCI device */
+
+/* Device private ioctl calls */
+
+/*
+ * These 16 ioctls are available to devices via the do_ioctl() device
+ * vector. Each device should include this file and redefine these names
+ * as their own. Because these are device dependent it is a good idea
+ * _NOT_ to issue them to random objects and hope.
+ */
+
+#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */
+
+/*
+ * These 16 ioctl calls are protocol private
+ */
+
+#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */
+#endif /* _LINUX_SOCKIOS_H */
diff --git a/pfinet/linux-src/include/linux/sound.h b/pfinet/linux-src/include/linux/sound.h
new file mode 100644
index 00000000..4921b90e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sound.h
@@ -0,0 +1,15 @@
+/*
+ * Sound core interface functions
+ */
+
+extern int register_sound_special(struct file_operations *fops, int unit);
+extern int register_sound_mixer(struct file_operations *fops, int dev);
+extern int register_sound_midi(struct file_operations *fops, int dev);
+extern int register_sound_dsp(struct file_operations *fops, int dev);
+extern int register_sound_synth(struct file_operations *fops, int dev);
+
+extern void unregister_sound_special(int unit);
+extern void unregister_sound_mixer(int unit);
+extern void unregister_sound_midi(int unit);
+extern void unregister_sound_dsp(int unit);
+extern void unregister_sound_synth(int unit);
diff --git a/pfinet/linux-src/include/linux/soundcard.h b/pfinet/linux-src/include/linux/soundcard.h
new file mode 100644
index 00000000..2d5128dc
--- /dev/null
+++ b/pfinet/linux-src/include/linux/soundcard.h
@@ -0,0 +1,1270 @@
+#ifndef SOUNDCARD_H
+#define SOUNDCARD_H
+/*
+ * Copyright by Hannu Savolainen 1993-1997
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * OSS interface version. With versions earlier than 3.6 this value is
+ * an integer with value less than 361. In versions 3.6 and later
+ * it's a six digit hexadecimal value. For example value
+ * of 0x030600 represents OSS version 3.6.0.
+ * Use ioctl(fd, OSS_GETVERSION, &int) to get the version number of
+ * the currently active driver.
+ */
+#define SOUND_VERSION 0x030802
+#define OPEN_SOUND_SYSTEM
+
+/* In Linux we need to be prepared for cross compiling */
+#include <linux/ioctl.h>
+
+/*
+ * Supported card ID numbers (Should be somewhere else?)
+ */
+
+#define SNDCARD_ADLIB 1
+#define SNDCARD_SB 2
+#define SNDCARD_PAS 3
+#define SNDCARD_GUS 4
+#define SNDCARD_MPU401 5
+#define SNDCARD_SB16 6
+#define SNDCARD_SB16MIDI 7
+#define SNDCARD_UART6850 8
+#define SNDCARD_GUS16 9
+#define SNDCARD_MSS 10
+#define SNDCARD_PSS 11
+#define SNDCARD_SSCAPE 12
+#define SNDCARD_PSS_MPU 13
+#define SNDCARD_PSS_MSS 14
+#define SNDCARD_SSCAPE_MSS 15
+#define SNDCARD_TRXPRO 16
+#define SNDCARD_TRXPRO_SB 17
+#define SNDCARD_TRXPRO_MPU 18
+#define SNDCARD_MAD16 19
+#define SNDCARD_MAD16_MPU 20
+#define SNDCARD_CS4232 21
+#define SNDCARD_CS4232_MPU 22
+#define SNDCARD_MAUI 23
+#define SNDCARD_PSEUDO_MSS 24
+#define SNDCARD_GUSPNP 25
+#define SNDCARD_UART401 26
+/* Sound card numbers 27 to N are reserved. Don't add more numbers here. */
+
+/***********************************
+ * IOCTL Commands for /dev/sequencer
+ */
+
+#ifndef _SIOWR
+#if defined(_IOWR) && (defined(_AIX) || (!defined(sun) && !defined(sparc) && !defined(__INCioctlh) && !defined(__Lynx__)))
+/* Use already defined ioctl defines if they exist (except with Sun) */
+#define SIOCPARM_MASK IOCPARM_MASK
+#define SIOC_VOID IOC_VOID
+#define SIOC_OUT IOC_OUT
+#define SIOC_IN IOC_IN
+#define SIOC_INOUT IOC_INOUT
+#define _SIOC_SIZE _IOC_SIZE
+#define _SIOC_DIR _IOC_DIR
+#define _SIOC_NONE _IOC_NONE
+#define _SIOC_READ _IOC_READ
+#define _SIOC_WRITE _IOC_WRITE
+#define _SIO _IO
+#define _SIOR _IOR
+#define _SIOW _IOW
+#define _SIOWR _IOWR
+#else
+
+/* Ioctl's have the command encoded in the lower word,
+ * and the size of any in or out parameters in the upper
+ * word. The high 2 bits of the upper word are used
+ * to encode the in/out status of the parameter; for now
+ * we restrict parameters to at most 8191 bytes.
+ */
+/* #define SIOCTYPE (0xff<<8) */
+#define SIOCPARM_MASK 0x1fff /* parameters must be < 8192 bytes */
+#define SIOC_VOID 0x00000000 /* no parameters */
+#define SIOC_OUT 0x20000000 /* copy out parameters */
+#define SIOC_IN 0x40000000 /* copy in parameters */
+#define SIOC_INOUT (SIOC_IN|SIOC_OUT)
+/* the 0x20000000 is so we can distinguish new ioctl's from old */
+#define _SIO(x,y) ((int)(SIOC_VOID|(x<<8)|y))
+#define _SIOR(x,y,t) ((int)(SIOC_OUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#define _SIOW(x,y,t) ((int)(SIOC_IN|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+/* this should be _SIORW, but stdio got there first */
+#define _SIOWR(x,y,t) ((int)(SIOC_INOUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#define _SIOC_SIZE(x) ((x>>16)&SIOCPARM_MASK)
+#define _SIOC_DIR(x) (x & 0xf0000000)
+#define _SIOC_NONE SIOC_VOID
+#define _SIOC_READ SIOC_OUT
+#define _SIOC_WRITE SIOC_IN
+# endif /* _IOWR */
+#endif /* !_SIOWR */
+
+#define SNDCTL_SEQ_RESET _SIO ('Q', 0)
+#define SNDCTL_SEQ_SYNC _SIO ('Q', 1)
+#define SNDCTL_SYNTH_INFO _SIOWR('Q', 2, struct synth_info)
+#define SNDCTL_SEQ_CTRLRATE _SIOWR('Q', 3, int) /* Set/get timer resolution (HZ) */
+#define SNDCTL_SEQ_GETOUTCOUNT _SIOR ('Q', 4, int)
+#define SNDCTL_SEQ_GETINCOUNT _SIOR ('Q', 5, int)
+#define SNDCTL_SEQ_PERCMODE _SIOW ('Q', 6, int)
+#define SNDCTL_FM_LOAD_INSTR _SIOW ('Q', 7, struct sbi_instrument) /* Obsolete. Don't use!!!!!! */
+#define SNDCTL_SEQ_TESTMIDI _SIOW ('Q', 8, int)
+#define SNDCTL_SEQ_RESETSAMPLES _SIOW ('Q', 9, int)
+#define SNDCTL_SEQ_NRSYNTHS _SIOR ('Q',10, int)
+#define SNDCTL_SEQ_NRMIDIS _SIOR ('Q',11, int)
+#define SNDCTL_MIDI_INFO _SIOWR('Q',12, struct midi_info)
+#define SNDCTL_SEQ_THRESHOLD _SIOW ('Q',13, int)
+#define SNDCTL_SYNTH_MEMAVL _SIOWR('Q',14, int) /* in=dev#, out=memsize */
+#define SNDCTL_FM_4OP_ENABLE _SIOW ('Q',15, int) /* in=dev# */
+#define SNDCTL_SEQ_PANIC _SIO ('Q',17)
+#define SNDCTL_SEQ_OUTOFBAND _SIOW ('Q',18, struct seq_event_rec)
+#define SNDCTL_SEQ_GETTIME _SIOR ('Q',19, int)
+#define SNDCTL_SYNTH_ID _SIOWR('Q',20, struct synth_info)
+#define SNDCTL_SYNTH_CONTROL _SIOWR('Q',21, struct synth_control)
+#define SNDCTL_SYNTH_REMOVESAMPLE _SIOWR('Q',22, struct remove_sample)
+
+typedef struct synth_control
+{
+ int devno; /* Synthesizer # */
+ char data[4000]; /* Device spesific command/data record */
+}synth_control;
+
+typedef struct remove_sample
+{
+ int devno; /* Synthesizer # */
+ int bankno; /* MIDI bank # (0=General MIDI) */
+ int instrno; /* MIDI instrument number */
+} remove_sample;
+
+typedef struct seq_event_rec {
+ unsigned char arr[8];
+} seq_event_rec;
+
+#define SNDCTL_TMR_TIMEBASE _SIOWR('T', 1, int)
+#define SNDCTL_TMR_START _SIO ('T', 2)
+#define SNDCTL_TMR_STOP _SIO ('T', 3)
+#define SNDCTL_TMR_CONTINUE _SIO ('T', 4)
+#define SNDCTL_TMR_TEMPO _SIOWR('T', 5, int)
+#define SNDCTL_TMR_SOURCE _SIOWR('T', 6, int)
+# define TMR_INTERNAL 0x00000001
+# define TMR_EXTERNAL 0x00000002
+# define TMR_MODE_MIDI 0x00000010
+# define TMR_MODE_FSK 0x00000020
+# define TMR_MODE_CLS 0x00000040
+# define TMR_MODE_SMPTE 0x00000080
+#define SNDCTL_TMR_METRONOME _SIOW ('T', 7, int)
+#define SNDCTL_TMR_SELECT _SIOW ('T', 8, int)
+
+/*
+ * Some big endian/little endian handling macros
+ */
+
+#if defined(_AIX) || defined(AIX) || defined(sparc) || defined(HPPA) || defined(PPC)
+/* Big endian machines */
+# define _PATCHKEY(id) (0xfd00|id)
+# define AFMT_S16_NE AFMT_S16_BE
+#else
+# define _PATCHKEY(id) ((id<<8)|0xfd)
+# define AFMT_S16_NE AFMT_S16_LE
+#endif
+
+/*
+ * Sample loading mechanism for internal synthesizers (/dev/sequencer)
+ * The following patch_info structure has been designed to support
+ * Gravis UltraSound. It tries to be universal format for uploading
+ * sample based patches but is probably too limited.
+ *
+ * (PBD) As Hannu guessed, the GUS structure is too limited for
+ * the WaveFront, but this is the right place for a constant definition.
+ */
+
+struct patch_info {
+ unsigned short key; /* Use WAVE_PATCH here */
+#define WAVE_PATCH _PATCHKEY(0x04)
+#define GUS_PATCH WAVE_PATCH
+#define WAVEFRONT_PATCH _PATCHKEY(0x06)
+
+ short device_no; /* Synthesizer number */
+ short instr_no; /* Midi pgm# */
+
+ unsigned int mode;
+/*
+ * The least significant byte has the same format than the GUS .PAT
+ * files
+ */
+#define WAVE_16_BITS 0x01 /* bit 0 = 8 or 16 bit wave data. */
+#define WAVE_UNSIGNED 0x02 /* bit 1 = Signed - Unsigned data. */
+#define WAVE_LOOPING 0x04 /* bit 2 = looping enabled-1. */
+#define WAVE_BIDIR_LOOP 0x08 /* bit 3 = Set is bidirectional looping. */
+#define WAVE_LOOP_BACK 0x10 /* bit 4 = Set is looping backward. */
+#define WAVE_SUSTAIN_ON 0x20 /* bit 5 = Turn sustaining on. (Env. pts. 3)*/
+#define WAVE_ENVELOPES 0x40 /* bit 6 = Enable envelopes - 1 */
+#define WAVE_FAST_RELEASE 0x80 /* bit 7 = Shut off immediately after note off */
+ /* (use the env_rate/env_offs fields). */
+/* Linux specific bits */
+#define WAVE_VIBRATO 0x00010000 /* The vibrato info is valid */
+#define WAVE_TREMOLO 0x00020000 /* The tremolo info is valid */
+#define WAVE_SCALE 0x00040000 /* The scaling info is valid */
+#define WAVE_FRACTIONS 0x00080000 /* Fraction information is valid */
+/* Reserved bits */
+#define WAVE_ROM 0x40000000 /* For future use */
+#define WAVE_MULAW 0x20000000 /* For future use */
+/* Other bits must be zeroed */
+
+ int len; /* Size of the wave data in bytes */
+ int loop_start, loop_end; /* Byte offsets from the beginning */
+
+/*
+ * The base_freq and base_note fields are used when computing the
+ * playback speed for a note. The base_note defines the tone frequency
+ * which is heard if the sample is played using the base_freq as the
+ * playback speed.
+ *
+ * The low_note and high_note fields define the minimum and maximum note
+ * frequencies for which this sample is valid. It is possible to define
+ * more than one samples for an instrument number at the same time. The
+ * low_note and high_note fields are used to select the most suitable one.
+ *
+ * The fields base_note, high_note and low_note should contain
+ * the note frequency multiplied by 1000. For example value for the
+ * middle A is 440*1000.
+ */
+
+ unsigned int base_freq;
+ unsigned int base_note;
+ unsigned int high_note;
+ unsigned int low_note;
+ int panning; /* -128=left, 127=right */
+ int detuning;
+
+/* New fields introduced in version 1.99.5 */
+
+ /* Envelope. Enabled by mode bit WAVE_ENVELOPES */
+ unsigned char env_rate[ 6 ]; /* GUS HW ramping rate */
+ unsigned char env_offset[ 6 ]; /* 255 == 100% */
+
+ /*
+ * The tremolo, vibrato and scale info are not supported yet.
+ * Enable by setting the mode bits WAVE_TREMOLO, WAVE_VIBRATO or
+ * WAVE_SCALE
+ */
+
+ unsigned char tremolo_sweep;
+ unsigned char tremolo_rate;
+ unsigned char tremolo_depth;
+
+ unsigned char vibrato_sweep;
+ unsigned char vibrato_rate;
+ unsigned char vibrato_depth;
+
+ int scale_frequency;
+ unsigned int scale_factor; /* from 0 to 2048 or 0 to 2 */
+
+ int volume;
+ int fractions;
+ int reserved1;
+ int spare[2];
+ char data[1]; /* The waveform data starts here */
+ };
+
+struct sysex_info {
+ short key; /* Use SYSEX_PATCH or MAUI_PATCH here */
+#define SYSEX_PATCH _PATCHKEY(0x05)
+#define MAUI_PATCH _PATCHKEY(0x06)
+ short device_no; /* Synthesizer number */
+ int len; /* Size of the sysex data in bytes */
+ unsigned char data[1]; /* Sysex data starts here */
+ };
+
+/*
+ * /dev/sequencer input events.
+ *
+ * The data written to the /dev/sequencer is a stream of events. Events
+ * are records of 4 or 8 bytes. The first byte defines the size.
+ * Any number of events can be written with a write call. There
+ * is a set of macros for sending these events. Use these macros if you
+ * want to maximize portability of your program.
+ *
+ * Events SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO. Are also input events.
+ * (All input events are currently 4 bytes long. Be prepared to support
+ * 8 byte events also. If you receive any event having first byte >= 128,
+ * it's a 8 byte event.
+ *
+ * The events are documented at the end of this file.
+ *
+ * Normal events (4 bytes)
+ * There is also a 8 byte version of most of the 4 byte events. The
+ * 8 byte one is recommended.
+ */
+#define SEQ_NOTEOFF 0
+#define SEQ_FMNOTEOFF SEQ_NOTEOFF /* Just old name */
+#define SEQ_NOTEON 1
+#define SEQ_FMNOTEON SEQ_NOTEON
+#define SEQ_WAIT TMR_WAIT_ABS
+#define SEQ_PGMCHANGE 3
+#define SEQ_FMPGMCHANGE SEQ_PGMCHANGE
+#define SEQ_SYNCTIMER TMR_START
+#define SEQ_MIDIPUTC 5
+#define SEQ_DRUMON 6 /*** OBSOLETE ***/
+#define SEQ_DRUMOFF 7 /*** OBSOLETE ***/
+#define SEQ_ECHO TMR_ECHO /* For synching programs with output */
+#define SEQ_AFTERTOUCH 9
+#define SEQ_CONTROLLER 10
+
+/*******************************************
+ * Midi controller numbers
+ *******************************************
+ * Controllers 0 to 31 (0x00 to 0x1f) and
+ * 32 to 63 (0x20 to 0x3f) are continuous
+ * controllers.
+ * In the MIDI 1.0 these controllers are sent using
+ * two messages. Controller numbers 0 to 31 are used
+ * to send the MSB and the controller numbers 32 to 63
+ * are for the LSB. Note that just 7 bits are used in MIDI bytes.
+ */
+
+#define CTL_BANK_SELECT 0x00
+#define CTL_MODWHEEL 0x01
+#define CTL_BREATH 0x02
+/* undefined 0x03 */
+#define CTL_FOOT 0x04
+#define CTL_PORTAMENTO_TIME 0x05
+#define CTL_DATA_ENTRY 0x06
+#define CTL_MAIN_VOLUME 0x07
+#define CTL_BALANCE 0x08
+/* undefined 0x09 */
+#define CTL_PAN 0x0a
+#define CTL_EXPRESSION 0x0b
+/* undefined 0x0c */
+/* undefined 0x0d */
+/* undefined 0x0e */
+/* undefined 0x0f */
+#define CTL_GENERAL_PURPOSE1 0x10
+#define CTL_GENERAL_PURPOSE2 0x11
+#define CTL_GENERAL_PURPOSE3 0x12
+#define CTL_GENERAL_PURPOSE4 0x13
+/* undefined 0x14 - 0x1f */
+
+/* undefined 0x20 */
+/* The controller numbers 0x21 to 0x3f are reserved for the */
+/* least significant bytes of the controllers 0x00 to 0x1f. */
+/* These controllers are not recognised by the driver. */
+
+/* Controllers 64 to 69 (0x40 to 0x45) are on/off switches. */
+/* 0=OFF and 127=ON (intermediate values are possible) */
+#define CTL_DAMPER_PEDAL 0x40
+#define CTL_SUSTAIN 0x40 /* Alias */
+#define CTL_HOLD 0x40 /* Alias */
+#define CTL_PORTAMENTO 0x41
+#define CTL_SOSTENUTO 0x42
+#define CTL_SOFT_PEDAL 0x43
+/* undefined 0x44 */
+#define CTL_HOLD2 0x45
+/* undefined 0x46 - 0x4f */
+
+#define CTL_GENERAL_PURPOSE5 0x50
+#define CTL_GENERAL_PURPOSE6 0x51
+#define CTL_GENERAL_PURPOSE7 0x52
+#define CTL_GENERAL_PURPOSE8 0x53
+/* undefined 0x54 - 0x5a */
+#define CTL_EXT_EFF_DEPTH 0x5b
+#define CTL_TREMOLO_DEPTH 0x5c
+#define CTL_CHORUS_DEPTH 0x5d
+#define CTL_DETUNE_DEPTH 0x5e
+#define CTL_CELESTE_DEPTH 0x5e /* Alias for the above one */
+#define CTL_PHASER_DEPTH 0x5f
+#define CTL_DATA_INCREMENT 0x60
+#define CTL_DATA_DECREMENT 0x61
+#define CTL_NONREG_PARM_NUM_LSB 0x62
+#define CTL_NONREG_PARM_NUM_MSB 0x63
+#define CTL_REGIST_PARM_NUM_LSB 0x64
+#define CTL_REGIST_PARM_NUM_MSB 0x65
+/* undefined 0x66 - 0x78 */
+/* reserved 0x79 - 0x7f */
+
+/* Pseudo controllers (not midi compatible) */
+#define CTRL_PITCH_BENDER 255
+#define CTRL_PITCH_BENDER_RANGE 254
+#define CTRL_EXPRESSION 253 /* Obsolete */
+#define CTRL_MAIN_VOLUME 252 /* Obsolete */
+#define SEQ_BALANCE 11
+#define SEQ_VOLMODE 12
+
+/*
+ * Volume mode decides how volumes are used
+ */
+
+#define VOL_METHOD_ADAGIO 1
+#define VOL_METHOD_LINEAR 2
+
+/*
+ * Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as
+ * input events.
+ */
+
+/*
+ * Event codes 0xf0 to 0xfc are reserved for future extensions.
+ */
+
+#define SEQ_FULLSIZE 0xfd /* Long events */
+/*
+ * SEQ_FULLSIZE events are used for loading patches/samples to the
+ * synthesizer devices. These events are passed directly to the driver
+ * of the associated synthesizer device. There is no limit to the size
+ * of the extended events. These events are not queued but executed
+ * immediately when the write() is called (execution can take several
+ * seconds of time).
+ *
+ * When a SEQ_FULLSIZE message is written to the device, it must
+ * be written using exactly one write() call. Other events cannot
+ * be mixed to the same write.
+ *
+ * For FM synths (YM3812/OPL3) use struct sbi_instrument and write it to the
+ * /dev/sequencer. Don't write other data together with the instrument structure
+ * Set the key field of the structure to FM_PATCH. The device field is used to
+ * route the patch to the corresponding device.
+ *
+ * For wave table use struct patch_info. Initialize the key field
+ * to WAVE_PATCH.
+ */
+#define SEQ_PRIVATE 0xfe /* Low level HW dependent events (8 bytes) */
+#define SEQ_EXTENDED 0xff /* Extended events (8 bytes) OBSOLETE */
+
+/*
+ * Record for FM patches
+ */
+
+typedef unsigned char sbi_instr_data[32];
+
+struct sbi_instrument {
+ unsigned short key; /* FM_PATCH or OPL3_PATCH */
+#define FM_PATCH _PATCHKEY(0x01)
+#define OPL3_PATCH _PATCHKEY(0x03)
+ short device; /* Synth# (0-4) */
+ int channel; /* Program# to be initialized */
+ sbi_instr_data operators; /* Register settings for operator cells (.SBI format) */
+ };
+
+struct synth_info { /* Read only */
+ char name[30];
+ int device; /* 0-N. INITIALIZE BEFORE CALLING */
+ int synth_type;
+#define SYNTH_TYPE_FM 0
+#define SYNTH_TYPE_SAMPLE 1
+#define SYNTH_TYPE_MIDI 2 /* Midi interface */
+
+ int synth_subtype;
+#define FM_TYPE_ADLIB 0x00
+#define FM_TYPE_OPL3 0x01
+#define MIDI_TYPE_MPU401 0x401
+
+#define SAMPLE_TYPE_BASIC 0x10
+#define SAMPLE_TYPE_GUS SAMPLE_TYPE_BASIC
+#define SAMPLE_TYPE_WAVEFRONT 0x11
+
+ int perc_mode; /* No longer supported */
+ int nr_voices;
+ int nr_drums; /* Obsolete field */
+ int instr_bank_size;
+ unsigned int capabilities;
+#define SYNTH_CAP_PERCMODE 0x00000001 /* No longer used */
+#define SYNTH_CAP_OPL3 0x00000002 /* Set if OPL3 supported */
+#define SYNTH_CAP_INPUT 0x00000004 /* Input (MIDI) device */
+ int dummies[19]; /* Reserve space */
+ };
+
+struct sound_timer_info {
+ char name[32];
+ int caps;
+ };
+
+#define MIDI_CAP_MPU401 1 /* MPU-401 intelligent mode */
+
+struct midi_info {
+ char name[30];
+ int device; /* 0-N. INITIALIZE BEFORE CALLING */
+ unsigned int capabilities; /* To be defined later */
+ int dev_type;
+ int dummies[18]; /* Reserve space */
+ };
+
+/********************************************
+ * ioctl commands for the /dev/midi##
+ */
+typedef struct {
+ unsigned char cmd;
+ char nr_args, nr_returns;
+ unsigned char data[30];
+ } mpu_command_rec;
+
+#define SNDCTL_MIDI_PRETIME _SIOWR('m', 0, int)
+#define SNDCTL_MIDI_MPUMODE _SIOWR('m', 1, int)
+#define SNDCTL_MIDI_MPUCMD _SIOWR('m', 2, mpu_command_rec)
+
+/********************************************
+ * IOCTL commands for /dev/dsp and /dev/audio
+ */
+
+#define SNDCTL_DSP_RESET _SIO ('P', 0)
+#define SNDCTL_DSP_SYNC _SIO ('P', 1)
+#define SNDCTL_DSP_SPEED _SIOWR('P', 2, int)
+#define SNDCTL_DSP_STEREO _SIOWR('P', 3, int)
+#define SNDCTL_DSP_GETBLKSIZE _SIOWR('P', 4, int)
+#define SNDCTL_DSP_SAMPLESIZE SNDCTL_DSP_SETFMT
+#define SNDCTL_DSP_CHANNELS _SIOWR('P', 6, int)
+#define SOUND_PCM_WRITE_CHANNELS SNDCTL_DSP_CHANNELS
+#define SOUND_PCM_WRITE_FILTER _SIOWR('P', 7, int)
+#define SNDCTL_DSP_POST _SIO ('P', 8)
+#define SNDCTL_DSP_SUBDIVIDE _SIOWR('P', 9, int)
+#define SNDCTL_DSP_SETFRAGMENT _SIOWR('P',10, int)
+
+/* Audio data formats (Note! U8=8 and S16_LE=16 for compatibility) */
+#define SNDCTL_DSP_GETFMTS _SIOR ('P',11, int) /* Returns a mask */
+#define SNDCTL_DSP_SETFMT _SIOWR('P',5, int) /* Selects ONE fmt*/
+# define AFMT_QUERY 0x00000000 /* Return current fmt */
+# define AFMT_MU_LAW 0x00000001
+# define AFMT_A_LAW 0x00000002
+# define AFMT_IMA_ADPCM 0x00000004
+# define AFMT_U8 0x00000008
+# define AFMT_S16_LE 0x00000010 /* Little endian signed 16*/
+# define AFMT_S16_BE 0x00000020 /* Big endian signed 16 */
+# define AFMT_S8 0x00000040
+# define AFMT_U16_LE 0x00000080 /* Little endian U16 */
+# define AFMT_U16_BE 0x00000100 /* Big endian U16 */
+# define AFMT_MPEG 0x00000200 /* MPEG (2) audio */
+
+/*
+ * Buffer status queries.
+ */
+typedef struct audio_buf_info {
+ int fragments; /* # of available fragments (partially usend ones not counted) */
+ int fragstotal; /* Total # of fragments allocated */
+ int fragsize; /* Size of a fragment in bytes */
+
+ int bytes; /* Available space in bytes (includes partially used fragments) */
+ /* Note! 'bytes' could be more than fragments*fragsize */
+ } audio_buf_info;
+
+#define SNDCTL_DSP_GETOSPACE _SIOR ('P',12, audio_buf_info)
+#define SNDCTL_DSP_GETISPACE _SIOR ('P',13, audio_buf_info)
+#define SNDCTL_DSP_NONBLOCK _SIO ('P',14)
+#define SNDCTL_DSP_GETCAPS _SIOR ('P',15, int)
+# define DSP_CAP_REVISION 0x000000ff /* Bits for revision level (0 to 255) */
+# define DSP_CAP_DUPLEX 0x00000100 /* Full duplex record/playback */
+# define DSP_CAP_REALTIME 0x00000200 /* Real time capability */
+# define DSP_CAP_BATCH 0x00000400 /* Device has some kind of */
+ /* internal buffers which may */
+ /* cause some delays and */
+ /* decrease precision of timing */
+# define DSP_CAP_COPROC 0x00000800 /* Has a coprocessor */
+ /* Sometimes it's a DSP */
+ /* but usually not */
+# define DSP_CAP_TRIGGER 0x00001000 /* Supports SETTRIGGER */
+# define DSP_CAP_MMAP 0x00002000 /* Supports mmap() */
+
+#define SNDCTL_DSP_GETTRIGGER _SIOR ('P',16, int)
+#define SNDCTL_DSP_SETTRIGGER _SIOW ('P',16, int)
+# define PCM_ENABLE_INPUT 0x00000001
+# define PCM_ENABLE_OUTPUT 0x00000002
+
+typedef struct count_info {
+ int bytes; /* Total # of bytes processed */
+ int blocks; /* # of fragment transitions since last time */
+ int ptr; /* Current DMA pointer value */
+ } count_info;
+
+#define SNDCTL_DSP_GETIPTR _SIOR ('P',17, count_info)
+#define SNDCTL_DSP_GETOPTR _SIOR ('P',18, count_info)
+
+typedef struct buffmem_desc {
+ unsigned *buffer;
+ int size;
+ } buffmem_desc;
+#define SNDCTL_DSP_MAPINBUF _SIOR ('P', 19, buffmem_desc)
+#define SNDCTL_DSP_MAPOUTBUF _SIOR ('P', 20, buffmem_desc)
+#define SNDCTL_DSP_SETSYNCRO _SIO ('P', 21)
+#define SNDCTL_DSP_SETDUPLEX _SIO ('P', 22)
+#define SNDCTL_DSP_GETODELAY _SIOR ('P', 23, int)
+
+/*
+ * Application's profile defines the way how playback underrun situations should be handled.
+ *
+ * APF_NORMAL (the default) and APF_NETWORK make the driver to cleanup the
+ * playback buffer whenever an underrun occurs. This consumes some time
+ * prevents looping the existing buffer.
+ * APF_CPUINTENS is intended to be set by CPU intensive applications which
+ * are likely to run out of time occasionally. In this mode the buffer cleanup is
+ * disabled which saves CPU time but also let's the previous buffer content to
+ * be played during the "pause" after the underrun.
+ */
+#define SNDCTL_DSP_PROFILE _SIOW ('P', 23, int)
+#define APF_NORMAL 0 /* Normal applications */
+#define APF_NETWORK 1 /* Underruns probably caused by an "external" delay */
+#define APF_CPUINTENS 2 /* Underruns probably caused by "overheating" the CPU */
+
+#define SOUND_PCM_READ_RATE _SIOR ('P', 2, int)
+#define SOUND_PCM_READ_CHANNELS _SIOR ('P', 6, int)
+#define SOUND_PCM_READ_BITS _SIOR ('P', 5, int)
+#define SOUND_PCM_READ_FILTER _SIOR ('P', 7, int)
+
+/* Some alias names */
+#define SOUND_PCM_WRITE_BITS SNDCTL_DSP_SETFMT
+#define SOUND_PCM_WRITE_RATE SNDCTL_DSP_SPEED
+#define SOUND_PCM_POST SNDCTL_DSP_POST
+#define SOUND_PCM_RESET SNDCTL_DSP_RESET
+#define SOUND_PCM_SYNC SNDCTL_DSP_SYNC
+#define SOUND_PCM_SUBDIVIDE SNDCTL_DSP_SUBDIVIDE
+#define SOUND_PCM_SETFRAGMENT SNDCTL_DSP_SETFRAGMENT
+#define SOUND_PCM_GETFMTS SNDCTL_DSP_GETFMTS
+#define SOUND_PCM_SETFMT SNDCTL_DSP_SETFMT
+#define SOUND_PCM_GETOSPACE SNDCTL_DSP_GETOSPACE
+#define SOUND_PCM_GETISPACE SNDCTL_DSP_GETISPACE
+#define SOUND_PCM_NONBLOCK SNDCTL_DSP_NONBLOCK
+#define SOUND_PCM_GETCAPS SNDCTL_DSP_GETCAPS
+#define SOUND_PCM_GETTRIGGER SNDCTL_DSP_GETTRIGGER
+#define SOUND_PCM_SETTRIGGER SNDCTL_DSP_SETTRIGGER
+#define SOUND_PCM_SETSYNCRO SNDCTL_DSP_SETSYNCRO
+#define SOUND_PCM_GETIPTR SNDCTL_DSP_GETIPTR
+#define SOUND_PCM_GETOPTR SNDCTL_DSP_GETOPTR
+#define SOUND_PCM_MAPINBUF SNDCTL_DSP_MAPINBUF
+#define SOUND_PCM_MAPOUTBUF SNDCTL_DSP_MAPOUTBUF
+
+/*
+ * ioctl calls to be used in communication with coprocessors and
+ * DSP chips.
+ */
+
+typedef struct copr_buffer {
+ int command; /* Set to 0 if not used */
+ int flags;
+#define CPF_NONE 0x0000
+#define CPF_FIRST 0x0001 /* First block */
+#define CPF_LAST 0x0002 /* Last block */
+ int len;
+ int offs; /* If required by the device (0 if not used) */
+
+ unsigned char data[4000]; /* NOTE! 4000 is not 4k */
+ } copr_buffer;
+
+typedef struct copr_debug_buf {
+ int command; /* Used internally. Set to 0 */
+ int parm1;
+ int parm2;
+ int flags;
+ int len; /* Length of data in bytes */
+ } copr_debug_buf;
+
+typedef struct copr_msg {
+ int len;
+ unsigned char data[4000];
+ } copr_msg;
+
+#define SNDCTL_COPR_RESET _SIO ('C', 0)
+#define SNDCTL_COPR_LOAD _SIOWR('C', 1, copr_buffer)
+#define SNDCTL_COPR_RDATA _SIOWR('C', 2, copr_debug_buf)
+#define SNDCTL_COPR_RCODE _SIOWR('C', 3, copr_debug_buf)
+#define SNDCTL_COPR_WDATA _SIOW ('C', 4, copr_debug_buf)
+#define SNDCTL_COPR_WCODE _SIOW ('C', 5, copr_debug_buf)
+#define SNDCTL_COPR_RUN _SIOWR('C', 6, copr_debug_buf)
+#define SNDCTL_COPR_HALT _SIOWR('C', 7, copr_debug_buf)
+#define SNDCTL_COPR_SENDMSG _SIOWR('C', 8, copr_msg)
+#define SNDCTL_COPR_RCVMSG _SIOR ('C', 9, copr_msg)
+
+/*********************************************
+ * IOCTL commands for /dev/mixer
+ */
+
+/*
+ * Mixer devices
+ *
+ * There can be up to 20 different analog mixer channels. The
+ * SOUND_MIXER_NRDEVICES gives the currently supported maximum.
+ * The SOUND_MIXER_READ_DEVMASK returns a bitmask which tells
+ * the devices supported by the particular mixer.
+ */
+
+#define SOUND_MIXER_NRDEVICES 25
+#define SOUND_MIXER_VOLUME 0
+#define SOUND_MIXER_BASS 1
+#define SOUND_MIXER_TREBLE 2
+#define SOUND_MIXER_SYNTH 3
+#define SOUND_MIXER_PCM 4
+#define SOUND_MIXER_SPEAKER 5
+#define SOUND_MIXER_LINE 6
+#define SOUND_MIXER_MIC 7
+#define SOUND_MIXER_CD 8
+#define SOUND_MIXER_IMIX 9 /* Recording monitor */
+#define SOUND_MIXER_ALTPCM 10
+#define SOUND_MIXER_RECLEV 11 /* Recording level */
+#define SOUND_MIXER_IGAIN 12 /* Input gain */
+#define SOUND_MIXER_OGAIN 13 /* Output gain */
+/*
+ * The AD1848 codec and compatibles have three line level inputs
+ * (line, aux1 and aux2). Since each card manufacturer have assigned
+ * different meanings to these inputs, it's inpractical to assign
+ * specific meanings (line, cd, synth etc.) to them.
+ */
+#define SOUND_MIXER_LINE1 14 /* Input source 1 (aux1) */
+#define SOUND_MIXER_LINE2 15 /* Input source 2 (aux2) */
+#define SOUND_MIXER_LINE3 16 /* Input source 3 (line) */
+#define SOUND_MIXER_DIGITAL1 17 /* Digital (input) 1 */
+#define SOUND_MIXER_DIGITAL2 18 /* Digital (input) 2 */
+#define SOUND_MIXER_DIGITAL3 19 /* Digital (input) 3 */
+#define SOUND_MIXER_PHONEIN 20 /* Phone input */
+#define SOUND_MIXER_PHONEOUT 21 /* Phone output */
+#define SOUND_MIXER_VIDEO 22 /* Video/TV (audio) in */
+#define SOUND_MIXER_RADIO 23 /* Radio in */
+#define SOUND_MIXER_MONITOR 24 /* Monitor (usually mic) volume */
+
+/* Some on/off settings (SOUND_SPECIAL_MIN - SOUND_SPECIAL_MAX) */
+/* Not counted to SOUND_MIXER_NRDEVICES, but use the same number space */
+#define SOUND_ONOFF_MIN 28
+#define SOUND_ONOFF_MAX 30
+
+/* Note! Number 31 cannot be used since the sign bit is reserved */
+#define SOUND_MIXER_NONE 31
+
+/*
+ * The following unsupported macros are no longer functional.
+ * Use SOUND_MIXER_PRIVATE# macros in future.
+ */
+#define SOUND_MIXER_ENHANCE SOUND_MIXER_NONE
+#define SOUND_MIXER_MUTE SOUND_MIXER_NONE
+#define SOUND_MIXER_LOUD SOUND_MIXER_NONE
+
+
+#define SOUND_DEVICE_LABELS {"Vol ", "Bass ", "Trebl", "Synth", "Pcm ", "Spkr ", "Line ", \
+ "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \
+ "Line1", "Line2", "Line3", "Digital1", "Digital2", "Digital3", \
+ "PhoneIn", "PhoneOut", "Video", "Radio", "Monitor"}
+
+#define SOUND_DEVICE_NAMES {"vol", "bass", "treble", "synth", "pcm", "speaker", "line", \
+ "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", \
+ "line1", "line2", "line3", "dig1", "dig2", "dig3", \
+ "phin", "phout", "video", "radio", "monitor"}
+
+/* Device bitmask identifiers */
+
+#define SOUND_MIXER_RECSRC 0xff /* Arg contains a bit for each recording source */
+#define SOUND_MIXER_DEVMASK 0xfe /* Arg contains a bit for each supported device */
+#define SOUND_MIXER_RECMASK 0xfd /* Arg contains a bit for each supported recording source */
+#define SOUND_MIXER_CAPS 0xfc
+# define SOUND_CAP_EXCL_INPUT 0x00000001 /* Only one recording source at a time */
+#define SOUND_MIXER_STEREODEVS 0xfb /* Mixer channels supporting stereo */
+#define SOUND_MIXER_OUTSRC 0xfa /* Arg contains a bit for each input source to output */
+#define SOUND_MIXER_OUTMASK 0xf9 /* Arg contains a bit for each supported input source to output */
+
+/* Device mask bits */
+
+#define SOUND_MASK_VOLUME (1 << SOUND_MIXER_VOLUME)
+#define SOUND_MASK_BASS (1 << SOUND_MIXER_BASS)
+#define SOUND_MASK_TREBLE (1 << SOUND_MIXER_TREBLE)
+#define SOUND_MASK_SYNTH (1 << SOUND_MIXER_SYNTH)
+#define SOUND_MASK_PCM (1 << SOUND_MIXER_PCM)
+#define SOUND_MASK_SPEAKER (1 << SOUND_MIXER_SPEAKER)
+#define SOUND_MASK_LINE (1 << SOUND_MIXER_LINE)
+#define SOUND_MASK_MIC (1 << SOUND_MIXER_MIC)
+#define SOUND_MASK_CD (1 << SOUND_MIXER_CD)
+#define SOUND_MASK_IMIX (1 << SOUND_MIXER_IMIX)
+#define SOUND_MASK_ALTPCM (1 << SOUND_MIXER_ALTPCM)
+#define SOUND_MASK_RECLEV (1 << SOUND_MIXER_RECLEV)
+#define SOUND_MASK_IGAIN (1 << SOUND_MIXER_IGAIN)
+#define SOUND_MASK_OGAIN (1 << SOUND_MIXER_OGAIN)
+#define SOUND_MASK_LINE1 (1 << SOUND_MIXER_LINE1)
+#define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2)
+#define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3)
+#define SOUND_MASK_DIGITAL1 (1 << SOUND_MIXER_DIGITAL1)
+#define SOUND_MASK_DIGITAL2 (1 << SOUND_MIXER_DIGITAL2)
+#define SOUND_MASK_DIGITAL3 (1 << SOUND_MIXER_DIGITAL3)
+#define SOUND_MASK_PHONEIN (1 << SOUND_MIXER_PHONEIN)
+#define SOUND_MASK_PHONEOUT (1 << SOUND_MIXER_PHONEOUT)
+#define SOUND_MASK_RADIO (1 << SOUND_MIXER_RADIO)
+#define SOUND_MASK_VIDEO (1 << SOUND_MIXER_VIDEO)
+#define SOUND_MASK_MONITOR (1 << SOUND_MIXER_MONITOR)
+
+/* Obsolete macros */
+#define SOUND_MASK_MUTE (1 << SOUND_MIXER_MUTE)
+#define SOUND_MASK_ENHANCE (1 << SOUND_MIXER_ENHANCE)
+#define SOUND_MASK_LOUD (1 << SOUND_MIXER_LOUD)
+
+#define MIXER_READ(dev) _SIOR('M', dev, int)
+#define SOUND_MIXER_READ_VOLUME MIXER_READ(SOUND_MIXER_VOLUME)
+#define SOUND_MIXER_READ_BASS MIXER_READ(SOUND_MIXER_BASS)
+#define SOUND_MIXER_READ_TREBLE MIXER_READ(SOUND_MIXER_TREBLE)
+#define SOUND_MIXER_READ_SYNTH MIXER_READ(SOUND_MIXER_SYNTH)
+#define SOUND_MIXER_READ_PCM MIXER_READ(SOUND_MIXER_PCM)
+#define SOUND_MIXER_READ_SPEAKER MIXER_READ(SOUND_MIXER_SPEAKER)
+#define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE)
+#define SOUND_MIXER_READ_MIC MIXER_READ(SOUND_MIXER_MIC)
+#define SOUND_MIXER_READ_CD MIXER_READ(SOUND_MIXER_CD)
+#define SOUND_MIXER_READ_IMIX MIXER_READ(SOUND_MIXER_IMIX)
+#define SOUND_MIXER_READ_ALTPCM MIXER_READ(SOUND_MIXER_ALTPCM)
+#define SOUND_MIXER_READ_RECLEV MIXER_READ(SOUND_MIXER_RECLEV)
+#define SOUND_MIXER_READ_IGAIN MIXER_READ(SOUND_MIXER_IGAIN)
+#define SOUND_MIXER_READ_OGAIN MIXER_READ(SOUND_MIXER_OGAIN)
+#define SOUND_MIXER_READ_LINE1 MIXER_READ(SOUND_MIXER_LINE1)
+#define SOUND_MIXER_READ_LINE2 MIXER_READ(SOUND_MIXER_LINE2)
+#define SOUND_MIXER_READ_LINE3 MIXER_READ(SOUND_MIXER_LINE3)
+
+/* Obsolete macros */
+#define SOUND_MIXER_READ_MUTE MIXER_READ(SOUND_MIXER_MUTE)
+#define SOUND_MIXER_READ_ENHANCE MIXER_READ(SOUND_MIXER_ENHANCE)
+#define SOUND_MIXER_READ_LOUD MIXER_READ(SOUND_MIXER_LOUD)
+
+#define SOUND_MIXER_READ_RECSRC MIXER_READ(SOUND_MIXER_RECSRC)
+#define SOUND_MIXER_READ_DEVMASK MIXER_READ(SOUND_MIXER_DEVMASK)
+#define SOUND_MIXER_READ_RECMASK MIXER_READ(SOUND_MIXER_RECMASK)
+#define SOUND_MIXER_READ_STEREODEVS MIXER_READ(SOUND_MIXER_STEREODEVS)
+#define SOUND_MIXER_READ_CAPS MIXER_READ(SOUND_MIXER_CAPS)
+
+#define MIXER_WRITE(dev) _SIOWR('M', dev, int)
+#define SOUND_MIXER_WRITE_VOLUME MIXER_WRITE(SOUND_MIXER_VOLUME)
+#define SOUND_MIXER_WRITE_BASS MIXER_WRITE(SOUND_MIXER_BASS)
+#define SOUND_MIXER_WRITE_TREBLE MIXER_WRITE(SOUND_MIXER_TREBLE)
+#define SOUND_MIXER_WRITE_SYNTH MIXER_WRITE(SOUND_MIXER_SYNTH)
+#define SOUND_MIXER_WRITE_PCM MIXER_WRITE(SOUND_MIXER_PCM)
+#define SOUND_MIXER_WRITE_SPEAKER MIXER_WRITE(SOUND_MIXER_SPEAKER)
+#define SOUND_MIXER_WRITE_LINE MIXER_WRITE(SOUND_MIXER_LINE)
+#define SOUND_MIXER_WRITE_MIC MIXER_WRITE(SOUND_MIXER_MIC)
+#define SOUND_MIXER_WRITE_CD MIXER_WRITE(SOUND_MIXER_CD)
+#define SOUND_MIXER_WRITE_IMIX MIXER_WRITE(SOUND_MIXER_IMIX)
+#define SOUND_MIXER_WRITE_ALTPCM MIXER_WRITE(SOUND_MIXER_ALTPCM)
+#define SOUND_MIXER_WRITE_RECLEV MIXER_WRITE(SOUND_MIXER_RECLEV)
+#define SOUND_MIXER_WRITE_IGAIN MIXER_WRITE(SOUND_MIXER_IGAIN)
+#define SOUND_MIXER_WRITE_OGAIN MIXER_WRITE(SOUND_MIXER_OGAIN)
+#define SOUND_MIXER_WRITE_LINE1 MIXER_WRITE(SOUND_MIXER_LINE1)
+#define SOUND_MIXER_WRITE_LINE2 MIXER_WRITE(SOUND_MIXER_LINE2)
+#define SOUND_MIXER_WRITE_LINE3 MIXER_WRITE(SOUND_MIXER_LINE3)
+
+/* Obsolete macros */
+#define SOUND_MIXER_WRITE_MUTE MIXER_WRITE(SOUND_MIXER_MUTE)
+#define SOUND_MIXER_WRITE_ENHANCE MIXER_WRITE(SOUND_MIXER_ENHANCE)
+#define SOUND_MIXER_WRITE_LOUD MIXER_WRITE(SOUND_MIXER_LOUD)
+
+#define SOUND_MIXER_WRITE_RECSRC MIXER_WRITE(SOUND_MIXER_RECSRC)
+
+typedef struct mixer_info
+{
+ char id[16];
+ char name[32];
+ int modify_counter;
+ int fillers[10];
+} mixer_info;
+
+typedef struct _old_mixer_info /* Obsolete */
+{
+ char id[16];
+ char name[32];
+} _old_mixer_info;
+
+#define SOUND_MIXER_INFO _SIOR ('M', 101, mixer_info)
+#define SOUND_OLD_MIXER_INFO _SIOR ('M', 101, _old_mixer_info)
+
+/*
+ * A mechanism for accessing "proprietary" mixer features. This method
+ * permits passing 128 bytes of arbitrary data between a mixer application
+ * and the mixer driver. Interpretation of the record is defined by
+ * the particular mixer driver.
+ */
+typedef unsigned char mixer_record[128];
+
+#define SOUND_MIXER_ACCESS _SIOWR('M', 102, mixer_record)
+
+/*
+ * Two ioctls for special souncard function
+ */
+#define SOUND_MIXER_AGC _SIOWR('M', 103, int)
+#define SOUND_MIXER_3DSE _SIOWR('M', 104, int)
+
+/*
+ * The SOUND_MIXER_PRIVATE# commands can be redefined by low level drivers.
+ * These features can be used when accessing device specific features.
+ */
+#define SOUND_MIXER_PRIVATE1 _SIOWR('M', 111, int)
+#define SOUND_MIXER_PRIVATE2 _SIOWR('M', 112, int)
+#define SOUND_MIXER_PRIVATE3 _SIOWR('M', 113, int)
+#define SOUND_MIXER_PRIVATE4 _SIOWR('M', 114, int)
+#define SOUND_MIXER_PRIVATE5 _SIOWR('M', 115, int)
+
+/*
+ * SOUND_MIXER_GETLEVELS and SOUND_MIXER_SETLEVELS calls can be used
+ * for querying current mixer settings from the driver and for loading
+ * default volume settings _prior_ activating the mixer (loading
+ * doesn't affect current state of the mixer hardware). These calls
+ * are for internal use only.
+ */
+
+typedef struct mixer_vol_table {
+ int num; /* Index to volume table */
+ char name[32];
+ int levels[32];
+} mixer_vol_table;
+
+#define SOUND_MIXER_GETLEVELS _SIOWR('M', 116, mixer_vol_table)
+#define SOUND_MIXER_SETLEVELS _SIOWR('M', 117, mixer_vol_table)
+
+/*
+ * An ioctl for identifying the driver version. It will return value
+ * of the SOUND_VERSION macro used when compiling the driver.
+ * This call was introduced in OSS version 3.6 and it will not work
+ * with earlier versions (returns EINVAL).
+ */
+#define OSS_GETVERSION _SIOR ('M', 118, int)
+
+/*
+ * Level 2 event types for /dev/sequencer
+ */
+
+/*
+ * The 4 most significant bits of byte 0 specify the class of
+ * the event:
+ *
+ * 0x8X = system level events,
+ * 0x9X = device/port specific events, event[1] = device/port,
+ * The last 4 bits give the subtype:
+ * 0x02 = Channel event (event[3] = chn).
+ * 0x01 = note event (event[4] = note).
+ * (0x01 is not used alone but always with bit 0x02).
+ * event[2] = MIDI message code (0x80=note off etc.)
+ *
+ */
+
+#define EV_SEQ_LOCAL 0x80
+#define EV_TIMING 0x81
+#define EV_CHN_COMMON 0x92
+#define EV_CHN_VOICE 0x93
+#define EV_SYSEX 0x94
+/*
+ * Event types 200 to 220 are reserved for application use.
+ * These numbers will not be used by the driver.
+ */
+
+/*
+ * Events for event type EV_CHN_VOICE
+ */
+
+#define MIDI_NOTEOFF 0x80
+#define MIDI_NOTEON 0x90
+#define MIDI_KEY_PRESSURE 0xA0
+
+/*
+ * Events for event type EV_CHN_COMMON
+ */
+
+#define MIDI_CTL_CHANGE 0xB0
+#define MIDI_PGM_CHANGE 0xC0
+#define MIDI_CHN_PRESSURE 0xD0
+#define MIDI_PITCH_BEND 0xE0
+
+#define MIDI_SYSTEM_PREFIX 0xF0
+
+/*
+ * Timer event types
+ */
+#define TMR_WAIT_REL 1 /* Time relative to the prev time */
+#define TMR_WAIT_ABS 2 /* Absolute time since TMR_START */
+#define TMR_STOP 3
+#define TMR_START 4
+#define TMR_CONTINUE 5
+#define TMR_TEMPO 6
+#define TMR_ECHO 8
+#define TMR_CLOCK 9 /* MIDI clock */
+#define TMR_SPP 10 /* Song position pointer */
+#define TMR_TIMESIG 11 /* Time signature */
+
+/*
+ * Local event types
+ */
+#define LOCL_STARTAUDIO 1
+
+#if (!defined(__KERNEL__) && !defined(KERNEL) && !defined(INKERNEL) && !defined(_KERNEL)) || defined(USE_SEQ_MACROS)
+/*
+ * Some convenience macros to simplify programming of the
+ * /dev/sequencer interface
+ *
+ * These macros define the API which should be used when possible.
+ */
+#define SEQ_DECLAREBUF() SEQ_USE_EXTBUF()
+
+void seqbuf_dump(void); /* This function must be provided by programs */
+
+extern int OSS_init(int seqfd, int buflen);
+extern void OSS_seqbuf_dump(int fd, unsigned char *buf, int buflen);
+extern void OSS_seq_advbuf(int len, int fd, unsigned char *buf, int buflen);
+extern void OSS_seq_needbuf(int len, int fd, unsigned char *buf, int buflen);
+extern void OSS_patch_caching(int dev, int chn, int patch,
+ int fd, unsigned char *buf, int buflen);
+extern void OSS_drum_caching(int dev, int chn, int patch,
+ int fd, unsigned char *buf, int buflen);
+extern void OSS_write_patch(int fd, unsigned char *buf, int len);
+extern int OSS_write_patch2(int fd, unsigned char *buf, int len);
+
+#define SEQ_PM_DEFINES int __foo_bar___
+#ifdef OSSLIB
+# define SEQ_USE_EXTBUF() \
+ extern unsigned char *_seqbuf; \
+ extern int _seqbuflen;extern int _seqbufptr
+# define SEQ_DEFINEBUF(len) SEQ_USE_EXTBUF();static int _requested_seqbuflen=len
+# define _SEQ_ADVBUF(len) OSS_seq_advbuf(len, seqfd, _seqbuf, _seqbuflen)
+# define _SEQ_NEEDBUF(len) OSS_seq_needbuf(len, seqfd, _seqbuf, _seqbuflen)
+# define SEQ_DUMPBUF() OSS_seqbuf_dump(seqfd, _seqbuf, _seqbuflen)
+
+# define SEQ_LOAD_GMINSTR(dev, instr) \
+ OSS_patch_caching(dev, -1, instr, seqfd, _seqbuf, _seqbuflen)
+# define SEQ_LOAD_GMDRUM(dev, drum) \
+ OSS_drum_caching(dev, -1, drum, seqfd, _seqbuf, _seqbuflen)
+#else /* !OSSLIB */
+
+# define SEQ_LOAD_GMINSTR(dev, instr)
+# define SEQ_LOAD_GMDRUM(dev, drum)
+
+# define SEQ_USE_EXTBUF() \
+ extern unsigned char _seqbuf[]; \
+ extern int _seqbuflen;extern int _seqbufptr
+
+#ifndef USE_SIMPLE_MACROS
+/* Sample seqbuf_dump() implementation:
+ *
+ * SEQ_DEFINEBUF (2048); -- Defines a buffer for 2048 bytes
+ *
+ * int seqfd; -- The file descriptor for /dev/sequencer.
+ *
+ * void
+ * seqbuf_dump ()
+ * {
+ * if (_seqbufptr)
+ * if (write (seqfd, _seqbuf, _seqbufptr) == -1)
+ * {
+ * perror ("write /dev/sequencer");
+ * exit (-1);
+ * }
+ * _seqbufptr = 0;
+ * }
+ */
+
+#define SEQ_DEFINEBUF(len) unsigned char _seqbuf[len]; int _seqbuflen = len;int _seqbufptr = 0
+#define _SEQ_NEEDBUF(len) if ((_seqbufptr+(len)) > _seqbuflen) seqbuf_dump()
+#define _SEQ_ADVBUF(len) _seqbufptr += len
+#define SEQ_DUMPBUF seqbuf_dump
+#else
+/*
+ * This variation of the sequencer macros is used just to format one event
+ * using fixed buffer.
+ *
+ * The program using the macro library must define the following macros before
+ * using this library.
+ *
+ * #define _seqbuf name of the buffer (unsigned char[])
+ * #define _SEQ_ADVBUF(len) If the applic needs to know the exact
+ * size of the event, this macro can be used.
+ * Otherwise this must be defined as empty.
+ * #define _seqbufptr Define the name of index variable or 0 if
+ * not required.
+ */
+#define _SEQ_NEEDBUF(len) /* empty */
+#endif
+#endif /* !OSSLIB */
+
+#define SEQ_VOLUME_MODE(dev, mode) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = SEQ_EXTENDED;\
+ _seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\
+ _seqbuf[_seqbufptr+2] = (dev);\
+ _seqbuf[_seqbufptr+3] = (mode);\
+ _seqbuf[_seqbufptr+4] = 0;\
+ _seqbuf[_seqbufptr+5] = 0;\
+ _seqbuf[_seqbufptr+6] = 0;\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+
+/*
+ * Midi voice messages
+ */
+
+#define _CHN_VOICE(dev, event, chn, note, parm) \
+ {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_CHN_VOICE;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ _seqbuf[_seqbufptr+2] = (event);\
+ _seqbuf[_seqbufptr+3] = (chn);\
+ _seqbuf[_seqbufptr+4] = (note);\
+ _seqbuf[_seqbufptr+5] = (parm);\
+ _seqbuf[_seqbufptr+6] = (0);\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_START_NOTE(dev, chn, note, vol) \
+ _CHN_VOICE(dev, MIDI_NOTEON, chn, note, vol)
+
+#define SEQ_STOP_NOTE(dev, chn, note, vol) \
+ _CHN_VOICE(dev, MIDI_NOTEOFF, chn, note, vol)
+
+#define SEQ_KEY_PRESSURE(dev, chn, note, pressure) \
+ _CHN_VOICE(dev, MIDI_KEY_PRESSURE, chn, note, pressure)
+
+/*
+ * Midi channel messages
+ */
+
+#define _CHN_COMMON(dev, event, chn, p1, p2, w14) \
+ {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_CHN_COMMON;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ _seqbuf[_seqbufptr+2] = (event);\
+ _seqbuf[_seqbufptr+3] = (chn);\
+ _seqbuf[_seqbufptr+4] = (p1);\
+ _seqbuf[_seqbufptr+5] = (p2);\
+ *(short *)&_seqbuf[_seqbufptr+6] = (w14);\
+ _SEQ_ADVBUF(8);}
+/*
+ * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits
+ * sending any MIDI bytes but it's absolutely not possible. Trying to do
+ * so _will_ cause problems with MPU401 intelligent mode).
+ *
+ * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be
+ * sent by calling SEQ_SYSEX() several times (there must be no other events
+ * between them). First sysex fragment must have 0xf0 in the first byte
+ * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte
+ * between these sysex start and end markers cannot be larger than 0x7f. Also
+ * lengths of each fragments (except the last one) must be 6.
+ *
+ * Breaking the above rules may work with some MIDI ports but is likely to
+ * cause fatal problems with some other devices (such as MPU401).
+ */
+#define SEQ_SYSEX(dev, buf, len) \
+ {int ii, ll=(len); \
+ unsigned char *bufp=buf;\
+ if (ll>6)ll=6;\
+ _SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = EV_SYSEX;\
+ _seqbuf[_seqbufptr+1] = (dev);\
+ for(ii=0;ii<ll;ii++)\
+ _seqbuf[_seqbufptr+ii+2] = bufp[ii];\
+ for(ii=ll;ii<6;ii++)\
+ _seqbuf[_seqbufptr+ii+2] = 0xff;\
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_CHN_PRESSURE(dev, chn, pressure) \
+ _CHN_COMMON(dev, MIDI_CHN_PRESSURE, chn, pressure, 0, 0)
+
+#define SEQ_SET_PATCH SEQ_PGM_CHANGE
+#ifdef OSSLIB
+# define SEQ_PGM_CHANGE(dev, chn, patch) \
+ {OSS_patch_caching(dev, chn, patch, seqfd, _seqbuf, _seqbuflen); \
+ _CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0);}
+#else
+# define SEQ_PGM_CHANGE(dev, chn, patch) \
+ _CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0)
+#endif
+
+#define SEQ_CONTROL(dev, chn, controller, value) \
+ _CHN_COMMON(dev, MIDI_CTL_CHANGE, chn, controller, 0, value)
+
+#define SEQ_BENDER(dev, chn, value) \
+ _CHN_COMMON(dev, MIDI_PITCH_BEND, chn, 0, 0, value)
+
+
+#define SEQ_V2_X_CONTROL(dev, voice, controller, value) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr] = SEQ_EXTENDED;\
+ _seqbuf[_seqbufptr+1] = SEQ_CONTROLLER;\
+ _seqbuf[_seqbufptr+2] = (dev);\
+ _seqbuf[_seqbufptr+3] = (voice);\
+ _seqbuf[_seqbufptr+4] = (controller);\
+ _seqbuf[_seqbufptr+5] = ((value)&0xff);\
+ _seqbuf[_seqbufptr+6] = ((value>>8)&0xff);\
+ _seqbuf[_seqbufptr+7] = 0;\
+ _SEQ_ADVBUF(8);}
+/*
+ * The following 5 macros are incorrectly implemented and obsolete.
+ * Use SEQ_BENDER and SEQ_CONTROL (with proper controller) instead.
+ */
+#define SEQ_PITCHBEND(dev, voice, value) SEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER, value)
+#define SEQ_BENDER_RANGE(dev, voice, value) SEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER_RANGE, value)
+#define SEQ_EXPRESSION(dev, voice, value) SEQ_CONTROL(dev, voice, CTL_EXPRESSION, value*128)
+#define SEQ_MAIN_VOLUME(dev, voice, value) SEQ_CONTROL(dev, voice, CTL_MAIN_VOLUME, (value*16383)/100)
+#define SEQ_PANNING(dev, voice, pos) SEQ_CONTROL(dev, voice, CTL_PAN, (pos+128) / 2)
+
+/*
+ * Timing and syncronization macros
+ */
+
+#define _TIMER_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr+0] = EV_TIMING; \
+ _seqbuf[_seqbufptr+1] = (ev); \
+ _seqbuf[_seqbufptr+2] = 0;\
+ _seqbuf[_seqbufptr+3] = 0;\
+ *(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_START_TIMER() _TIMER_EVENT(TMR_START, 0)
+#define SEQ_STOP_TIMER() _TIMER_EVENT(TMR_STOP, 0)
+#define SEQ_CONTINUE_TIMER() _TIMER_EVENT(TMR_CONTINUE, 0)
+#define SEQ_WAIT_TIME(ticks) _TIMER_EVENT(TMR_WAIT_ABS, ticks)
+#define SEQ_DELTA_TIME(ticks) _TIMER_EVENT(TMR_WAIT_REL, ticks)
+#define SEQ_ECHO_BACK(key) _TIMER_EVENT(TMR_ECHO, key)
+#define SEQ_SET_TEMPO(value) _TIMER_EVENT(TMR_TEMPO, value)
+#define SEQ_SONGPOS(pos) _TIMER_EVENT(TMR_SPP, pos)
+#define SEQ_TIME_SIGNATURE(sig) _TIMER_EVENT(TMR_TIMESIG, sig)
+
+/*
+ * Local control events
+ */
+
+#define _LOCAL_EVENT(ev, parm) {_SEQ_NEEDBUF(8);\
+ _seqbuf[_seqbufptr+0] = EV_SEQ_LOCAL; \
+ _seqbuf[_seqbufptr+1] = (ev); \
+ _seqbuf[_seqbufptr+2] = 0;\
+ _seqbuf[_seqbufptr+3] = 0;\
+ *(unsigned int *)&_seqbuf[_seqbufptr+4] = (parm); \
+ _SEQ_ADVBUF(8);}
+
+#define SEQ_PLAYAUDIO(devmask) _LOCAL_EVENT(LOCL_STARTAUDIO, devmask)
+/*
+ * Events for the level 1 interface only
+ */
+
+#define SEQ_MIDIOUT(device, byte) {_SEQ_NEEDBUF(4);\
+ _seqbuf[_seqbufptr] = SEQ_MIDIPUTC;\
+ _seqbuf[_seqbufptr+1] = (byte);\
+ _seqbuf[_seqbufptr+2] = (device);\
+ _seqbuf[_seqbufptr+3] = 0;\
+ _SEQ_ADVBUF(4);}
+
+/*
+ * Patch loading.
+ */
+#ifdef OSSLIB
+# define SEQ_WRPATCH(patchx, len) \
+ OSS_write_patch(seqfd, (char*)(patchx), len)
+# define SEQ_WRPATCH2(patchx, len) \
+ OSS_write_patch2(seqfd, (char*)(patchx), len)
+#else
+# define SEQ_WRPATCH(patchx, len) \
+ {if (_seqbufptr) SEQ_DUMPBUF();\
+ if (write(seqfd, (char*)(patchx), len)==-1) \
+ perror("Write patch: /dev/sequencer");}
+# define SEQ_WRPATCH2(patchx, len) \
+ (SEQ_DUMPBUF(), write(seqfd, (char*)(patchx), len))
+#endif
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/linux/soundmodem.h b/pfinet/linux-src/include/linux/soundmodem.h
new file mode 100644
index 00000000..10d0799d
--- /dev/null
+++ b/pfinet/linux-src/include/linux/soundmodem.h
@@ -0,0 +1,90 @@
+/*
+ * The Linux soundcard driver for 1200 baud and 9600 baud packet radio
+ * (C) 1996-1998 by Thomas Sailer, HB9JNX/AE4WA
+ */
+
+#ifndef _SOUNDMODEM_H
+#define _SOUNDMODEM_H
+
+/* -------------------------------------------------------------------- */
+/*
+ * structs for the IOCTL commands
+ */
+
+struct sm_debug_data {
+ unsigned int int_rate;
+ unsigned int mod_cycles;
+ unsigned int demod_cycles;
+ unsigned int dma_residue;
+};
+
+struct sm_diag_data {
+ unsigned int mode;
+ unsigned int flags;
+ unsigned int samplesperbit;
+ unsigned int datalen;
+ short *data;
+};
+
+struct sm_mixer_data {
+ unsigned int mixer_type;
+ unsigned int sample_rate;
+ unsigned int bit_rate;
+ unsigned int reg;
+ unsigned int data;
+};
+
+struct sm_config {
+ int hardware;
+ int mode;
+};
+
+struct sm_ioctl {
+ int cmd;
+ union {
+ struct sm_config cfg;
+ struct sm_diag_data diag;
+ struct sm_mixer_data mix;
+ struct sm_debug_data dbg;
+ } data;
+};
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * diagnose modes
+ */
+#define SM_DIAGMODE_OFF 0
+#define SM_DIAGMODE_INPUT 1
+#define SM_DIAGMODE_DEMOD 2
+#define SM_DIAGMODE_CONSTELLATION 3
+
+/*
+ * diagnose flags
+ */
+#define SM_DIAGFLAG_DCDGATE (1<<0)
+#define SM_DIAGFLAG_VALID (1<<1)
+
+/*
+ * mixer types
+ */
+#define SM_MIXER_INVALID 0
+#define SM_MIXER_AD1848 0x10
+#define SM_MIXER_CRYSTAL 0x11
+#define SM_MIXER_CT1335 0x20
+#define SM_MIXER_CT1345 0x21
+#define SM_MIXER_CT1745 0x22
+
+/*
+ * ioctl values
+ */
+#define SMCTL_DIAGNOSE 0x82
+#define SMCTL_GETMIXER 0x83
+#define SMCTL_SETMIXER 0x84
+#define SMCTL_GETDEBUG 0x85
+
+/* -------------------------------------------------------------------- */
+
+#endif /* _SOUNDMODEM_H */
+
+/* --------------------------------------------------------------------- */
diff --git a/pfinet/linux-src/include/linux/stallion.h b/pfinet/linux-src/include/linux/stallion.h
new file mode 100644
index 00000000..35274488
--- /dev/null
+++ b/pfinet/linux-src/include/linux/stallion.h
@@ -0,0 +1,156 @@
+/*****************************************************************************/
+
+/*
+ * stallion.h -- stallion multiport serial driver.
+ *
+ * Copyright (C) 1996-1998 Stallion Technologies (support@stallion.oz.au).
+ * Copyright (C) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*****************************************************************************/
+#ifndef _STALLION_H
+#define _STALLION_H
+/*****************************************************************************/
+
+/*
+ * Define important driver constants here.
+ */
+#define STL_MAXBRDS 4
+#define STL_MAXPANELS 4
+#define STL_MAXBANKS 8
+#define STL_PORTSPERPANEL 16
+#define STL_MAXPORTS 64
+#define STL_MAXDEVS (STL_MAXBRDS * STL_MAXPORTS)
+
+
+/*
+ * Define a set of structures to hold all the board/panel/port info
+ * for our ports. These will be dynamically allocated as required.
+ */
+
+/*
+ * Define a ring queue structure for each port. This will hold the
+ * TX data waiting to be output. Characters are fed into this buffer
+ * from the line discipline (or even direct from user space!) and
+ * then fed into the UARTs during interrupts. Will use a classic ring
+ * queue here for this. The good thing about this type of ring queue
+ * is that the head and tail pointers can be updated without interrupt
+ * protection - since "write" code only needs to change the head, and
+ * interrupt code only needs to change the tail.
+ */
+typedef struct {
+ char *buf;
+ char *head;
+ char *tail;
+} stlrq_t;
+
+/*
+ * Port, panel and board structures to hold status info about each.
+ * The board structure contains pointers to structures for each panel
+ * connected to it, and in turn each panel structure contains pointers
+ * for each port structure for each port on that panel. Note that
+ * the port structure also contains the board and panel number that it
+ * is associated with, this makes it (fairly) easy to get back to the
+ * board/panel info for a port.
+ */
+typedef struct stlport {
+ unsigned long magic;
+ int portnr;
+ int panelnr;
+ int brdnr;
+ int ioaddr;
+ int uartaddr;
+ int pagenr;
+ int istate;
+ int flags;
+ int baud_base;
+ int custom_divisor;
+ int close_delay;
+ int closing_wait;
+ int refcount;
+ int openwaitcnt;
+ int brklen;
+ long session;
+ long pgrp;
+ unsigned int sigs;
+ unsigned int rxignoremsk;
+ unsigned int rxmarkmsk;
+ unsigned int imr;
+ unsigned int crenable;
+ unsigned long clk;
+ unsigned long hwid;
+ void *uartp;
+ struct tty_struct *tty;
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+ struct termios normaltermios;
+ struct termios callouttermios;
+ struct tq_struct tqueue;
+ comstats_t stats;
+ stlrq_t tx;
+} stlport_t;
+
+typedef struct stlpanel {
+ unsigned long magic;
+ int panelnr;
+ int brdnr;
+ int pagenr;
+ int nrports;
+ int iobase;
+ void *uartp;
+ void (*isr)(struct stlpanel *panelp, unsigned int iobase);
+ unsigned int hwid;
+ unsigned int ackmask;
+ stlport_t *ports[STL_PORTSPERPANEL];
+} stlpanel_t;
+
+typedef struct stlbrd {
+ unsigned long magic;
+ int brdnr;
+ int brdtype;
+ int state;
+ int nrpanels;
+ int nrports;
+ int nrbnks;
+ int irq;
+ int irqtype;
+ void (*isr)(struct stlbrd *brdp);
+ unsigned int ioaddr1;
+ unsigned int ioaddr2;
+ unsigned int iosize1;
+ unsigned int iosize2;
+ unsigned int iostatus;
+ unsigned int ioctrl;
+ unsigned int ioctrlval;
+ unsigned int hwid;
+ unsigned long clk;
+ unsigned int bnkpageaddr[STL_MAXBANKS];
+ unsigned int bnkstataddr[STL_MAXBANKS];
+ stlpanel_t *bnk2panel[STL_MAXBANKS];
+ stlpanel_t *panels[STL_MAXPANELS];
+} stlbrd_t;
+
+
+/*
+ * Define MAGIC numbers used for above structures.
+ */
+#define STL_PORTMAGIC 0x5a7182c9
+#define STL_PANELMAGIC 0x7ef621a1
+#define STL_BOARDMAGIC 0xa2267f52
+
+/*****************************************************************************/
+#endif
diff --git a/pfinet/linux-src/include/linux/stat.h b/pfinet/linux-src/include/linux/stat.h
new file mode 100644
index 00000000..e43e241f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/stat.h
@@ -0,0 +1,57 @@
+#ifndef _LINUX_STAT_H
+#define _LINUX_STAT_H
+
+#ifdef __KERNEL__
+
+#include <asm/stat.h>
+
+#endif
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#define S_IFMT 00170000
+#define S_IFSOCK 0140000
+#define S_IFLNK 0120000
+#define S_IFREG 0100000
+#define S_IFBLK 0060000
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+
+#define S_IRWXU 00700
+#define S_IRUSR 00400
+#define S_IWUSR 00200
+#define S_IXUSR 00100
+
+#define S_IRWXG 00070
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+
+#define S_IRWXO 00007
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+
+#endif
+
+#ifdef __KERNEL__
+#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
+#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
+#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
+#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
+#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/stddef.h b/pfinet/linux-src/include/linux/stddef.h
new file mode 100644
index 00000000..39da8088
--- /dev/null
+++ b/pfinet/linux-src/include/linux/stddef.h
@@ -0,0 +1,10 @@
+#ifndef _LINUX_STDDEF_H
+#define _LINUX_STDDEF_H
+
+#undef NULL
+#define NULL ((void *)0)
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif
diff --git a/pfinet/linux-src/include/linux/string.h b/pfinet/linux-src/include/linux/string.h
new file mode 100644
index 00000000..1b3fa4e5
--- /dev/null
+++ b/pfinet/linux-src/include/linux/string.h
@@ -0,0 +1,46 @@
+#ifndef _LINUX_STRING_H_
+#define _LINUX_STRING_H_
+
+#include <linux/types.h> /* for size_t */
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char * ___strtok;
+extern char * strcpy(char *,const char *);
+extern char * strncpy(char *,const char *, __kernel_size_t);
+extern char * strcat(char *, const char *);
+extern char * strncat(char *, const char *, __kernel_size_t);
+extern char * strchr(const char *,int);
+extern char * strrchr(const char *,int);
+extern char * strpbrk(const char *,const char *);
+extern char * strtok(char *,const char *);
+extern char * strstr(const char *,const char *);
+extern __kernel_size_t strlen(const char *);
+extern __kernel_size_t strnlen(const char *,__kernel_size_t);
+extern __kernel_size_t strspn(const char *,const char *);
+extern int strcmp(const char *,const char *);
+extern int strncmp(const char *,const char *,__kernel_size_t);
+extern int strnicmp(const char *, const char *, __kernel_size_t);
+
+extern void * memset(void *,int,__kernel_size_t);
+extern void * memcpy(void *,const void *,__kernel_size_t);
+extern void * memmove(void *,const void *,__kernel_size_t);
+extern void * memscan(void *,int,__kernel_size_t);
+extern int memcmp(const void *,const void *,__kernel_size_t);
+
+/*
+ * Include machine specific inline routines
+ */
+#include <asm/string.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LINUX_STRING_H_ */
diff --git a/pfinet/linux-src/include/linux/swap.h b/pfinet/linux-src/include/linux/swap.h
new file mode 100644
index 00000000..66ba5d62
--- /dev/null
+++ b/pfinet/linux-src/include/linux/swap.h
@@ -0,0 +1,175 @@
+#ifndef _LINUX_SWAP_H
+#define _LINUX_SWAP_H
+
+#include <asm/page.h>
+
+#define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */
+#define SWAP_FLAG_PRIO_MASK 0x7fff
+#define SWAP_FLAG_PRIO_SHIFT 0
+
+#define MAX_SWAPFILES 8
+
+union swap_header {
+ struct
+ {
+ char reserved[PAGE_SIZE - 10];
+ char magic[10];
+ } magic;
+ struct
+ {
+ char bootbits[1024]; /* Space for disklabel etc. */
+ unsigned int version;
+ unsigned int last_page;
+ unsigned int nr_badpages;
+ unsigned int padding[125];
+ unsigned int badpages[1];
+ } info;
+};
+
+#ifdef __KERNEL__
+
+/*
+ * Max bad pages in the new format..
+ */
+#define __swapoffset(x) ((unsigned long)&((union swap_header *)0)->x)
+#define MAX_SWAP_BADPAGES \
+ ((__swapoffset(magic.magic) - __swapoffset(info.badpages)) / sizeof(int))
+
+#undef DEBUG_SWAP
+
+#include <asm/atomic.h>
+
+#define SWP_USED 1
+#define SWP_WRITEOK 3
+
+#define SWAP_CLUSTER_MAX 32
+
+#define SWAP_MAP_MAX 0x7fff
+#define SWAP_MAP_BAD 0x8000
+
+struct swap_info_struct {
+ unsigned int flags;
+ kdev_t swap_device;
+ struct dentry * swap_file;
+ unsigned short * swap_map;
+ unsigned char * swap_lockmap;
+ unsigned int lowest_bit;
+ unsigned int highest_bit;
+ unsigned int cluster_next;
+ unsigned int cluster_nr;
+ int prio; /* swap priority */
+ int pages;
+ unsigned long max;
+ int next; /* next entry on swap list */
+};
+
+extern int nr_swap_pages;
+extern int nr_free_pages;
+extern atomic_t nr_async_pages;
+extern struct inode swapper_inode;
+extern unsigned long page_cache_size;
+extern int buffermem;
+
+/* Incomplete types for prototype declarations: */
+struct task_struct;
+struct vm_area_struct;
+struct sysinfo;
+
+/* linux/ipc/shm.c */
+extern int shm_swap (int, int);
+
+/* linux/mm/swap.c */
+extern void swap_setup (void);
+
+/* linux/mm/vmscan.c */
+extern int try_to_free_pages(unsigned int gfp_mask);
+
+/* linux/mm/page_io.c */
+extern void rw_swap_page(int, unsigned long, char *, int);
+extern void rw_swap_page_nocache(int, unsigned long, char *);
+extern void rw_swap_page_nolock(int, unsigned long, char *, int);
+extern void swap_after_unlock_page (unsigned long entry);
+
+/* linux/mm/page_alloc.c */
+extern void swap_in(struct task_struct *, struct vm_area_struct *,
+ pte_t *, unsigned long, int);
+
+
+/* linux/mm/swap_state.c */
+extern void show_swap_cache_info(void);
+extern int add_to_swap_cache(struct page *, unsigned long);
+extern int swap_duplicate(unsigned long);
+extern int swap_check_entry(unsigned long);
+struct page * lookup_swap_cache(unsigned long);
+extern struct page * read_swap_cache_async(unsigned long, int);
+#define read_swap_cache(entry) read_swap_cache_async(entry, 1);
+extern int FASTCALL(swap_count(unsigned long));
+/*
+ * Make these inline later once they are working properly.
+ */
+extern void delete_from_swap_cache(struct page *page);
+extern void free_page_and_swap_cache(unsigned long addr);
+
+/* linux/mm/swapfile.c */
+extern unsigned int nr_swapfiles;
+extern struct swap_info_struct swap_info[];
+void si_swapinfo(struct sysinfo *);
+unsigned long get_swap_page(void);
+extern void FASTCALL(swap_free(unsigned long));
+struct swap_list_t {
+ int head; /* head of priority-ordered swapfile list */
+ int next; /* swapfile to be used next */
+};
+extern struct swap_list_t swap_list;
+asmlinkage int sys_swapoff(const char *);
+asmlinkage int sys_swapon(const char *, int);
+
+/*
+ * vm_ops not present page codes for shared memory.
+ *
+ * Will go away eventually..
+ */
+#define SHM_SWP_TYPE 0x20
+
+/*
+ * swap cache stuff (in linux/mm/swap_state.c)
+ */
+
+#define SWAP_CACHE_INFO
+
+#ifdef SWAP_CACHE_INFO
+extern unsigned long swap_cache_add_total;
+extern unsigned long swap_cache_del_total;
+extern unsigned long swap_cache_find_total;
+extern unsigned long swap_cache_find_success;
+#endif
+
+extern inline unsigned long in_swap_cache(struct page *page)
+{
+ if (PageSwapCache(page))
+ return page->offset;
+ return 0;
+}
+
+/*
+ * Work out if there are any other processes sharing this page, ignoring
+ * any page reference coming from the swap cache, or from outstanding
+ * swap IO on this page. (The page cache _does_ count as another valid
+ * reference to the page, however.)
+ */
+static inline int is_page_shared(struct page *page)
+{
+ unsigned int count;
+ if (PageReserved(page))
+ return 1;
+ count = atomic_read(&page->count);
+ if (PageSwapCache(page))
+ count += swap_count(page->offset) - 2;
+ if (PageFreeAfter(page))
+ count--;
+ return count > 1;
+}
+
+#endif /* __KERNEL__*/
+
+#endif /* _LINUX_SWAP_H */
diff --git a/pfinet/linux-src/include/linux/swapctl.h b/pfinet/linux-src/include/linux/swapctl.h
new file mode 100644
index 00000000..f9f2d2ac
--- /dev/null
+++ b/pfinet/linux-src/include/linux/swapctl.h
@@ -0,0 +1,35 @@
+#ifndef _LINUX_SWAPCTL_H
+#define _LINUX_SWAPCTL_H
+
+#include <asm/page.h>
+#include <linux/fs.h>
+
+typedef struct buffer_mem_v1
+{
+ unsigned int min_percent;
+ unsigned int borrow_percent;
+ unsigned int max_percent;
+} buffer_mem_v1;
+typedef buffer_mem_v1 buffer_mem_t;
+extern buffer_mem_t buffer_mem;
+extern buffer_mem_t page_cache;
+
+typedef struct freepages_v1
+{
+ unsigned int min;
+ unsigned int low;
+ unsigned int high;
+} freepages_v1;
+typedef freepages_v1 freepages_t;
+extern freepages_t freepages;
+
+typedef struct pager_daemon_v1
+{
+ unsigned int tries_base;
+ unsigned int tries_min;
+ unsigned int swap_cluster;
+} pager_daemon_v1;
+typedef pager_daemon_v1 pager_daemon_t;
+extern pager_daemon_t pager_daemon;
+
+#endif /* _LINUX_SWAPCTL_H */
diff --git a/pfinet/linux-src/include/linux/synclink.h b/pfinet/linux-src/include/linux/synclink.h
new file mode 100644
index 00000000..70ce90e1
--- /dev/null
+++ b/pfinet/linux-src/include/linux/synclink.h
@@ -0,0 +1,253 @@
+/*
+ * SyncLink Multiprotocol Serial Adapter Driver
+ *
+ * ==FILEDATE 19990523==
+ *
+ * Copyright (C) 1998 by Microgate Corporation
+ *
+ * Redistribution of this file is permitted under
+ * the terms of the GNU Public License (GPL)
+ */
+
+#ifndef _SYNCLINK_H_
+#define _SYNCLINK_H_
+
+#define BOOLEAN int
+#define TRUE 1
+#define FALSE 0
+
+#define BIT0 0x0001
+#define BIT1 0x0002
+#define BIT2 0x0004
+#define BIT3 0x0008
+#define BIT4 0x0010
+#define BIT5 0x0020
+#define BIT6 0x0040
+#define BIT7 0x0080
+#define BIT8 0x0100
+#define BIT9 0x0200
+#define BIT10 0x0400
+#define BIT11 0x0800
+#define BIT12 0x1000
+#define BIT13 0x2000
+#define BIT14 0x4000
+#define BIT15 0x8000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+
+
+#define HDLC_MAX_FRAME_SIZE 4096
+#define MAX_ASYNC_TRANSMIT 4096
+
+#define ASYNC_PARITY_NONE 0
+#define ASYNC_PARITY_EVEN 1
+#define ASYNC_PARITY_ODD 2
+#define ASYNC_PARITY_SPACE 3
+
+#define HDLC_FLAG_UNDERRUN_ABORT7 0x0000
+#define HDLC_FLAG_UNDERRUN_ABORT15 0x0001
+#define HDLC_FLAG_UNDERRUN_FLAG 0x0002
+#define HDLC_FLAG_UNDERRUN_CRC 0x0004
+#define HDLC_FLAG_SHARE_ZERO 0x0010
+#define HDLC_FLAG_AUTO_CTS 0x0020
+#define HDLC_FLAG_AUTO_DCD 0x0040
+#define HDLC_FLAG_AUTO_RTS 0x0080
+#define HDLC_FLAG_RXC_DPLL 0x0100
+#define HDLC_FLAG_RXC_BRG 0x0200
+#define HDLC_FLAG_RXC_TXCPIN 0x8000
+#define HDLC_FLAG_RXC_RXCPIN 0x0000
+#define HDLC_FLAG_TXC_DPLL 0x0400
+#define HDLC_FLAG_TXC_BRG 0x0800
+#define HDLC_FLAG_TXC_TXCPIN 0x0000
+#define HDLC_FLAG_TXC_RXCPIN 0x0008
+#define HDLC_FLAG_DPLL_DIV8 0x1000
+#define HDLC_FLAG_DPLL_DIV16 0x2000
+#define HDLC_FLAG_DPLL_DIV32 0x0000
+#define HDLC_FLAG_HDLC_LOOPMODE 0x4000
+
+#define HDLC_CRC_NONE 0
+#define HDLC_CRC_16_CCITT 1
+
+#define HDLC_TXIDLE_FLAGS 0
+#define HDLC_TXIDLE_ALT_ZEROS_ONES 1
+#define HDLC_TXIDLE_ZEROS 2
+#define HDLC_TXIDLE_ONES 3
+#define HDLC_TXIDLE_ALT_MARK_SPACE 4
+#define HDLC_TXIDLE_SPACE 5
+#define HDLC_TXIDLE_MARK 6
+
+#define HDLC_ENCODING_NRZ 0
+#define HDLC_ENCODING_NRZB 1
+#define HDLC_ENCODING_NRZI_MARK 2
+#define HDLC_ENCODING_NRZI_SPACE 3
+#define HDLC_ENCODING_NRZI HDLC_ENCODING_NRZI_SPACE
+#define HDLC_ENCODING_BIPHASE_MARK 4
+#define HDLC_ENCODING_BIPHASE_SPACE 5
+#define HDLC_ENCODING_BIPHASE_LEVEL 6
+#define HDLC_ENCODING_DIFF_BIPHASE_LEVEL 7
+
+#define HDLC_PREAMBLE_LENGTH_8BITS 0
+#define HDLC_PREAMBLE_LENGTH_16BITS 1
+#define HDLC_PREAMBLE_LENGTH_32BITS 2
+#define HDLC_PREAMBLE_LENGTH_64BITS 3
+
+#define HDLC_PREAMBLE_PATTERN_NONE 0
+#define HDLC_PREAMBLE_PATTERN_ZEROS 1
+#define HDLC_PREAMBLE_PATTERN_FLAGS 2
+#define HDLC_PREAMBLE_PATTERN_10 3
+#define HDLC_PREAMBLE_PATTERN_01 4
+#define HDLC_PREAMBLE_PATTERN_ONES 5
+
+#define MGSL_MODE_ASYNC 1
+#define MGSL_MODE_HDLC 2
+
+#define MGSL_BUS_TYPE_ISA 1
+#define MGSL_BUS_TYPE_EISA 2
+#define MGSL_BUS_TYPE_PCI 5
+
+typedef struct _MGSL_PARAMS
+{
+ /* Common */
+
+ unsigned long mode; /* Asynchronous or HDLC */
+ unsigned char loopback; /* internal loopback mode */
+
+ /* HDLC Only */
+
+ unsigned short flags;
+ unsigned char encoding; /* NRZ, NRZI, etc. */
+ unsigned long clock_speed; /* external clock speed in bits per second */
+ unsigned char addr_filter; /* receive HDLC address filter, 0xFF = disable */
+ unsigned short crc_type; /* None, CRC16 or CRC16-CCITT */
+ unsigned char preamble_length;
+ unsigned char preamble;
+
+ /* Async Only */
+
+ unsigned long data_rate; /* bits per second */
+ unsigned char data_bits; /* 7 or 8 data bits */
+ unsigned char stop_bits; /* 1 or 2 stop bits */
+ unsigned char parity; /* none, even, or odd */
+
+} MGSL_PARAMS, *PMGSL_PARAMS;
+
+#define MICROGATE_VENDOR_ID 0x13c0
+#define SYNCLINK_DEVICE_ID 0x0010
+#define MGSL_MAX_SERIAL_NUMBER 30
+
+/*
+** device diagnostics status
+*/
+
+#define DiagStatus_OK 0
+#define DiagStatus_AddressFailure 1
+#define DiagStatus_AddressConflict 2
+#define DiagStatus_IrqFailure 3
+#define DiagStatus_IrqConflict 4
+#define DiagStatus_DmaFailure 5
+#define DiagStatus_DmaConflict 6
+#define DiagStatus_PciAdapterNotFound 7
+#define DiagStatus_CantAssignPciResources 8
+#define DiagStatus_CantAssignPciMemAddr 9
+#define DiagStatus_CantAssignPciIoAddr 10
+#define DiagStatus_CantAssignPciIrq 11
+#define DiagStatus_MemoryError 12
+
+#define SerialSignal_DCD 0x01 /* Data Carrier Detect */
+#define SerialSignal_TXD 0x02 /* Transmit Data */
+#define SerialSignal_RI 0x04 /* Ring Indicator */
+#define SerialSignal_RXD 0x08 /* Receive Data */
+#define SerialSignal_CTS 0x10 /* Clear to Send */
+#define SerialSignal_RTS 0x20 /* Request to Send */
+#define SerialSignal_DSR 0x40 /* Data Set Ready */
+#define SerialSignal_DTR 0x80 /* Data Terminal Ready */
+
+
+/*
+ * Counters of the input lines (CTS, DSR, RI, CD) interrupts
+ */
+struct mgsl_icount {
+ __u32 cts, dsr, rng, dcd, tx, rx;
+ __u32 frame, parity, overrun, brk;
+ __u32 buf_overrun;
+ __u32 txok;
+ __u32 txunder;
+ __u32 txabort;
+ __u32 txtimeout;
+ __u32 rxshort;
+ __u32 rxlong;
+ __u32 rxabort;
+ __u32 rxover;
+ __u32 rxcrc;
+ __u32 rxok;
+ __u32 exithunt;
+ __u32 rxidle;
+};
+
+
+#define DEBUG_LEVEL_DATA 1
+#define DEBUG_LEVEL_ERROR 2
+#define DEBUG_LEVEL_INFO 3
+#define DEBUG_LEVEL_BH 4
+#define DEBUG_LEVEL_ISR 5
+
+/*
+** Event bit flags for use with MgslWaitEvent
+*/
+
+#define MgslEvent_DsrActive 0x0001
+#define MgslEvent_DsrInactive 0x0002
+#define MgslEvent_Dsr 0x0003
+#define MgslEvent_CtsActive 0x0004
+#define MgslEvent_CtsInactive 0x0008
+#define MgslEvent_Cts 0x000c
+#define MgslEvent_DcdActive 0x0010
+#define MgslEvent_DcdInactive 0x0020
+#define MgslEvent_Dcd 0x0030
+#define MgslEvent_RiActive 0x0040
+#define MgslEvent_RiInactive 0x0080
+#define MgslEvent_Ri 0x00c0
+#define MgslEvent_ExitHuntMode 0x0100
+#define MgslEvent_IdleReceived 0x0200
+
+/* Private IOCTL codes:
+ *
+ * MGSL_IOCSPARAMS set MGSL_PARAMS structure values
+ * MGSL_IOCGPARAMS get current MGSL_PARAMS structure values
+ * MGSL_IOCSTXIDLE set current transmit idle mode
+ * MGSL_IOCGTXIDLE get current transmit idle mode
+ * MGSL_IOCTXENABLE enable or disable transmitter
+ * MGSL_IOCRXENABLE enable or disable receiver
+ * MGSL_IOCTXABORT abort transmitting frame (HDLC)
+ * MGSL_IOCGSTATS return current statistics
+ * MGSL_IOCWAITEVENT wait for specified event to occur
+ * MGSL_LOOPTXDONE transmit in HDLC LoopMode done
+ */
+#define MGSL_MAGIC_IOC 'm'
+#define MGSL_IOCSPARAMS _IOW(MGSL_MAGIC_IOC,0,struct _MGSL_PARAMS)
+#define MGSL_IOCGPARAMS _IOR(MGSL_MAGIC_IOC,1,struct _MGSL_PARAMS)
+#define MGSL_IOCSTXIDLE _IO(MGSL_MAGIC_IOC,2)
+#define MGSL_IOCGTXIDLE _IO(MGSL_MAGIC_IOC,3)
+#define MGSL_IOCTXENABLE _IO(MGSL_MAGIC_IOC,4)
+#define MGSL_IOCRXENABLE _IO(MGSL_MAGIC_IOC,5)
+#define MGSL_IOCTXABORT _IO(MGSL_MAGIC_IOC,6)
+#define MGSL_IOCGSTATS _IO(MGSL_MAGIC_IOC,7)
+#define MGSL_IOCWAITEVENT _IOWR(MGSL_MAGIC_IOC,8,int)
+#define MGSL_IOCCLRMODCOUNT _IO(MGSL_MAGIC_IOC,15)
+#define MGSL_IOCLOOPTXDONE _IO(MGSL_MAGIC_IOC,9)
+
+#endif /* _SYNCLINK_H_ */
diff --git a/pfinet/linux-src/include/linux/sys.h b/pfinet/linux-src/include/linux/sys.h
new file mode 100644
index 00000000..dcd32566
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sys.h
@@ -0,0 +1,30 @@
+#ifndef _LINUX_SYS_H
+#define _LINUX_SYS_H
+
+/*
+ * system call entry points ... but not all are defined
+ */
+#define NR_syscalls 256
+
+/*
+ * These are system calls that will be removed at some time
+ * due to newer versions existing..
+ * (please be careful - ibcs2 may need some of these).
+ */
+#ifdef notdef
+#define _sys_waitpid _sys_old_syscall /* _sys_wait4 */
+#define _sys_olduname _sys_old_syscall /* _sys_newuname */
+#define _sys_uname _sys_old_syscall /* _sys_newuname */
+#define _sys_stat _sys_old_syscall /* _sys_newstat */
+#define _sys_fstat _sys_old_syscall /* _sys_newfstat */
+#define _sys_lstat _sys_old_syscall /* _sys_newlstat */
+#define _sys_signal _sys_old_syscall /* _sys_sigaction */
+#define _sys_sgetmask _sys_old_syscall /* _sys_sigprocmask */
+#define _sys_ssetmask _sys_old_syscall /* _sys_sigprocmask */
+#endif
+
+/*
+ * These are system calls that haven't been implemented yet
+ * but have an entry in the table for future expansion..
+ */
+#endif
diff --git a/pfinet/linux-src/include/linux/sysctl.h b/pfinet/linux-src/include/linux/sysctl.h
new file mode 100644
index 00000000..aba1498a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sysctl.h
@@ -0,0 +1,555 @@
+/*
+ * sysctl.h: General linux system control interface
+ *
+ * Begun 24 March 1995, Stephen Tweedie
+ *
+ ****************************************************************
+ ****************************************************************
+ **
+ ** WARNING:
+ ** The values in this file are exported to user space via
+ ** the sysctl() binary interface. Do *NOT* change the
+ ** numbering of any existing values here, and do not change
+ ** any numbers within any one set of values. If you have
+ ** to redefine an existing interface, use a new number for it.
+ ** The kernel will then return ENOTDIR to any application using
+ ** the old binary interface.
+ **
+ ** --sct
+ **
+ ****************************************************************
+ ****************************************************************
+ */
+
+#include <linux/lists.h>
+
+#ifndef _LINUX_SYSCTL_H
+#define _LINUX_SYSCTL_H
+
+#define CTL_MAXNAME 10
+
+struct __sysctl_args {
+ int *name;
+ int nlen;
+ void *oldval;
+ size_t *oldlenp;
+ void *newval;
+ size_t newlen;
+ unsigned long __unused[4];
+};
+
+/* Define sysctl names first */
+
+/* Top-level names: */
+
+/* For internal pattern-matching use only: */
+#ifdef __KERNEL__
+#define CTL_ANY -1 /* Matches any name */
+#define CTL_NONE 0
+#endif
+
+enum
+{
+ CTL_KERN=1, /* General kernel info and control */
+ CTL_VM=2, /* VM management */
+ CTL_NET=3, /* Networking */
+ CTL_PROC=4, /* Process info */
+ CTL_FS=5, /* Filesystems */
+ CTL_DEBUG=6, /* Debugging */
+ CTL_DEV=7, /* Devices */
+ CTL_BUS=8 /* Buses */
+};
+
+/* CTL_BUS names: */
+enum
+{
+ BUS_ISA=1 /* ISA */
+};
+
+/* CTL_KERN names: */
+enum
+{
+ KERN_OSTYPE=1, /* string: system version */
+ KERN_OSRELEASE=2, /* string: system release */
+ KERN_OSREV=3, /* int: system revision */
+ KERN_VERSION=4, /* string: compile time info */
+ KERN_SECUREMASK=5, /* struct: maximum rights mask */
+ KERN_PROF=6, /* table: profiling information */
+ KERN_NODENAME=7,
+ KERN_DOMAINNAME=8,
+
+ KERN_CAP_BSET=14, /* int: capability bounding set */
+ KERN_PANIC=15, /* int: panic timeout */
+ KERN_REALROOTDEV=16, /* real root device to mount after initrd */
+
+ KERN_JAVA_INTERPRETER=19, /* path to Java(tm) interpreter */
+ KERN_JAVA_APPLETVIEWER=20, /* path to Java(tm) appletviewer */
+ KERN_SPARC_REBOOT=21, /* reboot command on Sparc */
+ KERN_CTLALTDEL=22, /* int: allow ctl-alt-del to reboot */
+ KERN_PRINTK=23, /* struct: control printk logging parameters */
+ KERN_NAMETRANS=24, /* Name translation */
+ KERN_PPC_HTABRECLAIM=25, /* turn htab reclaimation on/off on PPC */
+ KERN_PPC_ZEROPAGED=26, /* turn idle page zeroing on/off on PPC */
+ KERN_PPC_POWERSAVE_NAP=27, /* use nap mode for power saving */
+ KERN_MODPROBE=28,
+ KERN_SG_BIG_BUFF=29,
+ KERN_ACCT=30, /* BSD process accounting parameters */
+ KERN_PPC_L2CR=31, /* l2cr register on PPC */
+
+ KERN_RTSIGNR=32, /* Number of rt sigs queued */
+ KERN_RTSIGMAX=33, /* Max queuable */
+
+ KERN_SHMMAX=34, /* int: Maximum shared memory segment */
+ KERN_MSGMAX=35, /* int: Maximum size of a messege */
+ KERN_MSGMNB=36, /* int: Maximum message queue size */
+ KERN_MSGPOOL=37, /* int: Maximum system message pool size */
+ KERN_SYSRQ=38 /* int: Sysreq enable */
+};
+
+
+/* CTL_VM names: */
+enum
+{
+ VM_SWAPCTL=1, /* struct: Set vm swapping control */
+ VM_SWAPOUT=2, /* int: Background pageout interval */
+ VM_FREEPG=3, /* struct: Set free page thresholds */
+ VM_BDFLUSH=4, /* struct: Control buffer cache flushing */
+ VM_OVERCOMMIT_MEMORY=5, /* Turn off the virtual memory safety limit */
+ VM_BUFFERMEM=6, /* struct: Set buffer memory thresholds */
+ VM_PAGECACHE=7, /* struct: Set cache memory thresholds */
+ VM_PAGERDAEMON=8, /* struct: Control kswapd behaviour */
+ VM_PGT_CACHE=9, /* struct: Set page table cache parameters */
+ VM_PAGE_CLUSTER=10 /* int: set number of pages to swap together */
+};
+
+
+/* CTL_NET names: */
+enum
+{
+ NET_CORE=1,
+ NET_ETHER=2,
+ NET_802=3,
+ NET_UNIX=4,
+ NET_IPV4=5,
+ NET_IPX=6,
+ NET_ATALK=7,
+ NET_NETROM=8,
+ NET_AX25=9,
+ NET_BRIDGE=10,
+ NET_ROSE=11,
+ NET_IPV6=12,
+ NET_X25=13,
+ NET_TR=14,
+ NET_DECNET=15,
+ NET_ECONET=16
+};
+
+/* /proc/sys/bus/isa */
+enum
+{
+ BUS_ISA_MEM_BASE=1,
+ BUS_ISA_PORT_BASE=2,
+ BUS_ISA_PORT_SHIFT=3
+};
+
+/* /proc/sys/net/core */
+enum
+{
+ NET_CORE_WMEM_MAX=1,
+ NET_CORE_RMEM_MAX=2,
+ NET_CORE_WMEM_DEFAULT=3,
+ NET_CORE_RMEM_DEFAULT=4,
+/* was NET_CORE_DESTROY_DELAY */
+ NET_CORE_MAX_BACKLOG=6,
+ NET_CORE_FASTROUTE=7,
+ NET_CORE_MSG_COST=8,
+ NET_CORE_MSG_BURST=9,
+ NET_CORE_OPTMEM_MAX=10
+};
+
+/* /proc/sys/net/ethernet */
+
+/* /proc/sys/net/802 */
+
+/* /proc/sys/net/unix */
+
+enum
+{
+ NET_UNIX_DESTROY_DELAY=1,
+ NET_UNIX_DELETE_DELAY=2,
+ NET_UNIX_MAX_DGRAM_QLEN=3,
+};
+
+/* /proc/sys/net/ipv4 */
+enum
+{
+ /* v2.0 compatibile variables */
+ NET_IPV4_FORWARD=8,
+ NET_IPV4_DYNADDR=9,
+
+ NET_IPV4_CONF=16,
+ NET_IPV4_NEIGH=17,
+ NET_IPV4_ROUTE=18,
+ NET_IPV4_FIB_HASH=19,
+
+ NET_IPV4_TCP_TIMESTAMPS=33,
+ NET_IPV4_TCP_WINDOW_SCALING=34,
+ NET_IPV4_TCP_SACK=35,
+ NET_IPV4_TCP_RETRANS_COLLAPSE=36,
+ NET_IPV4_DEFAULT_TTL=37,
+ NET_IPV4_AUTOCONFIG=38,
+ NET_IPV4_NO_PMTU_DISC=39,
+ NET_IPV4_TCP_SYN_RETRIES=40,
+ NET_IPV4_IPFRAG_HIGH_THRESH=41,
+ NET_IPV4_IPFRAG_LOW_THRESH=42,
+ NET_IPV4_IPFRAG_TIME=43,
+ NET_IPV4_TCP_MAX_KA_PROBES=44,
+ NET_IPV4_TCP_KEEPALIVE_TIME=45,
+ NET_IPV4_TCP_KEEPALIVE_PROBES=46,
+ NET_IPV4_TCP_RETRIES1=47,
+ NET_IPV4_TCP_RETRIES2=48,
+ NET_IPV4_TCP_FIN_TIMEOUT=49,
+ NET_IPV4_IP_MASQ_DEBUG=50,
+ NET_TCP_SYNCOOKIES=51,
+ NET_TCP_STDURG=52,
+ NET_TCP_RFC1337=53,
+ NET_TCP_SYN_TAILDROP=54,
+ NET_TCP_MAX_SYN_BACKLOG=55,
+ NET_IPV4_LOCAL_PORT_RANGE=56,
+ NET_IPV4_ICMP_ECHO_IGNORE_ALL=57,
+ NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS=58,
+ NET_IPV4_ICMP_SOURCEQUENCH_RATE=59,
+ NET_IPV4_ICMP_DESTUNREACH_RATE=60,
+ NET_IPV4_ICMP_TIMEEXCEED_RATE=61,
+ NET_IPV4_ICMP_PARAMPROB_RATE=62,
+ NET_IPV4_ICMP_ECHOREPLY_RATE=63,
+ NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=64,
+ NET_IPV4_IGMP_MAX_MEMBERSHIPS=65
+};
+
+enum {
+ NET_IPV4_ROUTE_FLUSH=1,
+ NET_IPV4_ROUTE_MIN_DELAY=2,
+ NET_IPV4_ROUTE_MAX_DELAY=3,
+ NET_IPV4_ROUTE_GC_THRESH=4,
+ NET_IPV4_ROUTE_MAX_SIZE=5,
+ NET_IPV4_ROUTE_GC_MIN_INTERVAL=6,
+ NET_IPV4_ROUTE_GC_TIMEOUT=7,
+ NET_IPV4_ROUTE_GC_INTERVAL=8,
+ NET_IPV4_ROUTE_REDIRECT_LOAD=9,
+ NET_IPV4_ROUTE_REDIRECT_NUMBER=10,
+ NET_IPV4_ROUTE_REDIRECT_SILENCE=11,
+ NET_IPV4_ROUTE_ERROR_COST=12,
+ NET_IPV4_ROUTE_ERROR_BURST=13,
+ NET_IPV4_ROUTE_GC_ELASTICITY=14,
+ NET_IPV4_ROUTE_MTU_EXPIRES=15
+};
+
+enum
+{
+ NET_PROTO_CONF_ALL=-2,
+ NET_PROTO_CONF_DEFAULT=-3
+
+ /* And device ifindices ... */
+};
+
+enum
+{
+ NET_IPV4_CONF_FORWARDING=1,
+ NET_IPV4_CONF_MC_FORWARDING=2,
+ NET_IPV4_CONF_PROXY_ARP=3,
+ NET_IPV4_CONF_ACCEPT_REDIRECTS=4,
+ NET_IPV4_CONF_SECURE_REDIRECTS=5,
+ NET_IPV4_CONF_SEND_REDIRECTS=6,
+ NET_IPV4_CONF_SHARED_MEDIA=7,
+ NET_IPV4_CONF_RP_FILTER=8,
+ NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9,
+ NET_IPV4_CONF_BOOTP_RELAY=10,
+ NET_IPV4_CONF_LOG_MARTIANS=11
+};
+
+/* /proc/sys/net/ipv6 */
+enum {
+ NET_IPV6_CONF=16,
+ NET_IPV6_NEIGH=17,
+ NET_IPV6_ROUTE=18
+};
+
+enum {
+ NET_IPV6_ROUTE_FLUSH=1,
+ NET_IPV6_ROUTE_GC_THRESH=2,
+ NET_IPV6_ROUTE_MAX_SIZE=3,
+ NET_IPV6_ROUTE_GC_MIN_INTERVAL=4,
+ NET_IPV6_ROUTE_GC_TIMEOUT=5,
+ NET_IPV6_ROUTE_GC_INTERVAL=6,
+ NET_IPV6_ROUTE_GC_ELASTICITY=7,
+ NET_IPV6_ROUTE_MTU_EXPIRES=8
+};
+
+enum {
+ NET_IPV6_FORWARDING=1,
+ NET_IPV6_HOP_LIMIT=2,
+ NET_IPV6_MTU=3,
+ NET_IPV6_ACCEPT_RA=4,
+ NET_IPV6_ACCEPT_REDIRECTS=5,
+ NET_IPV6_AUTOCONF=6,
+ NET_IPV6_DAD_TRANSMITS=7,
+ NET_IPV6_RTR_SOLICITS=8,
+ NET_IPV6_RTR_SOLICIT_INTERVAL=9,
+ NET_IPV6_RTR_SOLICIT_DELAY=10
+};
+
+/* /proc/sys/net/<protocol>/neigh/<dev> */
+enum {
+ NET_NEIGH_MCAST_SOLICIT=1,
+ NET_NEIGH_UCAST_SOLICIT=2,
+ NET_NEIGH_APP_SOLICIT=3,
+ NET_NEIGH_RETRANS_TIME=4,
+ NET_NEIGH_REACHABLE_TIME=5,
+ NET_NEIGH_DELAY_PROBE_TIME=6,
+ NET_NEIGH_GC_STALE_TIME=7,
+ NET_NEIGH_UNRES_QLEN=8,
+ NET_NEIGH_PROXY_QLEN=9,
+ NET_NEIGH_ANYCAST_DELAY=10,
+ NET_NEIGH_PROXY_DELAY=11,
+ NET_NEIGH_LOCKTIME=12,
+ NET_NEIGH_GC_INTERVAL=13,
+ NET_NEIGH_GC_THRESH1=14,
+ NET_NEIGH_GC_THRESH2=15,
+ NET_NEIGH_GC_THRESH3=16
+};
+
+/* /proc/sys/net/ipx */
+
+
+/* /proc/sys/net/appletalk */
+enum {
+ NET_ATALK_AARP_EXPIRY_TIME=1,
+ NET_ATALK_AARP_TICK_TIME=2,
+ NET_ATALK_AARP_RETRANSMIT_LIMIT=3,
+ NET_ATALK_AARP_RESOLVE_TIME=4
+};
+
+
+/* /proc/sys/net/netrom */
+enum {
+ NET_NETROM_DEFAULT_PATH_QUALITY=1,
+ NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER=2,
+ NET_NETROM_NETWORK_TTL_INITIALISER=3,
+ NET_NETROM_TRANSPORT_TIMEOUT=4,
+ NET_NETROM_TRANSPORT_MAXIMUM_TRIES=5,
+ NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY=6,
+ NET_NETROM_TRANSPORT_BUSY_DELAY=7,
+ NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE=8,
+ NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT=9,
+ NET_NETROM_ROUTING_CONTROL=10,
+ NET_NETROM_LINK_FAILS_COUNT=11
+};
+
+/* /proc/sys/net/ax25 */
+enum {
+ NET_AX25_IP_DEFAULT_MODE=1,
+ NET_AX25_DEFAULT_MODE=2,
+ NET_AX25_BACKOFF_TYPE=3,
+ NET_AX25_CONNECT_MODE=4,
+ NET_AX25_STANDARD_WINDOW=5,
+ NET_AX25_EXTENDED_WINDOW=6,
+ NET_AX25_T1_TIMEOUT=7,
+ NET_AX25_T2_TIMEOUT=8,
+ NET_AX25_T3_TIMEOUT=9,
+ NET_AX25_IDLE_TIMEOUT=10,
+ NET_AX25_N2=11,
+ NET_AX25_PACLEN=12,
+ NET_AX25_PROTOCOL=13,
+ NET_AX25_DAMA_SLAVE_TIMEOUT=14
+};
+
+/* /proc/sys/net/rose */
+enum {
+ NET_ROSE_RESTART_REQUEST_TIMEOUT=1,
+ NET_ROSE_CALL_REQUEST_TIMEOUT=2,
+ NET_ROSE_RESET_REQUEST_TIMEOUT=3,
+ NET_ROSE_CLEAR_REQUEST_TIMEOUT=4,
+ NET_ROSE_ACK_HOLD_BACK_TIMEOUT=5,
+ NET_ROSE_ROUTING_CONTROL=6,
+ NET_ROSE_LINK_FAIL_TIMEOUT=7,
+ NET_ROSE_MAX_VCS=8,
+ NET_ROSE_WINDOW_SIZE=9,
+ NET_ROSE_NO_ACTIVITY_TIMEOUT=10
+};
+
+/* /proc/sys/net/x25 */
+enum {
+ NET_X25_RESTART_REQUEST_TIMEOUT=1,
+ NET_X25_CALL_REQUEST_TIMEOUT=2,
+ NET_X25_RESET_REQUEST_TIMEOUT=3,
+ NET_X25_CLEAR_REQUEST_TIMEOUT=4,
+ NET_X25_ACK_HOLD_BACK_TIMEOUT=5
+};
+
+/* /proc/sys/net/token-ring */
+enum
+{
+ NET_TR_RIF_TIMEOUT=1
+};
+
+/* /proc/sys/net/decnet */
+enum {
+ NET_DECNET_DEF_T3_BROADCAST=1,
+ NET_DECNET_DEF_T3_POINTTOPOINT=2,
+ NET_DECNET_DEF_T1=3,
+ NET_DECNET_DEF_BCT1=4,
+ NET_DECNET_CACHETIMEOUT=5,
+ NET_DECNET_DEBUG_LEVEL=6
+};
+
+/* CTL_PROC names: */
+
+/* CTL_FS names: */
+enum
+{
+ FS_NRINODE=1, /* int:current number of allocated inodes */
+ FS_STATINODE=2,
+ FS_MAXINODE=3, /* int:maximum number of inodes that can be allocated */
+ FS_NRDQUOT=4, /* int:current number of allocated dquots */
+ FS_MAXDQUOT=5, /* int:maximum number of dquots that can be allocated */
+ FS_NRFILE=6, /* int:current number of allocated filedescriptors */
+ FS_MAXFILE=7, /* int:maximum number of filedescriptors that can be allocated */
+ FS_DENTRY=8,
+ FS_NRSUPER=9, /* int:current number of allocated super_blocks */
+ FS_MAXSUPER=10 /* int:maximum number of super_blocks that can be allocated */
+};
+
+/* CTL_DEBUG names: */
+
+/* CTL_DEV names: */
+enum {
+ DEV_CDROM=1,
+ DEV_HWMON=2
+};
+
+/* /proc/sys/dev/cdrom */
+enum {
+ DEV_CDROM_INFO=1
+};
+
+#ifdef __KERNEL__
+
+extern asmlinkage int sys_sysctl(struct __sysctl_args *);
+extern void sysctl_init(void);
+
+typedef struct ctl_table ctl_table;
+
+typedef int ctl_handler (ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen,
+ void **context);
+
+typedef int proc_handler (ctl_table *ctl, int write, struct file * filp,
+ void *buffer, size_t *lenp);
+
+extern int proc_dostring(ctl_table *, int, struct file *,
+ void *, size_t *);
+extern int proc_dointvec(ctl_table *, int, struct file *,
+ void *, size_t *);
+extern int proc_dointvec_bset(ctl_table *, int, struct file *,
+ void *, size_t *);
+extern int proc_dointvec_minmax(ctl_table *, int, struct file *,
+ void *, size_t *);
+extern int proc_dointvec_jiffies(ctl_table *, int, struct file *,
+ void *, size_t *);
+
+extern int do_sysctl (int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen);
+
+extern int do_sysctl_strategy (ctl_table *table,
+ int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen, void ** context);
+
+extern ctl_handler sysctl_string;
+extern ctl_handler sysctl_intvec;
+extern ctl_handler sysctl_jiffies;
+
+extern int do_string (
+ void *oldval, size_t *oldlenp, void *newval, size_t newlen,
+ int rdwr, char *data, size_t max);
+extern int do_int (
+ void *oldval, size_t *oldlenp, void *newval, size_t newlen,
+ int rdwr, int *data);
+extern int do_struct (
+ void *oldval, size_t *oldlenp, void *newval, size_t newlen,
+ int rdwr, void *data, size_t len);
+
+
+/*
+ * Register a set of sysctl names by calling register_sysctl_table
+ * with an initialised array of ctl_table's. An entry with zero
+ * ctl_name terminates the table. table->de will be set up by the
+ * registration and need not be initialised in advance.
+ *
+ * sysctl names can be mirrored automatically under /proc/sys. The
+ * procname supplied controls /proc naming.
+ *
+ * The table's mode will be honoured both for sys_sysctl(2) and
+ * proc-fs access.
+ *
+ * Leaf nodes in the sysctl tree will be represented by a single file
+ * under /proc; non-leaf nodes will be represented by directories. A
+ * null procname disables /proc mirroring at this node.
+ *
+ * sysctl(2) can automatically manage read and write requests through
+ * the sysctl table. The data and maxlen fields of the ctl_table
+ * struct enable minimal validation of the values being written to be
+ * performed, and the mode field allows minimal authentication.
+ *
+ * More sophisticated management can be enabled by the provision of a
+ * strategy routine with the table entry. This will be called before
+ * any automatic read or write of the data is performed.
+ *
+ * The strategy routine may return:
+ * <0: Error occurred (error is passed to user process)
+ * 0: OK - proceed with automatic read or write.
+ * >0: OK - read or write has been done by the strategy routine, so
+ * return immediately.
+ *
+ * There must be a proc_handler routine for any terminal nodes
+ * mirrored under /proc/sys (non-terminals are handled by a built-in
+ * directory handler). Several default handlers are available to
+ * cover common cases.
+ */
+
+/* A sysctl table is an array of struct ctl_table: */
+struct ctl_table
+{
+ int ctl_name; /* Binary ID */
+ const char *procname; /* Text ID for /proc/sys, or zero */
+ void *data;
+ int maxlen;
+ mode_t mode;
+ ctl_table *child;
+ proc_handler *proc_handler; /* Callback for text formatting */
+ ctl_handler *strategy; /* Callback function for all r/w */
+ struct proc_dir_entry *de; /* /proc control block */
+ void *extra1;
+ void *extra2;
+};
+
+/* struct ctl_table_header is used to maintain dynamic lists of
+ ctl_table trees. */
+struct ctl_table_header
+{
+ ctl_table *ctl_table;
+ DLNODE(struct ctl_table_header) ctl_entry;
+};
+
+struct ctl_table_header * register_sysctl_table(ctl_table * table,
+ int insert_at_head);
+void unregister_sysctl_table(struct ctl_table_header * table);
+
+#else /* __KERNEL__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SYSCTL_H */
diff --git a/pfinet/linux-src/include/linux/sysrq.h b/pfinet/linux-src/include/linux/sysrq.h
new file mode 100644
index 00000000..6c080adb
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sysrq.h
@@ -0,0 +1,40 @@
+/* -*- linux-c -*-
+ *
+ * $Id: sysrq.h,v 1.3 1997/07/17 11:54:33 mj Exp $
+ *
+ * Linux Magic System Request Key Hacks
+ *
+ * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <linux/config.h>
+
+struct pt_regs;
+struct kbd_struct;
+struct tty_struct;
+
+/* Generic SysRq interface -- you may call it from any device driver, supplying
+ * ASCII code of the key, pointer to registers and kbd/tty structs (if they
+ * are available -- else NULL's).
+ */
+
+void handle_sysrq(int, struct pt_regs *, struct kbd_struct *, struct tty_struct *);
+
+/* Deferred actions */
+
+extern int emergency_sync_scheduled;
+
+#define EMERG_SYNC 1
+#define EMERG_REMOUNT 2
+
+void do_emergency_sync(void);
+
+#ifdef CONFIG_MAGIC_SYSRQ
+#define CHECK_EMERGENCY_SYNC \
+ if (emergency_sync_scheduled) \
+ do_emergency_sync();
+#else
+#define CHECK_EMERGENCY_SYNC
+#endif
+
+extern int sysrq_enabled;
diff --git a/pfinet/linux-src/include/linux/sysv_fs.h b/pfinet/linux-src/include/linux/sysv_fs.h
new file mode 100644
index 00000000..49d9d24f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sysv_fs.h
@@ -0,0 +1,414 @@
+#ifndef _LINUX_SYSV_FS_H
+#define _LINUX_SYSV_FS_H
+
+/*
+ * The SystemV/Coherent filesystem constants/structures/macros
+ */
+
+
+/* This code assumes
+ - a little endian processor like 386,
+ - sizeof(short) = 2, sizeof(int) = 4, sizeof(long) = 4,
+ - alignof(short) = 2, alignof(long) = 4.
+*/
+
+#ifdef __GNUC__
+#define __packed2__ __attribute__ ((packed, aligned(2)))
+#else
+#error I want gcc!
+#endif
+
+#include <linux/stat.h> /* declares S_IFLNK etc. */
+#include <linux/sched.h> /* declares wake_up() */
+#include <linux/sysv_fs_sb.h> /* defines the sv_... shortcuts */
+
+
+/* Layout on disk */
+/* ============== */
+
+
+/* The block size is sb->sv_block_size which may be smaller than BLOCK_SIZE. */
+
+/* zones (= data allocation units) are blocks */
+
+/* On Coherent FS, 32 bit quantities are stored using (I quote the Coherent
+ manual) a "canonical byte ordering". This is the PDP-11 byte ordering:
+ x = 2^24 * byte3 + 2^16 * byte2 + 2^8 * byte1 + byte0 is stored
+ as { byte2, byte3, byte0, byte1 }. We need conversions.
+*/
+
+typedef u32 coh_ulong;
+
+static inline coh_ulong to_coh_ulong (u32 x)
+{
+ return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
+}
+
+static inline u32 from_coh_ulong (coh_ulong x)
+{
+ return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
+}
+
+/* inode numbers are 16 bit */
+
+typedef u16 sysv_ino_t;
+
+/* Block numbers are 24 bit, sometimes stored in 32 bit.
+ On Coherent FS, they are always stored in PDP-11 manner: the least
+ significant 16 bits come last.
+*/
+
+typedef u32 sysv_zone_t;
+
+/* Among the blocks ... */
+/* Xenix FS, Coherent FS: block 0 is the boot block, block 1 the super-block.
+ SystemV FS: block 0 contains both the boot sector and the super-block. */
+/* The first inode zone is sb->sv_firstinodezone (1 or 2). */
+
+/* Among the inodes ... */
+/* 0 is non-existent */
+#define SYSV_BADBL_INO 1 /* inode of bad blocks file */
+#define SYSV_ROOT_INO 2 /* inode of root directory */
+
+
+/* Xenix super-block data on disk */
+#define XENIX_NICINOD 100 /* number of inode cache entries */
+#define XENIX_NICFREE 100 /* number of free block list chunk entries */
+struct xenix_super_block {
+ u16 s_isize; /* index of first data zone */
+ u32 s_fsize __packed2__; /* total number of zones of this fs */
+ /* the start of the free block list: */
+ u16 s_nfree; /* number of free blocks in s_free, <= XENIX_NICFREE */
+ u32 s_free[XENIX_NICFREE]; /* first free block list chunk */
+ /* the cache of free inodes: */
+ u16 s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
+ sysv_ino_t s_inode[XENIX_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+ u32 s_time __packed2__; /* time of last super block update */
+ u32 s_tfree __packed2__; /* total number of free zones */
+ u16 s_tinode; /* total number of free inodes */
+ s16 s_dinfo[4]; /* device information ?? */
+ char s_fname[6]; /* file system volume name */
+ char s_fpack[6]; /* file system pack name */
+ char s_clean; /* set to 0x46 when filesystem is properly unmounted */
+ char s_fill[371];
+ s32 s_magic; /* version of file system */
+ s32 s_type; /* type of file system: 1 for 512 byte blocks
+ 2 for 1024 byte blocks
+ 3 for 2048 byte blocks */
+
+};
+
+/* Xenix free list block on disk */
+struct xenix_freelist_chunk {
+ u16 fl_nfree; /* number of free blocks in fl_free, <= XENIX_NICFREE] */
+ u32 fl_free[XENIX_NICFREE] __packed2__;
+};
+
+/* SystemV FS comes in two variants:
+ * sysv2: System V Release 2 (e.g. Microport), structure elements aligned(2).
+ * sysv4: System V Release 4 (e.g. Consensys), structure elements aligned(4).
+ */
+#define SYSV_NICINOD 100 /* number of inode cache entries */
+#define SYSV_NICFREE 50 /* number of free block list chunk entries */
+
+/* SystemV4 super-block data on disk */
+struct sysv4_super_block {
+ u16 s_isize; /* index of first data zone */
+ u16 s_pad0;
+ u32 s_fsize; /* total number of zones of this fs */
+ /* the start of the free block list: */
+ u16 s_nfree; /* number of free blocks in s_free, <= SYSV_NICFREE */
+ u16 s_pad1;
+ u32 s_free[SYSV_NICFREE]; /* first free block list chunk */
+ /* the cache of free inodes: */
+ u16 s_ninode; /* number of free inodes in s_inode, <= SYSV_NICINOD */
+ u16 s_pad2;
+ sysv_ino_t s_inode[SYSV_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+ u32 s_time; /* time of last super block update */
+ s16 s_dinfo[4]; /* device information ?? */
+ u32 s_tfree; /* total number of free zones */
+ u16 s_tinode; /* total number of free inodes */
+ u16 s_pad3;
+ char s_fname[6]; /* file system volume name */
+ char s_fpack[6]; /* file system pack name */
+ s32 s_fill[12];
+ s32 s_state; /* file system state: 0x7c269d38-s_time means clean */
+ s32 s_magic; /* version of file system */
+ s32 s_type; /* type of file system: 1 for 512 byte blocks
+ 2 for 1024 byte blocks */
+};
+
+/* SystemV4 free list block on disk */
+struct sysv4_freelist_chunk {
+ u16 fl_nfree; /* number of free blocks in fl_free, <= SYSV_NICFREE] */
+ u32 fl_free[SYSV_NICFREE];
+};
+
+/* SystemV2 super-block data on disk */
+struct sysv2_super_block {
+ u16 s_isize; /* index of first data zone */
+ u32 s_fsize __packed2__; /* total number of zones of this fs */
+ /* the start of the free block list: */
+ u16 s_nfree; /* number of free blocks in s_free, <= SYSV_NICFREE */
+ u32 s_free[SYSV_NICFREE]; /* first free block list chunk */
+ /* the cache of free inodes: */
+ u16 s_ninode; /* number of free inodes in s_inode, <= SYSV_NICINOD */
+ sysv_ino_t s_inode[SYSV_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+ u32 s_time __packed2__; /* time of last super block update */
+ s16 s_dinfo[4]; /* device information ?? */
+ u32 s_tfree __packed2__; /* total number of free zones */
+ u16 s_tinode; /* total number of free inodes */
+ char s_fname[6]; /* file system volume name */
+ char s_fpack[6]; /* file system pack name */
+ s32 s_fill[14];
+ s32 s_state; /* file system state: 0xcb096f43 means clean */
+ s32 s_magic; /* version of file system */
+ s32 s_type; /* type of file system: 1 for 512 byte blocks
+ 2 for 1024 byte blocks */
+};
+
+/* SystemV2 free list block on disk */
+struct sysv2_freelist_chunk {
+ u16 fl_nfree; /* number of free blocks in fl_free, <= SYSV_NICFREE] */
+ u32 fl_free[SYSV_NICFREE] __packed2__;
+};
+
+/* Coherent super-block data on disk */
+#define COH_NICINOD 100 /* number of inode cache entries */
+#define COH_NICFREE 64 /* number of free block list chunk entries */
+struct coh_super_block {
+ u16 s_isize; /* index of first data zone */
+ coh_ulong s_fsize __packed2__; /* total number of zones of this fs */
+ /* the start of the free block list: */
+ u16 s_nfree; /* number of free blocks in s_free, <= COH_NICFREE */
+ coh_ulong s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
+ /* the cache of free inodes: */
+ u16 s_ninode; /* number of free inodes in s_inode, <= COH_NICINOD */
+ sysv_ino_t s_inode[COH_NICINOD]; /* some free inodes */
+ /* locks, not used by Linux: */
+ char s_flock; /* lock during free block list manipulation */
+ char s_ilock; /* lock during inode cache manipulation */
+ char s_fmod; /* super-block modified flag */
+ char s_ronly; /* flag whether fs is mounted read-only */
+ coh_ulong s_time __packed2__; /* time of last super block update */
+ coh_ulong s_tfree __packed2__; /* total number of free zones */
+ u16 s_tinode; /* total number of free inodes */
+ u16 s_interleave_m; /* interleave factor */
+ u16 s_interleave_n;
+ char s_fname[6]; /* file system volume name */
+ char s_fpack[6]; /* file system pack name */
+ u32 s_unique; /* zero, not used */
+};
+
+/* Coherent free list block on disk */
+struct coh_freelist_chunk {
+ u16 fl_nfree; /* number of free blocks in fl_free, <= COH_NICFREE] */
+ u32 fl_free[COH_NICFREE] __packed2__;
+};
+
+
+/* SystemV/Coherent inode data on disk */
+
+struct sysv_inode {
+ u16 i_mode;
+ u16 i_nlink;
+ u16 i_uid;
+ u16 i_gid;
+ u32 i_size;
+ union { /* directories, regular files, ... */
+ unsigned char i_addb[3*(10+1+1+1)+1]; /* zone numbers: max. 10 data blocks,
+ * then 1 indirection block,
+ * then 1 double indirection block,
+ * then 1 triple indirection block.
+ * Then maybe a "file generation number" ??
+ */
+ /* devices */
+ dev_t i_rdev;
+ /* named pipes on Coherent */
+ struct {
+ char p_addp[30];
+ s16 p_pnc;
+ s16 p_prx;
+ s16 p_pwx;
+ } i_p;
+ } i_a;
+ u32 i_atime; /* time of last access */
+ u32 i_mtime; /* time of last modification */
+ u32 i_ctime; /* time of creation */
+};
+
+/* The admissible values for i_mode are listed in <linux/stat.h> :
+ * #define S_IFMT 00170000 mask for type
+ * #define S_IFREG 0100000 type = regular file
+ * #define S_IFBLK 0060000 type = block device
+ * #define S_IFDIR 0040000 type = directory
+ * #define S_IFCHR 0020000 type = character device
+ * #define S_IFIFO 0010000 type = named pipe
+ * #define S_ISUID 0004000 set user id
+ * #define S_ISGID 0002000 set group id
+ * #define S_ISVTX 0001000 save swapped text even after use
+ * Additionally for SystemV:
+ * #define S_IFLNK 0120000 type = symbolic link
+ * #define S_IFNAM 0050000 type = XENIX special named file ??
+ * Additionally for Coherent:
+ * #define S_IFMPB 0070000 type = multiplexed block device ??
+ * #define S_IFMPC 0030000 type = multiplexed character device ??
+ *
+ * Since Coherent doesn't know about symbolic links, we use a kludgey
+ * implementation of symbolic links: i_mode = COH_KLUDGE_SYMLINK_MODE
+ * denotes a symbolic link. When a regular file should get this mode by
+ * accident, it is automatically converted to COH_KLUDGE_NOT_SYMLINK.
+ * We use S_IFREG because only regular files (and Coherent pipes...) can have
+ * data blocks with arbitrary contents associated with them, and S_ISVTX
+ * ("save swapped text after use") because it is unused on both Linux and
+ * Coherent: Linux does much more intelligent paging, and Coherent hasn't
+ * virtual memory at all.
+ * Same trick for Xenix.
+ */
+#define COH_KLUDGE_SYMLINK_MODE (S_IFREG | S_ISVTX)
+#define COH_KLUDGE_NOT_SYMLINK (S_IFREG | S_ISVTX | S_IRUSR) /* force read access */
+extern inline mode_t from_coh_imode(unsigned short mode)
+{
+ if (mode == COH_KLUDGE_SYMLINK_MODE)
+ return (S_IFLNK | 0777);
+ else
+ return mode;
+}
+extern inline unsigned short to_coh_imode(mode_t mode)
+{
+ if (S_ISLNK(mode))
+ return COH_KLUDGE_SYMLINK_MODE;
+ else if (mode == COH_KLUDGE_SYMLINK_MODE)
+ return COH_KLUDGE_NOT_SYMLINK;
+ else
+ return mode;
+}
+
+/* Admissible values for i_nlink: 0.._LINK_MAX */
+#define XENIX_LINK_MAX 126 /* ?? */
+#define SYSV_LINK_MAX 126 /* 127? 251? */
+#define COH_LINK_MAX 10000 /* max number of hard links to an inode */
+
+/* The number of inodes per block is
+ sb->sv_inodes_per_block = block_size / sizeof(struct sysv_inode) */
+/* The number of indirect pointers per block is
+ sb->sv_ind_per_block = block_size / sizeof(u32) */
+
+
+/* SystemV/Coherent directory entry on disk */
+
+#define SYSV_NAMELEN 14 /* max size of name in struct sysv_dir_entry */
+
+struct sysv_dir_entry {
+ sysv_ino_t inode;
+ char name[SYSV_NAMELEN]; /* up to 14 characters, the rest are zeroes */
+};
+
+#define SYSV_DIRSIZE sizeof(struct sysv_dir_entry) /* size of every directory entry */
+
+
+/* Operations */
+/* ========== */
+
+
+/* identify the FS in memory */
+#define FSTYPE_XENIX 1
+#define FSTYPE_SYSV4 2
+#define FSTYPE_SYSV2 3
+#define FSTYPE_COH 4
+
+#define SYSV_MAGIC_BASE 0x012FF7B3
+
+#define XENIX_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_XENIX)
+#define SYSV4_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_SYSV4)
+#define SYSV2_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_SYSV2)
+#define COH_SUPER_MAGIC (SYSV_MAGIC_BASE+FSTYPE_COH)
+
+#ifdef __KERNEL__
+
+/* sv_get_hash_table(sb,dev,block) is equivalent to get_hash_table(dev,block,block_size) */
+static inline struct buffer_head *
+sv_get_hash_table (struct super_block *sb, kdev_t dev, unsigned int block)
+{
+ return get_hash_table (dev, block + sb->sv_block_base, sb->sv_block_size);
+}
+
+/* sv_getblk(sb,dev,block) is equivalent to getblk(dev,block,block_size) */
+static inline struct buffer_head *
+sv_getblk (struct super_block *sb, kdev_t dev, unsigned int block)
+{
+ return getblk (dev, block + sb->sv_block_base, sb->sv_block_size);
+}
+
+/* sv_bread(sb,dev,block) is equivalent to bread(dev,block,block_size) */
+static inline struct buffer_head *
+sv_bread (struct super_block *sb, kdev_t dev, unsigned int block)
+{
+ return bread (dev, block + sb->sv_block_base, sb->sv_block_size);
+}
+
+
+/*
+ * Function prototypes
+ */
+
+extern struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry);
+extern int sysv_create(struct inode * dir, struct dentry * dentry, int mode);
+extern int sysv_mkdir(struct inode * dir, struct dentry * dentry, int mode);
+extern int sysv_rmdir(struct inode * dir, struct dentry * dentry);
+extern int sysv_unlink(struct inode * dir, struct dentry * dentry);
+extern int sysv_symlink(struct inode * inode, struct dentry * dentry, const char * symname);
+extern int sysv_link(struct dentry * old_dentry, struct inode * dir, struct dentry * dentry);
+extern int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev);
+extern int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
+ struct inode * new_dir, struct dentry * new_dentry);
+extern struct inode * sysv_new_inode(const struct inode * dir);
+extern void sysv_free_inode(struct inode * inode);
+extern unsigned long sysv_count_free_inodes(struct super_block *sb);
+extern int sysv_new_block(struct super_block * sb);
+extern void sysv_free_block(struct super_block * sb, unsigned int block);
+extern unsigned long sysv_count_free_blocks(struct super_block *sb);
+
+extern int sysv_bmap(struct inode *,int);
+
+extern struct buffer_head * sysv_getblk(struct inode *, unsigned int, int);
+extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
+extern ssize_t sysv_file_read(struct file *, char *, size_t, loff_t *);
+
+extern void sysv_truncate(struct inode *);
+extern void sysv_put_super(struct super_block *);
+extern struct super_block *sysv_read_super(struct super_block *,void *,int);
+extern int init_sysv_fs(void);
+extern void sysv_write_super(struct super_block *);
+extern void sysv_read_inode(struct inode *);
+extern int sysv_notify_change(struct dentry *, struct iattr *);
+extern void sysv_write_inode(struct inode *);
+extern int sysv_statfs(struct super_block *, struct statfs *, int);
+extern int sysv_sync_inode(struct inode *);
+extern int sysv_sync_file(struct file *, struct dentry *);
+extern int sysv_mmap(struct file *, struct vm_area_struct *);
+
+extern struct inode_operations sysv_file_inode_operations;
+extern struct inode_operations sysv_file_inode_operations_with_bmap;
+extern struct inode_operations sysv_dir_inode_operations;
+extern struct inode_operations sysv_symlink_inode_operations;
+
+#endif /* __KERNEL__ */
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/sysv_fs_i.h b/pfinet/linux-src/include/linux/sysv_fs_i.h
new file mode 100644
index 00000000..990b3543
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sysv_fs_i.h
@@ -0,0 +1,16 @@
+#ifndef _SYSV_FS_I
+#define _SYSV_FS_I
+
+/*
+ * SystemV/Coherent FS inode data in memory
+ */
+struct sysv_inode_info {
+ u32 i_data[10+1+1+1]; /* zone numbers: max. 10 data blocks,
+ * then 1 indirection block,
+ * then 1 double indirection block,
+ * then 1 triple indirection block.
+ */
+};
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/sysv_fs_sb.h b/pfinet/linux-src/include/linux/sysv_fs_sb.h
new file mode 100644
index 00000000..df886f65
--- /dev/null
+++ b/pfinet/linux-src/include/linux/sysv_fs_sb.h
@@ -0,0 +1,122 @@
+#ifndef _SYSV_FS_SB
+#define _SYSV_FS_SB
+
+/*
+ * SystemV/Coherent super-block data in memory
+ * The SystemV/Coherent superblock contains dynamic data (it gets modified
+ * while the system is running). This is in contrast to the Minix and Berkeley
+ * filesystems (where the superblock is never modified). This affects the
+ * sync() operation: we must keep the superblock in a disk buffer and use this
+ * one as our "working copy".
+ */
+
+struct sysv_sb_info {
+ int s_type; /* file system type: FSTYPE_{XENIX|SYSV|COH} */
+ unsigned int s_block_size; /* zone size, = 512 or = 1024 */
+ unsigned int s_block_size_1; /* block_size - 1 */
+ unsigned int s_block_size_bits; /* log2(block_size) */
+ unsigned int s_block_size_inc_bits; /* log2(block_size/BLOCK_SIZE) if >0 */
+ unsigned int s_block_size_dec_bits; /* log2(BLOCK_SIZE/block_size) if >0 */
+ char s_convert; /* flag whether byte ordering requires conversion */
+ char s_kludge_symlinks; /* flag whether symlinks have a kludgey mode */
+ char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */
+ /* if 0: they are disallowed (ENAMETOOLONG) */
+ nlink_t s_link_max; /* max number of hard links to a file */
+ unsigned int s_inodes_per_block; /* number of inodes per block */
+ unsigned int s_inodes_per_block_1; /* inodes_per_block - 1 */
+ unsigned int s_inodes_per_block_bits; /* log2(inodes_per_block) */
+ unsigned int s_ind_per_block; /* number of indirections per block */
+ unsigned int s_ind_per_block_1; /* ind_per_block - 1 */
+ unsigned int s_ind_per_block_bits; /* log2(ind_per_block) */
+ unsigned int s_ind_per_block_2; /* ind_per_block ^ 2 */
+ unsigned int s_ind_per_block_2_1; /* ind_per_block ^ 2 - 1 */
+ unsigned int s_ind_per_block_2_bits; /* log2(ind_per_block^2) */
+ unsigned int s_ind_per_block_3; /* ind_per_block ^ 3 */
+ unsigned int s_ind_per_block_block_size_1; /* ind_per_block*block_size - 1 */
+ unsigned int s_ind_per_block_block_size_bits; /* log2(ind_per_block*block_size) */
+ unsigned int s_ind_per_block_2_block_size_1; /* ind_per_block^2 * block_size - 1 */
+ unsigned int s_ind_per_block_2_block_size_bits; /* log2(ind_per_block^2 * block_size) */
+ unsigned int s_ind0_size; /* 10 * block_size */
+ unsigned int s_ind1_size; /* (10 + ipb) * block_size */
+ unsigned int s_ind2_size; /* (10 + ipb + ipb^2) * block_size */
+ unsigned int s_toobig_block; /* 10 + ipb + ipb^2 + ipb^3 */
+ unsigned int s_block_base; /* physical block number of block 0 */
+ unsigned short s_fic_size; /* free inode cache size, NICINOD */
+ unsigned short s_flc_size; /* free block list chunk size, NICFREE */
+ /* The superblock is kept in one or two disk buffers: */
+ struct buffer_head *s_bh1;
+ struct buffer_head *s_bh2;
+ /* These are pointers into the disk buffer, to compensate for
+ different superblock layout. */
+ char * s_sbd1; /* entire superblock data, for part 1 */
+ char * s_sbd2; /* entire superblock data, for part 2 */
+ u16 *s_sb_fic_count; /* pointer to s_sbd->s_ninode */
+ u16 *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
+ u16 *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
+ u16 *s_sb_flc_count; /* pointer to s_sbd->s_nfree */
+ u32 *s_sb_flc_blocks; /* pointer to s_sbd->s_free */
+ u32 *s_sb_total_free_blocks;/* pointer to s_sbd->s_tfree */
+ u32 *s_sb_time; /* pointer to s_sbd->s_time */
+ u32 *s_sb_state; /* pointer to s_sbd->s_state, only FSTYPE_SYSV */
+ /* We keep those superblock entities that don't change here;
+ this saves us an indirection and perhaps a conversion. */
+ u32 s_firstinodezone; /* index of first inode zone */
+ u32 s_firstdatazone; /* same as s_sbd->s_isize */
+ u32 s_ninodes; /* total number of inodes */
+ u32 s_ndatazones; /* total number of data zones */
+ u32 s_nzones; /* same as s_sbd->s_fsize */
+};
+/* The fields s_ind_per_block_2_1, s_toobig_block are currently unused. */
+
+/* sv_ == u.sysv_sb.s_ */
+#define sv_type u.sysv_sb.s_type
+#define sv_block_size u.sysv_sb.s_block_size
+#define sv_block_size_1 u.sysv_sb.s_block_size_1
+#define sv_block_size_bits u.sysv_sb.s_block_size_bits
+#define sv_block_size_inc_bits u.sysv_sb.s_block_size_inc_bits
+#define sv_block_size_dec_bits u.sysv_sb.s_block_size_dec_bits
+#define sv_convert u.sysv_sb.s_convert
+#define sv_kludge_symlinks u.sysv_sb.s_kludge_symlinks
+#define sv_truncate u.sysv_sb.s_truncate
+#define sv_link_max u.sysv_sb.s_link_max
+#define sv_inodes_per_block u.sysv_sb.s_inodes_per_block
+#define sv_inodes_per_block_1 u.sysv_sb.s_inodes_per_block_1
+#define sv_inodes_per_block_bits u.sysv_sb.s_inodes_per_block_bits
+#define sv_ind_per_block u.sysv_sb.s_ind_per_block
+#define sv_ind_per_block_1 u.sysv_sb.s_ind_per_block_1
+#define sv_ind_per_block_bits u.sysv_sb.s_ind_per_block_bits
+#define sv_ind_per_block_2 u.sysv_sb.s_ind_per_block_2
+#define sv_ind_per_block_2_1 u.sysv_sb.s_ind_per_block_2_1
+#define sv_ind_per_block_2_bits u.sysv_sb.s_ind_per_block_2_bits
+#define sv_ind_per_block_3 u.sysv_sb.s_ind_per_block_3
+#define sv_ind_per_block_block_size_1 u.sysv_sb.s_ind_per_block_block_size_1
+#define sv_ind_per_block_block_size_bits u.sysv_sb.s_ind_per_block_block_size_bits
+#define sv_ind_per_block_2_block_size_1 u.sysv_sb.s_ind_per_block_2_block_size_1
+#define sv_ind_per_block_2_block_size_bits u.sysv_sb.s_ind_per_block_2_block_size_bits
+#define sv_ind0_size u.sysv_sb.s_ind0_size
+#define sv_ind1_size u.sysv_sb.s_ind1_size
+#define sv_ind2_size u.sysv_sb.s_ind2_size
+#define sv_toobig_block u.sysv_sb.s_toobig_block
+#define sv_block_base u.sysv_sb.s_block_base
+#define sv_fic_size u.sysv_sb.s_fic_size
+#define sv_flc_size u.sysv_sb.s_flc_size
+#define sv_bh1 u.sysv_sb.s_bh1
+#define sv_bh2 u.sysv_sb.s_bh2
+#define sv_sbd1 u.sysv_sb.s_sbd1
+#define sv_sbd2 u.sysv_sb.s_sbd2
+#define sv_sb_fic_count u.sysv_sb.s_sb_fic_count
+#define sv_sb_fic_inodes u.sysv_sb.s_sb_fic_inodes
+#define sv_sb_total_free_inodes u.sysv_sb.s_sb_total_free_inodes
+#define sv_sb_flc_count u.sysv_sb.s_sb_flc_count
+#define sv_sb_flc_blocks u.sysv_sb.s_sb_flc_blocks
+#define sv_sb_total_free_blocks u.sysv_sb.s_sb_total_free_blocks
+#define sv_sb_time u.sysv_sb.s_sb_time
+#define sv_sb_state u.sysv_sb.s_sb_state
+#define sv_firstinodezone u.sysv_sb.s_firstinodezone
+#define sv_firstdatazone u.sysv_sb.s_firstdatazone
+#define sv_ninodes u.sysv_sb.s_ninodes
+#define sv_ndatazones u.sysv_sb.s_ndatazones
+#define sv_nzones u.sysv_sb.s_nzones
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/tasks.h b/pfinet/linux-src/include/linux/tasks.h
new file mode 100644
index 00000000..91b758f4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/tasks.h
@@ -0,0 +1,25 @@
+#ifndef _LINUX_TASKS_H
+#define _LINUX_TASKS_H
+
+/*
+ * This is the maximum nr of tasks - change it if you need to
+ */
+
+#ifdef __SMP__
+#define NR_CPUS 32 /* Max processors that can be running in SMP */
+#else
+#define NR_CPUS 1
+#endif
+
+#define NR_TASKS 512 /* On x86 Max 4092, or 4090 w/APM configured. */
+
+#define MAX_TASKS_PER_USER (NR_TASKS/2)
+#define MIN_TASKS_LEFT_FOR_ROOT 4
+
+
+/*
+ * This controls the maximum pid allocated to a process
+ */
+#define PID_MAX 0x8000
+
+#endif
diff --git a/pfinet/linux-src/include/linux/tcp.h b/pfinet/linux-src/include/linux/tcp.h
new file mode 100644
index 00000000..9ee71810
--- /dev/null
+++ b/pfinet/linux-src/include/linux/tcp.h
@@ -0,0 +1,90 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the TCP protocol.
+ *
+ * Version: @(#)tcp.h 1.0.2 04/28/93
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_TCP_H
+#define _LINUX_TCP_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+struct tcphdr {
+ __u16 source;
+ __u16 dest;
+ __u32 seq;
+ __u32 ack_seq;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u16 res1:4,
+ doff:4,
+ fin:1,
+ syn:1,
+ rst:1,
+ psh:1,
+ ack:1,
+ urg:1,
+ res2:2;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u16 doff:4,
+ res1:4,
+ res2:2,
+ urg:1,
+ ack:1,
+ psh:1,
+ rst:1,
+ syn:1,
+ fin:1;
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+ __u16 window;
+ __u16 check;
+ __u16 urg_ptr;
+};
+
+
+enum {
+ TCP_ESTABLISHED = 1,
+ TCP_SYN_SENT,
+ TCP_SYN_RECV,
+ TCP_FIN_WAIT1,
+ TCP_FIN_WAIT2,
+ TCP_TIME_WAIT,
+ TCP_CLOSE,
+ TCP_CLOSE_WAIT,
+ TCP_LAST_ACK,
+ TCP_LISTEN,
+ TCP_CLOSING, /* now a valid state */
+
+ TCP_MAX_STATES /* Leave at the end! */
+};
+
+#define TCP_STATE_MASK 0xF
+#define TCP_ACTION_FIN (1 << 7)
+
+enum {
+ TCPF_ESTABLISHED = (1 << 1),
+ TCPF_SYN_SENT = (1 << 2),
+ TCPF_SYN_RECV = (1 << 3),
+ TCPF_FIN_WAIT1 = (1 << 4),
+ TCPF_FIN_WAIT2 = (1 << 5),
+ TCPF_TIME_WAIT = (1 << 6),
+ TCPF_CLOSE = (1 << 7),
+ TCPF_CLOSE_WAIT = (1 << 8),
+ TCPF_LAST_ACK = (1 << 9),
+ TCPF_LISTEN = (1 << 10),
+ TCPF_CLOSING = (1 << 11)
+};
+
+#endif /* _LINUX_TCP_H */
diff --git a/pfinet/linux-src/include/linux/termios.h b/pfinet/linux-src/include/linux/termios.h
new file mode 100644
index 00000000..47866288
--- /dev/null
+++ b/pfinet/linux-src/include/linux/termios.h
@@ -0,0 +1,7 @@
+#ifndef _LINUX_TERMIOS_H
+#define _LINUX_TERMIOS_H
+
+#include <linux/types.h>
+#include <asm/termios.h>
+
+#endif
diff --git a/pfinet/linux-src/include/linux/time.h b/pfinet/linux-src/include/linux/time.h
new file mode 100644
index 00000000..53a125a0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/time.h
@@ -0,0 +1,92 @@
+#ifndef _LINUX_TIME_H
+#define _LINUX_TIME_H
+
+#include <asm/param.h>
+#include <linux/types.h>
+
+#ifndef _STRUCT_TIMESPEC
+#define _STRUCT_TIMESPEC
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+#endif /* _STRUCT_TIMESPEC */
+
+/*
+ * Change timeval to jiffies, trying to avoid the
+ * most obvious overflows..
+ *
+ * And some not so obvious.
+ *
+ * Note that we don't want to return MAX_LONG, because
+ * for various timeout reasons we often end up having
+ * to wait "jiffies+1" in order to guarantee that we wait
+ * at _least_ "jiffies" - so "jiffies+1" had better still
+ * be positive.
+ */
+#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
+
+static __inline__ unsigned long
+timespec_to_jiffies(struct timespec *value)
+{
+ unsigned long sec = value->tv_sec;
+ long nsec = value->tv_nsec;
+
+ if (sec >= (MAX_JIFFY_OFFSET / HZ))
+ return MAX_JIFFY_OFFSET;
+ nsec += 1000000000L / HZ - 1;
+ nsec /= 1000000000L / HZ;
+ return HZ * sec + nsec;
+}
+
+static __inline__ void
+jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
+{
+ value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
+ value->tv_sec = jiffies / HZ;
+}
+
+struct timeval {
+ time_t tv_sec; /* seconds */
+ suseconds_t tv_usec; /* microseconds */
+};
+
+struct timezone {
+ int tz_minuteswest; /* minutes west of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+#define NFDBITS __NFDBITS
+
+#ifdef __KERNEL__
+extern void do_gettimeofday(struct timeval *tv);
+extern void do_settimeofday(struct timeval *tv);
+extern void get_fast_time(struct timeval *tv);
+extern void (*do_get_fast_time)(struct timeval *);
+#endif
+
+#define FD_SETSIZE __FD_SETSIZE
+#define FD_SET(fd,fdsetp) __FD_SET(fd,fdsetp)
+#define FD_CLR(fd,fdsetp) __FD_CLR(fd,fdsetp)
+#define FD_ISSET(fd,fdsetp) __FD_ISSET(fd,fdsetp)
+#define FD_ZERO(fdsetp) __FD_ZERO(fdsetp)
+
+/*
+ * Names of the interval timers, and structure
+ * defining a timer setting.
+ */
+#define ITIMER_REAL 0
+#define ITIMER_VIRTUAL 1
+#define ITIMER_PROF 2
+
+struct itimerspec {
+ struct timespec it_interval; /* timer period */
+ struct timespec it_value; /* timer expiration */
+};
+
+struct itimerval {
+ struct timeval it_interval; /* timer interval */
+ struct timeval it_value; /* current value */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/timer.h b/pfinet/linux-src/include/linux/timer.h
new file mode 100644
index 00000000..56f39893
--- /dev/null
+++ b/pfinet/linux-src/include/linux/timer.h
@@ -0,0 +1,96 @@
+#ifndef _LINUX_TIMER_H
+#define _LINUX_TIMER_H
+
+/*
+ * Old-style timers. Please don't use for any new code.
+ *
+ * Numbering of these timers should be consecutive to minimize
+ * processing delays. [MJ]
+ */
+
+#define BLANK_TIMER 0 /* Console screen-saver */
+#define BEEP_TIMER 1 /* Console beep */
+#define RS_TIMER 2 /* RS-232 ports */
+#define SWAP_TIMER 3 /* Background pageout */
+#define BACKGR_TIMER 4 /* io_request background I/O */
+#define HD_TIMER 5 /* Old IDE driver */
+#define FLOPPY_TIMER 6 /* Floppy */
+#define QIC02_TAPE_TIMER 7 /* QIC 02 tape */
+#define MCD_TIMER 8 /* Mitsumi CDROM */
+#define GSCD_TIMER 9 /* Goldstar CDROM */
+#define COMTROL_TIMER 10 /* Comtrol serial */
+#define DIGI_TIMER 11 /* Digi serial */
+#define GDTH_TIMER 12 /* Ugh - gdth scsi driver */
+
+#define COPRO_TIMER 31 /* 387 timeout for buggy hardware (boot only) */
+
+struct timer_struct {
+ unsigned long expires;
+ void (*fn)(void);
+};
+
+extern unsigned long timer_active;
+extern struct timer_struct timer_table[32];
+
+/*
+ * This is completely separate from the above, and is the
+ * "new and improved" way of handling timers more dynamically.
+ * Hopefully efficient and general enough for most things.
+ *
+ * The "hardcoded" timers above are still useful for well-
+ * defined problems, but the timer-list is probably better
+ * when you need multiple outstanding timers or similar.
+ *
+ * The "data" field is in case you want to use the same
+ * timeout function for several timeouts. You can use this
+ * to distinguish between the different invocations.
+ */
+struct timer_list {
+ struct timer_list *next; /* MUST be first element */
+ struct timer_list *prev;
+ unsigned long expires;
+ unsigned long data;
+ void (*function)(unsigned long);
+};
+
+extern void add_timer(struct timer_list * timer);
+extern int del_timer(struct timer_list * timer);
+
+/*
+ * mod_timer is a more efficient way to update the expire field of an
+ * active timer (if the timer is inactive it will be activated)
+ * mod_timer(a,b) is equivalent to del_timer(a); a->expires = b; add_timer(a)
+ */
+void mod_timer(struct timer_list *timer, unsigned long expires);
+
+extern void it_real_fn(unsigned long);
+
+extern inline void init_timer(struct timer_list * timer)
+{
+ timer->next = NULL;
+ timer->prev = NULL;
+}
+
+extern inline int timer_pending(struct timer_list * timer)
+{
+ return timer->prev != NULL;
+}
+
+/*
+ * These inlines deal with timer wrapping correctly. You are
+ * strongly encouraged to use them
+ * 1. Because people otherwise forget
+ * 2. Because if the timer wrap changes in future you wont have to
+ * alter your driver code.
+ *
+ * Do this with "<0" and ">=0" to only test the sign of the result. A
+ * good compiler would generate better code (and a really good compiler
+ * wouldn't care). Gcc is currently neither.
+ */
+#define time_after(a,b) ((long)(b) - (long)(a) < 0)
+#define time_before(a,b) time_after(b,a)
+
+#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
+#define time_before_eq(a,b) time_after_eq(b,a)
+
+#endif
diff --git a/pfinet/linux-src/include/linux/times.h b/pfinet/linux-src/include/linux/times.h
new file mode 100644
index 00000000..569349ef
--- /dev/null
+++ b/pfinet/linux-src/include/linux/times.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_TIMES_H
+#define _LINUX_TIMES_H
+
+struct tms {
+ clock_t tms_utime;
+ clock_t tms_stime;
+ clock_t tms_cutime;
+ clock_t tms_cstime;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/timex.h b/pfinet/linux-src/include/linux/timex.h
new file mode 100644
index 00000000..653009ad
--- /dev/null
+++ b/pfinet/linux-src/include/linux/timex.h
@@ -0,0 +1,277 @@
+/*****************************************************************************
+ * *
+ * Copyright (c) David L. Mills 1993 *
+ * *
+ * Permission to use, copy, modify, and distribute this software and its *
+ * documentation for any purpose and without fee is hereby granted, provided *
+ * that the above copyright notice appears in all copies and that both the *
+ * copyright notice and this permission notice appear in supporting *
+ * documentation, and that the name University of Delaware not be used in *
+ * advertising or publicity pertaining to distribution of the software *
+ * without specific, written prior permission. The University of Delaware *
+ * makes no representations about the suitability this software for any *
+ * purpose. It is provided "as is" without express or implied warranty. *
+ * *
+ *****************************************************************************/
+
+/*
+ * Modification history timex.h
+ *
+ * 29 Dec 97 Russell King
+ * Moved CLOCK_TICK_RATE, CLOCK_TICK_FACTOR and FINETUNE to asm/timex.h
+ * for ARM machines
+ *
+ * 9 Jan 97 Adrian Sun
+ * Shifted LATCH define to allow access to alpha machines.
+ *
+ * 26 Sep 94 David L. Mills
+ * Added defines for hybrid phase/frequency-lock loop.
+ *
+ * 19 Mar 94 David L. Mills
+ * Moved defines from kernel routines to header file and added new
+ * defines for PPS phase-lock loop.
+ *
+ * 20 Feb 94 David L. Mills
+ * Revised status codes and structures for external clock and PPS
+ * signal discipline.
+ *
+ * 28 Nov 93 David L. Mills
+ * Adjusted parameters to improve stability and increase poll
+ * interval.
+ *
+ * 17 Sep 93 David L. Mills
+ * Created file $NTP/include/sys/timex.h
+ * 07 Oct 93 Torsten Duwe
+ * Derived linux/timex.h
+ * 1995-08-13 Torsten Duwe
+ * kernel PLL updated to 1994-12-13 specs (rfc-1589)
+ * 1997-08-30 Ulrich Windl
+ * Added new constant NTP_PHASE_LIMIT
+ */
+#ifndef _LINUX_TIMEX_H
+#define _LINUX_TIMEX_H
+
+/*
+ * The following defines establish the engineering parameters of the PLL
+ * model. The HZ variable establishes the timer interrupt frequency, 100 Hz
+ * for the SunOS kernel, 256 Hz for the Ultrix kernel and 1024 Hz for the
+ * OSF/1 kernel. The SHIFT_HZ define expresses the same value as the
+ * nearest power of two in order to avoid hardware multiply operations.
+ */
+#ifdef __alpha__
+# define SHIFT_HZ 10 /* log2(HZ) */
+#else
+# define SHIFT_HZ 7 /* log2(HZ) */
+#endif
+
+/*
+ * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen
+ * for a slightly underdamped convergence characteristic. SHIFT_KH
+ * establishes the damping of the FLL and is chosen by wisdom and black
+ * art.
+ *
+ * MAXTC establishes the maximum time constant of the PLL. With the
+ * SHIFT_KG and SHIFT_KF values given and a time constant range from
+ * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours,
+ * respectively.
+ */
+#define SHIFT_KG 6 /* phase factor (shift) */
+#define SHIFT_KF 16 /* PLL frequency factor (shift) */
+#define SHIFT_KH 2 /* FLL frequency factor (shift) */
+#define MAXTC 6 /* maximum time constant (shift) */
+
+/*
+ * The SHIFT_SCALE define establishes the decimal point of the time_phase
+ * variable which serves as an extension to the low-order bits of the
+ * system clock variable. The SHIFT_UPDATE define establishes the decimal
+ * point of the time_offset variable which represents the current offset
+ * with respect to standard time. The FINEUSEC define represents 1 usec in
+ * scaled units.
+ *
+ * SHIFT_USEC defines the scaling (shift) of the time_freq and
+ * time_tolerance variables, which represent the current frequency
+ * offset and maximum frequency tolerance.
+ *
+ * FINEUSEC is 1 us in SHIFT_UPDATE units of the time_phase variable.
+ */
+#define SHIFT_SCALE 22 /* phase scale (shift) */
+#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* time offset scale (shift) */
+#define SHIFT_USEC 16 /* frequency offset scale (shift) */
+#define FINEUSEC (1L << SHIFT_SCALE) /* 1 us in phase units */
+
+#define MAXPHASE 512000L /* max phase error (us) */
+#define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */
+#define MAXTIME (200L << PPS_AVG) /* max PPS error (jitter) (200 us) */
+#define MINSEC 16L /* min interval between updates (s) */
+#define MAXSEC 1200L /* max interval between updates (s) */
+#define NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */
+
+/*
+ * The following defines are used only if a pulse-per-second (PPS)
+ * signal is available and connected via a modem control lead, such as
+ * produced by the optional ppsclock feature incorporated in the Sun
+ * asynch driver. They establish the design parameters of the frequency-
+ * lock loop used to discipline the CPU clock oscillator to the PPS
+ * signal.
+ *
+ * PPS_AVG is the averaging factor for the frequency loop, as well as
+ * the time and frequency dispersion.
+ *
+ * PPS_SHIFT and PPS_SHIFTMAX specify the minimum and maximum
+ * calibration intervals, respectively, in seconds as a power of two.
+ *
+ * PPS_VALID is the maximum interval before the PPS signal is considered
+ * invalid and protocol updates used directly instead.
+ *
+ * MAXGLITCH is the maximum interval before a time offset of more than
+ * MAXTIME is believed.
+ */
+#define PPS_AVG 2 /* pps averaging constant (shift) */
+#define PPS_SHIFT 2 /* min interval duration (s) (shift) */
+#define PPS_SHIFTMAX 8 /* max interval duration (s) (shift) */
+#define PPS_VALID 120 /* pps signal watchdog max (s) */
+#define MAXGLITCH 30 /* pps signal glitch max (s) */
+
+/*
+ * Pick up the architecture specific timex specifications
+ */
+#include <asm/timex.h>
+
+/* LATCH is used in the interval timer and ftape setup. */
+#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
+
+/*
+ * syscall interface - used (mainly by NTP daemon)
+ * to discipline kernel clock oscillator
+ */
+struct timex {
+ unsigned int modes; /* mode selector */
+ long offset; /* time offset (usec) */
+ long freq; /* frequency offset (scaled ppm) */
+ long maxerror; /* maximum error (usec) */
+ long esterror; /* estimated error (usec) */
+ int status; /* clock command/status */
+ long constant; /* pll time constant */
+ long precision; /* clock precision (usec) (read only) */
+ long tolerance; /* clock frequency tolerance (ppm)
+ * (read only)
+ */
+ struct timeval time; /* (read only) */
+ long tick; /* (modified) usecs between clock ticks */
+
+ long ppsfreq; /* pps frequency (scaled ppm) (ro) */
+ long jitter; /* pps jitter (us) (ro) */
+ int shift; /* interval duration (s) (shift) (ro) */
+ long stabil; /* pps stability (scaled ppm) (ro) */
+ long jitcnt; /* jitter limit exceeded (ro) */
+ long calcnt; /* calibration intervals (ro) */
+ long errcnt; /* calibration errors (ro) */
+ long stbcnt; /* stability limit exceeded (ro) */
+
+ int :32; int :32; int :32; int :32;
+ int :32; int :32; int :32; int :32;
+ int :32; int :32; int :32; int :32;
+};
+
+/*
+ * Mode codes (timex.mode)
+ */
+#define ADJ_OFFSET 0x0001 /* time offset */
+#define ADJ_FREQUENCY 0x0002 /* frequency offset */
+#define ADJ_MAXERROR 0x0004 /* maximum time error */
+#define ADJ_ESTERROR 0x0008 /* estimated time error */
+#define ADJ_STATUS 0x0010 /* clock status */
+#define ADJ_TIMECONST 0x0020 /* pll time constant */
+#define ADJ_TICK 0x4000 /* tick value */
+#define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */
+
+/* xntp 3.4 compatibility names */
+#define MOD_OFFSET ADJ_OFFSET
+#define MOD_FREQUENCY ADJ_FREQUENCY
+#define MOD_MAXERROR ADJ_MAXERROR
+#define MOD_ESTERROR ADJ_ESTERROR
+#define MOD_STATUS ADJ_STATUS
+#define MOD_TIMECONST ADJ_TIMECONST
+#define MOD_CLKB ADJ_TICK
+#define MOD_CLKA ADJ_OFFSET_SINGLESHOT /* 0x8000 in original */
+
+
+/*
+ * Status codes (timex.status)
+ */
+#define STA_PLL 0x0001 /* enable PLL updates (rw) */
+#define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */
+#define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */
+#define STA_FLL 0x0008 /* select frequency-lock mode (rw) */
+
+#define STA_INS 0x0010 /* insert leap (rw) */
+#define STA_DEL 0x0020 /* delete leap (rw) */
+#define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */
+#define STA_FREQHOLD 0x0080 /* hold frequency (rw) */
+
+#define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */
+#define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */
+#define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */
+#define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */
+
+#define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */
+
+#define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \
+ STA_PPSERROR | STA_CLOCKERR) /* read-only bits */
+
+/*
+ * Clock states (time_state)
+ */
+#define TIME_OK 0 /* clock synchronized, no leap second */
+#define TIME_INS 1 /* insert leap second */
+#define TIME_DEL 2 /* delete leap second */
+#define TIME_OOP 3 /* leap second in progress */
+#define TIME_WAIT 4 /* leap second has occurred */
+#define TIME_ERROR 5 /* clock not synchronized */
+#define TIME_BAD TIME_ERROR /* bw compat */
+
+#ifdef __KERNEL__
+/*
+ * kernel variables
+ * Note: maximum error = NTP synch distance = dispersion + delay / 2;
+ * estimated error = NTP dispersion.
+ */
+extern long tick; /* timer interrupt period */
+extern int tickadj; /* amount of adjustment per tick */
+
+/*
+ * phase-lock loop variables
+ */
+extern int time_state; /* clock status */
+extern int time_status; /* clock synchronization status bits */
+extern long time_offset; /* time adjustment (us) */
+extern long time_constant; /* pll time constant */
+extern long time_tolerance; /* frequency tolerance (ppm) */
+extern long time_precision; /* clock precision (us) */
+extern long time_maxerror; /* maximum error */
+extern long time_esterror; /* estimated error */
+
+extern long time_phase; /* phase offset (scaled us) */
+extern long time_freq; /* frequency offset (scaled ppm) */
+extern long time_adj; /* tick adjust (scaled 1 / HZ) */
+extern long time_reftime; /* time at last adjustment (s) */
+
+extern long time_adjust; /* The amount of adjtime left */
+
+/* interface variables pps->timer interrupt */
+extern long pps_offset; /* pps time offset (us) */
+extern long pps_jitter; /* time dispersion (jitter) (us) */
+extern long pps_freq; /* frequency offset (scaled ppm) */
+extern long pps_stabil; /* frequency dispersion (scaled ppm) */
+extern long pps_valid; /* pps signal watchdog counter */
+
+/* interface variables pps->adjtimex */
+extern int pps_shift; /* interval duration (s) (shift) */
+extern long pps_jitcnt; /* jitter limit exceeded */
+extern long pps_calcnt; /* calibration intervals */
+extern long pps_errcnt; /* calibration errors */
+extern long pps_stbcnt; /* stability limit exceeded */
+
+#endif /* KERNEL */
+
+#endif /* LINUX_TIMEX_H */
diff --git a/pfinet/linux-src/include/linux/tpqic02.h b/pfinet/linux-src/include/linux/tpqic02.h
new file mode 100644
index 00000000..fe13ad6e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/tpqic02.h
@@ -0,0 +1,739 @@
+/* $Id: tpqic02.h,v 1.5 1996/12/14 23:01:38 root Exp root $
+ *
+ * Include file for QIC-02 driver for Linux.
+ *
+ * Copyright (c) 1992--1995 by H. H. Bergman. All rights reserved.
+ *
+ * ******* USER CONFIG SECTION BELOW (Near line 70) *******
+ */
+
+#ifndef _LINUX_TPQIC02_H
+#define _LINUX_TPQIC02_H
+
+#include <linux/config.h>
+
+#if CONFIG_QIC02_TAPE || CONFIG_QIC02_TAPE_MODULE
+
+/* need to have QIC02_TAPE_DRIVE and QIC02_TAPE_IFC expand to something */
+#include <linux/mtio.h>
+
+
+/* Make QIC02_TAPE_IFC expand to something.
+ *
+ * The only difference between WANGTEK and EVEREX is in the
+ * handling of the DMA channel 3.
+ * Note that the driver maps EVEREX to WANGTEK internally for speed
+ * reasons. Externally WANGTEK==1, EVEREX==2, ARCHIVE==3.
+ * These must correspond to the values used in qic02config(1).
+ *
+ * Support for Mountain controllers was added by Erik Jacobson
+ * and severely hacked by me. -- hhb
+ *
+ * Support for Emerald controllers by Alan Bain <afrb2@chiark.chu.cam.ac.uk>
+ * with more hacks by me. -- hhb
+ */
+#define WANGTEK 1 /* don't know about Wangtek QIC-36 */
+#define EVEREX (WANGTEK+1) /* I heard *some* of these are identical */
+#define EVEREX_811V EVEREX /* With TEAC MT 2ST 45D */
+#define EVEREX_831V EVEREX
+#define ARCHIVE 3
+#define ARCHIVE_SC400 ARCHIVE /* rumoured to be from the pre-SMD-age */
+#define ARCHIVE_SC402 ARCHIVE /* don't know much about SC400 */
+#define ARCHIVE_SC499 ARCHIVE /* SC402 and SC499R should be identical */
+
+#define MOUNTAIN 5 /* Mountain Computer Interface */
+#define EMERALD 6 /* Emerald Interface card */
+
+
+
+#define QIC02_TAPE_PORT_RANGE 8 /* number of IO locations to reserve */
+
+
+/*********** START OF USER CONFIGURABLE SECTION ************/
+
+/* Tape configuration: Select DRIVE, IFC, PORT, IRQ and DMA below.
+ * Runtime (re)configuration is not supported yet.
+ *
+ * Tape drive configuration: (MT_IS* constants are defined in mtio.h)
+ *
+ * QIC02_TAPE_DRIVE = MT_ISWT5150
+ * - Wangtek 5150, format: up to QIC-150.
+ * QIC02_TAPE_DRIVE = MT_ISQIC02_ALL_FEATURES
+ * - Enables some optional QIC02 commands that some drives may lack.
+ * It is provided so you can check which are supported by your drive.
+ * Refer to tpqic02.h for others.
+ *
+ * Supported interface cards: QIC02_TAPE_IFC =
+ * WANGTEK,
+ * ARCHIVE_SC402, ARCHIVE_SC499. (both same programming interface)
+ *
+ * Make sure you have the I/O ports/DMA channels
+ * and IRQ stuff configured properly!
+ * NOTE: There may be other device drivers using the same major
+ * number. This must be avoided. Check for timer.h conflicts too.
+ *
+ * If you have an EVEREX EV-831 card and you are using DMA channel 3,
+ * you will probably have to ``#define QIC02_TAPE_DMA3_FIX'' below.
+ */
+
+/* CONFIG_QIC02_DYNCONF can be defined in autoconf.h, by `make config' */
+
+/*** #undef CONFIG_QIC02_DYNCONF ***/
+
+#ifndef CONFIG_QIC02_DYNCONF
+
+#define QIC02_TAPE_DRIVE MT_ISQIC02_ALL_FEATURES /* drive type */
+/* #define QIC02_TAPE_DRIVE MT_ISWT5150 */
+/* #define QIC02_TAPE_DRIVE MT_ISARCHIVE_5945L2 */
+/* #define QIC02_TAPE_DRIVE MT_ISTEAC_MT2ST */
+/* #define QIC02_TAPE_DRIVE MT_ISARCHIVE_2150L */
+/* #define QIC02_TAPE_DRIVE MT_ISARCHIVESC499 */
+
+/* Either WANGTEK, ARCHIVE or MOUNTAIN. Not EVEREX.
+ * If you have an EVEREX, use WANGTEK and try the DMA3_FIX below.
+ */
+#define QIC02_TAPE_IFC WANGTEK /* interface card type */
+/* #define QIC02_TAPE_IFC ARCHIVE */
+/* #define QIC02_TAPE_IFC MOUNTAIN */
+
+#define QIC02_TAPE_PORT 0x300 /* controller port address */
+#define QIC02_TAPE_IRQ 5 /* For IRQ2, use 9 here, others normal. */
+#define QIC02_TAPE_DMA 1 /* either 1 or 3, because 2 is used by the floppy */
+
+/* If DMA3 doesn't work, but DMA1 does, and you have a
+ * Wangtek/Everex card, you can try #define-ing the flag
+ * below. Note that you should also change the DACK jumper
+ * for Wangtek/Everex cards when changing the DMA channel.
+ */
+#undef QIC02_TAPE_DMA3_FIX
+
+/************ END OF USER CONFIGURABLE SECTION *************/
+
+/* I put the stuff above in config.in, but a few recompiles, to
+ * verify different configurations, and several days later I decided
+ * to change it back again.
+ */
+
+
+
+/* NOTE: TP_HAVE_DENS should distinguish between available densities (?)
+ * NOTE: Drive select is not implemented -- I have only one tape streamer,
+ * so I'm unable and unmotivated to test and implement that. ;-) ;-)
+ */
+#if QIC02_TAPE_DRIVE == MT_ISWT5150
+#define TP_HAVE_DENS 1
+#define TP_HAVE_BSF 0 /* nope */
+#define TP_HAVE_FSR 0 /* nope */
+#define TP_HAVE_BSR 0 /* nope */
+#define TP_HAVE_EOD 0 /* most of the time */
+#define TP_HAVE_SEEK 0
+#define TP_HAVE_TELL 0
+#define TP_HAVE_RAS1 1
+#define TP_HAVE_RAS2 1
+
+#elif QIC02_TAPE_DRIVE == MT_ISARCHIVESC499 /* Archive SC-499 QIC-36 controller */
+#define TP_HAVE_DENS 1 /* can do set density (QIC-11 / QIC-24) */
+#define TP_HAVE_BSF 0
+#define TP_HAVE_FSR 1 /* can skip one block forwards */
+#define TP_HAVE_BSR 1 /* can skip one block backwards */
+#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
+#define TP_HAVE_SEEK 0
+#define TP_HAVE_TELL 0
+#define TP_HAVE_RAS1 1 /* can run selftest 1 */
+#define TP_HAVE_RAS2 1 /* can run selftest 2 */
+/* These last two selftests shouldn't be used yet! */
+
+#elif (QIC02_TAPE_DRIVE == MT_ISARCHIVE_2060L) || (QIC02_TAPE_DRIVE == MT_ISARCHIVE_2150L)
+#define TP_HAVE_DENS 1 /* can do set density (QIC-24 / QIC-120 / QIC-150) */
+#define TP_HAVE_BSF 0
+#define TP_HAVE_FSR 1 /* can skip one block forwards */
+#define TP_HAVE_BSR 1 /* can skip one block backwards */
+#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
+#define TP_HAVE_TELL 1 /* can read current block address */
+#define TP_HAVE_SEEK 1 /* can seek to block */
+#define TP_HAVE_RAS1 1 /* can run selftest 1 */
+#define TP_HAVE_RAS2 1 /* can run selftest 2 */
+/* These last two selftests shouldn't be used yet! */
+
+#elif QIC02_TAPE_DRIVE == MT_ISARCHIVE_5945L2
+/* can anyone verify this entry?? */
+#define TP_HAVE_DENS 1 /* can do set density?? (QIC-24??) */
+#define TP_HAVE_BSF 0
+#define TP_HAVE_FSR 1 /* can skip one block forwards */
+#define TP_HAVE_BSR 1 /* can skip one block backwards */
+#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
+#define TP_HAVE_TELL 1 /* can read current block address */
+#define TP_HAVE_SEEK 1 /* can seek to block */
+#define TP_HAVE_RAS1 1 /* can run selftest 1 */
+#define TP_HAVE_RAS2 1 /* can run selftest 2 */
+/* These last two selftests shouldn't be used yet! */
+
+#elif QIC02_TAPE_DRIVE == MT_ISTEAC_MT2ST
+/* can anyone verify this entry?? */
+#define TP_HAVE_DENS 0 /* cannot do set density?? (QIC-150?) */
+#define TP_HAVE_BSF 0
+#define TP_HAVE_FSR 1 /* can skip one block forwards */
+#define TP_HAVE_BSR 1 /* can skip one block backwards */
+#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
+#define TP_HAVE_SEEK 1 /* can seek to block */
+#define TP_HAVE_TELL 1 /* can read current block address */
+#define TP_HAVE_RAS1 1 /* can run selftest 1 */
+#define TP_HAVE_RAS2 1 /* can run selftest 2 */
+/* These last two selftests shouldn't be used yet! */
+
+#elif QIC02_TAPE_DRIVE == MT_ISQIC02_ALL_FEATURES
+#define TP_HAVE_DENS 1 /* can do set density */
+#define TP_HAVE_BSF 1 /* can search filemark backwards */
+#define TP_HAVE_FSR 1 /* can skip one block forwards */
+#define TP_HAVE_BSR 1 /* can skip one block backwards */
+#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
+#define TP_HAVE_SEEK 1 /* seek to block address */
+#define TP_HAVE_TELL 1 /* tell current block address */
+#define TP_HAVE_RAS1 1 /* can run selftest 1 */
+#define TP_HAVE_RAS2 1 /* can run selftest 2 */
+/* These last two selftests shouldn't be used yet! */
+
+
+#else
+#error No QIC-02 tape drive type defined!
+/* If your drive is not listed above, first try the 'ALL_FEATURES',
+ * to see what commands are supported, then create your own entry in
+ * the list above. You may want to mail it to me, so that I can include
+ * it in the next release.
+ */
+#endif
+
+#endif /* !CONFIG_QIC02_DYNCONF */
+
+
+/* WANGTEK interface card specifics */
+#define WT_QIC02_STAT_PORT (QIC02_TAPE_PORT)
+#define WT_QIC02_CTL_PORT (QIC02_TAPE_PORT)
+#define WT_QIC02_CMD_PORT (QIC02_TAPE_PORT+1)
+#define WT_QIC02_DATA_PORT (QIC02_TAPE_PORT+1)
+
+/* status register bits (Active LOW!) */
+#define WT_QIC02_STAT_POLARITY 0
+#define WT_QIC02_STAT_READY 0x01
+#define WT_QIC02_STAT_EXCEPTION 0x02
+#define WT_QIC02_STAT_MASK (WT_QIC02_STAT_READY|WT_QIC02_STAT_EXCEPTION)
+
+#define WT_QIC02_STAT_RESETMASK 0x07
+#define WT_QIC02_STAT_RESETVAL (WT_QIC02_STAT_RESETMASK & ~WT_QIC02_STAT_EXCEPTION)
+
+/* controller register (QIC02_CTL_PORT) bits */
+#define WT_QIC02_CTL_RESET 0x02
+#define WT_QIC02_CTL_REQUEST 0x04
+#define WT_CTL_ONLINE 0x01
+#define WT_CTL_CMDOFF 0xC0
+
+#define WT_CTL_DMA3 0x10 /* enable dma chan3 */
+#define WT_CTL_DMA1 0x08 /* enable dma chan1 or chan2 */
+
+/* EMERALD interface card specifics
+ * Much like Wangtek, only different polarity and bit locations
+ */
+#define EMR_QIC02_STAT_PORT (QIC02_TAPE_PORT)
+#define EMR_QIC02_CTL_PORT (QIC02_TAPE_PORT)
+#define EMR_QIC02_CMD_PORT (QIC02_TAPE_PORT+1)
+#define EMR_QIC02_DATA_PORT (QIC02_TAPE_PORT+1)
+
+/* status register bits (Active High!) */
+#define EMR_QIC02_STAT_POLARITY 1
+#define EMR_QIC02_STAT_READY 0x01
+#define EMR_QIC02_STAT_EXCEPTION 0x02
+#define EMR_QIC02_STAT_MASK (EMR_QIC02_STAT_READY|EMR_QIC02_STAT_EXCEPTION)
+
+#define EMR_QIC02_STAT_RESETMASK 0x07
+#define EMR_QIC02_STAT_RESETVAL (EMR_QIC02_STAT_RESETMASK & ~EMR_QIC02_STAT_EXCEPTION)
+
+/* controller register (QIC02_CTL_PORT) bits */
+#define EMR_QIC02_CTL_RESET 0x02
+#define EMR_QIC02_CTL_REQUEST 0x04
+#define EMR_CTL_ONLINE 0x01
+#define EMR_CTL_CMDOFF 0xC0
+
+#define EMR_CTL_DMA3 0x10 /* enable dma chan3 */
+#define EMR_CTL_DMA1 0x08 /* enable dma chan1 or chan2 */
+
+
+
+/* ARCHIVE interface card specifics */
+#define AR_QIC02_STAT_PORT (QIC02_TAPE_PORT+1)
+#define AR_QIC02_CTL_PORT (QIC02_TAPE_PORT+1)
+#define AR_QIC02_CMD_PORT (QIC02_TAPE_PORT)
+#define AR_QIC02_DATA_PORT (QIC02_TAPE_PORT)
+
+#define AR_START_DMA_PORT (QIC02_TAPE_PORT+2)
+#define AR_RESET_DMA_PORT (QIC02_TAPE_PORT+3)
+
+/* STAT port bits */
+#define AR_QIC02_STAT_POLARITY 0
+#define AR_STAT_IRQF 0x80 /* active high, interrupt request flag */
+#define AR_QIC02_STAT_READY 0x40 /* active low */
+#define AR_QIC02_STAT_EXCEPTION 0x20 /* active low */
+#define AR_QIC02_STAT_MASK (AR_QIC02_STAT_READY|AR_QIC02_STAT_EXCEPTION)
+#define AR_STAT_DMADONE 0x10 /* active high, DMA done */
+#define AR_STAT_DIRC 0x08 /* active high, direction */
+
+#define AR_QIC02_STAT_RESETMASK 0x70 /* check RDY,EXC,DMADONE */
+#define AR_QIC02_STAT_RESETVAL ((AR_QIC02_STAT_RESETMASK & ~AR_STAT_IRQF & ~AR_QIC02_STAT_EXCEPTION) | AR_STAT_DMADONE)
+
+/* CTL port bits */
+#define AR_QIC02_CTL_RESET 0x80 /* drive reset */
+#define AR_QIC02_CTL_REQUEST 0x40 /* notify of new command */
+#define AR_CTL_IEN 0x20 /* interrupt enable */
+#define AR_CTL_DNIEN 0x10 /* done-interrupt enable */
+ /* Note: All of these bits are cleared automatically when writing to
+ * AR_RESET_DMA_PORT. So AR_CTL_IEN and AR_CTL_DNIEN must be
+ * reprogrammed before the write to AR_START_DMA_PORT.
+ */
+
+
+/* MOUNTAIN interface specifics */
+#define MTN_QIC02_STAT_PORT (QIC02_TAPE_PORT+1)
+#define MTN_QIC02_CTL_PORT (QIC02_TAPE_PORT+1)
+#define MTN_QIC02_CMD_PORT (QIC02_TAPE_PORT)
+#define MTN_QIC02_DATA_PORT (QIC02_TAPE_PORT)
+
+#define MTN_W_SELECT_DMA_PORT (QIC02_TAPE_PORT+2)
+#define MTN_R_DESELECT_DMA_PORT (QIC02_TAPE_PORT+2)
+#define MTN_W_DMA_WRITE_PORT (QIC02_TAPE_PORT+3)
+
+/* STAT port bits */
+#define MTN_QIC02_STAT_POLARITY 0
+#define MTN_QIC02_STAT_READY 0x02 /* active low */
+#define MTN_QIC02_STAT_EXCEPTION 0x04 /* active low */
+#define MTN_QIC02_STAT_MASK (MTN_QIC02_STAT_READY|MTN_QIC02_STAT_EXCEPTION)
+#define MTN_STAT_DMADONE 0x01 /* active high, DMA done */
+
+#define MTN_QIC02_STAT_RESETMASK 0x07 /* check RDY,EXC,DMADONE */
+#define MTN_QIC02_STAT_RESETVAL ((MTN_QIC02_STAT_RESETMASK & ~MTN_QIC02_STAT_EXCEPTION) | MTN_STAT_DMADONE)
+
+/* CTL port bits */
+#define MTN_QIC02_CTL_RESET_NOT 0x80 /* drive reset, active low */
+#define MTN_QIC02_CTL_RESET 0x80 /* Fodder #definition to keep gcc happy */
+
+#define MTN_QIC02_CTL_ONLINE 0x40 /* Put drive on line */
+#define MTN_QIC02_CTL_REQUEST 0x20 /* notify of new command */
+#define MTN_QIC02_CTL_IRQ_DRIVER 0x10 /* Enable IRQ tristate driver */
+#define MTN_QIC02_CTL_DMA_DRIVER 0x08 /* Enable DMA tristate driver */
+#define MTN_CTL_EXC_IEN 0x04 /* Exception interrupt enable */
+#define MTN_CTL_RDY_IEN 0x02 /* Ready interrupt enable */
+#define MTN_CTL_DNIEN 0x01 /* done-interrupt enable */
+
+#define MTN_CTL_ONLINE (MTN_QIC02_CTL_RESET_NOT | MTN_QIC02_CTL_IRQ_DRIVER | MTN_QIC02_CTL_DMA_DRIVER)
+
+
+#ifndef CONFIG_QIC02_DYNCONF
+
+# define QIC02_TAPE_DEBUG (qic02_tape_debug)
+
+# if QIC02_TAPE_IFC == WANGTEK
+# define QIC02_STAT_POLARITY WT_QIC02_STAT_POLARITY
+# define QIC02_STAT_PORT WT_QIC02_STAT_PORT
+# define QIC02_CTL_PORT WT_QIC02_CTL_PORT
+# define QIC02_CMD_PORT WT_QIC02_CMD_PORT
+# define QIC02_DATA_PORT WT_QIC02_DATA_PORT
+
+# define QIC02_STAT_READY WT_QIC02_STAT_READY
+# define QIC02_STAT_EXCEPTION WT_QIC02_STAT_EXCEPTION
+# define QIC02_STAT_MASK WT_QIC02_STAT_MASK
+# define QIC02_STAT_RESETMASK WT_QIC02_STAT_RESETMASK
+# define QIC02_STAT_RESETVAL WT_QIC02_STAT_RESETVAL
+
+# define QIC02_CTL_RESET WT_QIC02_CTL_RESET
+# define QIC02_CTL_REQUEST WT_QIC02_CTL_REQUEST
+
+# if QIC02_TAPE_DMA == 3
+# ifdef QIC02_TAPE_DMA3_FIX
+# define WT_CTL_DMA WT_CTL_DMA1
+# else
+# define WT_CTL_DMA WT_CTL_DMA3
+# endif
+# elif QIC02_TAPE_DMA == 1
+# define WT_CTL_DMA WT_CTL_DMA1
+# else
+# error Unsupported or incorrect DMA configuration.
+# endif
+
+# elif QIC02_TAPE_IFC == EMERALD
+# define QIC02_STAT_POLARITY EMR_QIC02_STAT_POLARITY
+# define QIC02_STAT_PORT EMR_QIC02_STAT_PORT
+# define QIC02_CTL_PORT EMR_QIC02_CTL_PORT
+# define QIC02_CMD_PORT EMR_QIC02_CMD_PORT
+# define QIC02_DATA_PORT EMR_QIC02_DATA_PORT
+
+# define QIC02_STAT_READY EMR_QIC02_STAT_READY
+# define QIC02_STAT_EXCEPTION EMR_QIC02_STAT_EXCEPTION
+# define QIC02_STAT_MASK EMR_QIC02_STAT_MASK
+# define QIC02_STAT_RESETMASK EMR_QIC02_STAT_RESETMASK
+# define QIC02_STAT_RESETVAL EMR_QIC02_STAT_RESETVAL
+
+# define QIC02_CTL_RESET EMR_QIC02_CTL_RESET
+# define QIC02_CTL_REQUEST EMR_QIC02_CTL_REQUEST
+
+# if QIC02_TAPE_DMA == 3
+# ifdef QIC02_TAPE_DMA3_FIX
+# define EMR_CTL_DMA EMR_CTL_DMA1
+# else
+# define EMR_CTL_DMA EMR_CTL_DMA3
+# endif
+# elif QIC02_TAPE_DMA == 1
+# define EMR_CTL_DMA EMR_CTL_DMA1
+# else
+# error Unsupported or incorrect DMA configuration.
+# endif
+
+# elif QIC02_TAPE_IFC == ARCHIVE
+# define QIC02_STAT_POLARITY AR_QIC02_STAT_POLARITY
+# define QIC02_STAT_PORT AR_QIC02_STAT_PORT
+# define QIC02_CTL_PORT AR_QIC02_CTL_PORT
+# define QIC02_CMD_PORT AR_QIC02_CMD_PORT
+# define QIC02_DATA_PORT AR_QIC02_DATA_PORT
+
+# define QIC02_STAT_READY AR_QIC02_STAT_READY
+# define QIC02_STAT_EXCEPTION AR_QIC02_STAT_EXCEPTION
+# define QIC02_STAT_MASK AR_QIC02_STAT_MASK
+# define QIC02_STAT_RESETMASK AR_QIC02_STAT_RESETMASK
+# define QIC02_STAT_RESETVAL AR_QIC02_STAT_RESETVAL
+
+# define QIC02_CTL_RESET AR_QIC02_CTL_RESET
+# define QIC02_CTL_REQUEST AR_QIC02_CTL_REQUEST
+
+# if QIC02_TAPE_DMA > 3 /* channel 2 is used by the floppy driver */
+# error DMA channels other than 1 and 3 are not supported.
+# endif
+
+# elif QIC02_TAPE_IFC == MOUNTAIN
+# define QIC02_STAT_POLARITY MTN_QIC02_STAT_POLARITY
+# define QIC02_STAT_PORT MTN_QIC02_STAT_PORT
+# define QIC02_CTL_PORT MTN_QIC02_CTL_PORT
+# define QIC02_CMD_PORT MTN_QIC02_CMD_PORT
+# define QIC02_DATA_PORT MTN_QIC02_DATA_PORT
+
+# define QIC02_STAT_READY MTN_QIC02_STAT_READY
+# define QIC02_STAT_EXCEPTION MTN_QIC02_STAT_EXCEPTION
+# define QIC02_STAT_MASK MTN_QIC02_STAT_MASK
+# define QIC02_STAT_RESETMASK MTN_QIC02_STAT_RESETMASK
+# define QIC02_STAT_RESETVAL MTN_QIC02_STAT_RESETVAL
+
+# define QIC02_CTL_RESET MTN_QIC02_CTL_RESET
+# define QIC02_CTL_REQUEST MTN_QIC02_CTL_REQUEST
+
+# if QIC02_TAPE_DMA > 3 /* channel 2 is used by the floppy driver */
+# error DMA channels other than 1 and 3 are not supported.
+# endif
+
+# else
+# error No valid interface card specified!
+# endif /* QIC02_TAPE_IFC */
+
+
+ /* An ugly hack to make sure WT_CTL_DMA is defined even for the
+ * static, non-Wangtek case. The alternative was even worse.
+ */
+# ifndef WT_CTL_DMA
+# define WT_CTL_DMA WT_CTL_DMA1
+# endif
+
+/*******************/
+
+#else /* !CONFIG_QIC02_DYNCONF */
+
+/* Now the runtime config version, using variables instead of constants.
+ *
+ * qic02_tape_dynconf is R/O for the kernel, set from userspace.
+ * qic02_tape_ccb is private to the driver, R/W.
+ */
+
+# define QIC02_TAPE_DRIVE (qic02_tape_dynconf.mt_type)
+# define QIC02_TAPE_IFC (qic02_tape_ccb.ifc_type)
+# define QIC02_TAPE_IRQ (qic02_tape_dynconf.irqnr)
+# define QIC02_TAPE_DMA (qic02_tape_dynconf.dmanr)
+# define QIC02_TAPE_PORT (qic02_tape_dynconf.port)
+# define WT_CTL_DMA (qic02_tape_ccb.dma_enable_value)
+# define QIC02_TAPE_DEBUG (qic02_tape_dynconf.debug)
+
+# define QIC02_STAT_PORT (qic02_tape_ccb.port_stat)
+# define QIC02_CTL_PORT (qic02_tape_ccb.port_ctl)
+# define QIC02_CMD_PORT (qic02_tape_ccb.port_cmd)
+# define QIC02_DATA_PORT (qic02_tape_ccb.port_data)
+
+# define QIC02_STAT_POLARITY (qic02_tape_ccb.stat_polarity)
+# define QIC02_STAT_READY (qic02_tape_ccb.stat_ready)
+# define QIC02_STAT_EXCEPTION (qic02_tape_ccb.stat_exception)
+# define QIC02_STAT_MASK (qic02_tape_ccb.stat_mask)
+
+# define QIC02_STAT_RESETMASK (qic02_tape_ccb.stat_resetmask)
+# define QIC02_STAT_RESETVAL (qic02_tape_ccb.stat_resetval)
+
+# define QIC02_CTL_RESET (qic02_tape_ccb.ctl_reset)
+# define QIC02_CTL_REQUEST (qic02_tape_ccb.ctl_request)
+
+# define TP_HAVE_DENS (qic02_tape_dynconf.have_dens)
+# define TP_HAVE_BSF (qic02_tape_dynconf.have_bsf)
+# define TP_HAVE_FSR (qic02_tape_dynconf.have_fsr)
+# define TP_HAVE_BSR (qic02_tape_dynconf.have_bsr)
+# define TP_HAVE_EOD (qic02_tape_dynconf.have_eod)
+# define TP_HAVE_SEEK (qic02_tape_dynconf.have_seek)
+# define TP_HAVE_TELL (qic02_tape_dynconf.have_tell)
+# define TP_HAVE_RAS1 (qic02_tape_dynconf.have_ras1)
+# define TP_HAVE_RAS2 (qic02_tape_dynconf.have_ras2)
+
+#endif /* CONFIG_QIC02_DYNCONF */
+
+
+/* "Vendor Unique" codes */
+/* Archive seek & tell stuff */
+#define AR_QCMDV_TELL_BLK 0xAE /* read current block address */
+#define AR_QCMDV_SEEK_BLK 0xAD /* seek to specific block */
+#define AR_SEEK_BUF_SIZE 3 /* address is 3 bytes */
+
+
+
+/*
+ * Misc common stuff
+ */
+
+/* Standard QIC-02 commands -- rev F. All QIC-02 drives must support these */
+#define QCMD_SEL_1 0x01 /* select drive 1 */
+#define QCMD_SEL_2 0x02 /* select drive 2 */
+#define QCMD_SEL_3 0x04 /* select drive 3 */
+#define QCMD_SEL_4 0x08 /* select drive 4 */
+#define QCMD_REWIND 0x21 /* rewind tape */
+#define QCMD_ERASE 0x22 /* erase tape */
+#define QCMD_RETEN 0x24 /* retension tape */
+#define QCMD_WRT_DATA 0x40 /* write data */
+#define QCMD_WRT_FM 0x60 /* write file mark */
+#define QCMD_RD_DATA 0x80 /* read data */
+#define QCMD_RD_FM 0xA0 /* read file mark (forward direction) */
+#define QCMD_RD_STAT 0xC0 /* read status */
+
+/* Other (optional/vendor unique) commands */
+ /* Density commands are only valid when TP_BOM is set! */
+#define QCMD_DENS_11 0x26 /* QIC-11 */
+#define QCMD_DENS_24 0x27 /* QIC-24: 9 track 60MB */
+#define QCMD_DENS_120 0x28 /* QIC-120: 15 track 120MB */
+#define QCMD_DENS_150 0x29 /* QIC-150: 18 track 150MB */
+#define QCMD_DENS_300 0x2A /* QIC-300/QIC-2100 */
+#define QCMD_DENS_600 0x2B /* QIC-600/QIC-2200 */
+/* don't know about QIC-1000 and QIC-1350 */
+
+#define QCMD_WRTNU_DATA 0x40 /* write data, no underruns, insert filler. */
+#define QCMD_SPACE_FWD 0x81 /* skip next block */
+#define QCMD_SPACE_BCK 0x89 /* move tape head one block back -- very useful! */
+#define QCMD_RD_FM_BCK 0xA8 /* read filemark (backwards) */
+#define QCMD_SEEK_EOD 0xA3 /* skip to EOD */
+#define QCMD_RD_STAT_X1 0xC1 /* read extended status 1 */
+#define QCMD_RD_STAT_X2 0xC4 /* read extended status 2 */
+#define QCMD_RD_STAT_X3 0xE0 /* read extended status 3 */
+#define QCMD_SELF_TST1 0xC2 /* run self test 1 (nondestructive) */
+#define QCMD_SELF_TST2 0xCA /* run self test 2 (destructive) */
+
+
+
+/* Optional, QFA (Quick File Access) commands.
+ * Not all drives support this, but those that do could use these commands
+ * to implement semi-non-sequential access. `mt fsf` would benefit from this.
+ * QFA divides the tape into 2 partitions, a data and a directory partition,
+ * causing some incompatibility problems wrt std QIC-02 data exchange.
+ * It would be useful to cache the directory info, but that might be tricky
+ * to do in kernel-space. [Size constraints.]
+ * Refer to the QIC-02 specs, appendix A for more information.
+ * I have no idea how other *nix variants implement QFA.
+ * I have no idea which drives support QFA and which don't.
+ */
+#define QFA_ENABLE 0x2D /* enter QFA mode, give @ BOT only */
+#define QFA_DATA 0x20 /* select data partition */
+#define QFA_DIR 0x23 /* select directory partition */
+#define QFA_RD_POS 0xCF /* read position+status bytes */
+#define QFA_SEEK_EOD 0xA1 /* seek EOD within current partition */
+#define QFA_SEEK_BLK 0xAF /* seek to a block within current partition */
+
+
+
+
+/*
+ * Debugging flags
+ */
+#define TPQD_SENSE_TEXT 0x0001
+#define TPQD_SENSE_CNTS 0x0002
+#define TPQD_REWIND 0x0004
+#define TPQD_TERM_CYCLE 0x0008
+#define TPQD_IOCTLS 0x0010
+#define TPQD_DMAX 0x0020
+#define TPQD_BLKSZ 0x0040
+#define TPQD_MISC 0x0080
+
+#define TPQD_DEBUG 0x0100
+
+#define TPQD_DIAGS 0x1000
+
+#define TPQD_ALWAYS 0x8000
+
+#define TPQD_DEFAULT_FLAGS 0x00fc
+
+
+#define TPQDBG(f) ((QIC02_TAPE_DEBUG) & (TPQD_##f))
+
+
+/* Minor device codes for tapes:
+ * |7|6|5|4|3|2|1|0|
+ * | \ | / \ | / |_____ 1=rewind on close, 0=no rewind on close
+ * | \|/ |_________ Density: 000=none, 001=QIC-11, 010=24, 011=120,
+ * | | 100=QIC-150, 101..111 reserved.
+ * | |_______________ Reserved for unit numbers.
+ * |___________________ Reserved for diagnostics during debugging.
+ */
+
+#define TP_REWCLOSE(d) ((MINOR(d)&0x01) == 1) /* rewind bit */
+ /* rewind is only done if data has been transfered */
+#define TP_DENS(dev) ((MINOR(dev) >> 1) & 0x07) /* tape density */
+#define TP_UNIT(dev) ((MINOR(dev) >> 4) & 0x07) /* unit number */
+
+/* print excessive diagnostics */
+#define TP_DIAGS(dev) (QIC02_TAPE_DEBUG & TPQD_DIAGS)
+
+/* status codes returned by a WTS_RDSTAT call */
+struct tpstatus { /* sizeof(short)==2), LSB first */
+ unsigned short exs; /* Drive exception flags */
+ unsigned short dec; /* data error count: nr of blocks rewritten/soft read errors */
+ unsigned short urc; /* underrun count: nr of times streaming was interrupted */
+};
+#define TPSTATSIZE sizeof(struct tpstatus)
+
+
+/* defines for tpstatus.exs -- taken from 386BSD wt driver */
+#define TP_POR 0x100 /* Power on or reset occurred */
+#define TP_EOR 0x200 /* REServed for end of RECORDED media */
+#define TP_PAR 0x400 /* REServed for bus parity */
+#define TP_BOM 0x800 /* Beginning of media */
+#define TP_MBD 0x1000 /* Marginal block detected */
+#define TP_NDT 0x2000 /* No data detected */
+#define TP_ILL 0x4000 /* Illegal command */
+#define TP_ST1 0x8000 /* Status byte 1 flag */
+#define TP_FIL 0x01 /* File mark detected */
+#define TP_BNL 0x02 /* Bad block not located */
+#define TP_UDA 0x04 /* Unrecoverable data error */
+#define TP_EOM 0x08 /* End of media */
+#define TP_WRP 0x10 /* Write protected cartridge */
+#define TP_USL 0x20 /* Unselected drive */
+#define TP_CNI 0x40 /* Cartridge not in place */
+#define TP_ST0 0x80 /* Status byte 0 flag */
+
+#define REPORT_ERR0 (TP_CNI|TP_USL|TP_WRP|TP_EOM|TP_UDA|TP_BNL|TP_FIL)
+#define REPORT_ERR1 (TP_ILL|TP_NDT|TP_MBD|TP_PAR)
+
+
+/* exception numbers */
+#define EXC_UNKNOWN 0 /* (extra) Unknown exception code */
+#define EXC_NDRV 1 /* No drive */
+#define EXC_NCART 2 /* No cartridge */
+#define EXC_WP 3 /* Write protected */
+#define EXC_EOM 4 /* EOM */
+#define EXC_RWA 5 /* read/write abort */
+#define EXC_XBAD 6 /* read error, bad block transfered */
+#define EXC_XFILLER 7 /* read error, filler block transfered */
+#define EXC_NDT 8 /* read error, no data */
+#define EXC_NDTEOM 9 /* read error, no data & EOM */
+#define EXC_NDTBOM 10 /* read error, no data & BOM */
+#define EXC_FM 11 /* Read a filemark */
+#define EXC_ILL 12 /* Illegal command */
+#define EXC_POR 13 /* Power on/reset */
+#define EXC_MARGINAL 14 /* Marginal block detected */
+#define EXC_EOR 15 /* (extra, for SEEKEOD) End Of Recorded data reached */
+#define EXC_BOM 16 /* (extra) BOM reached */
+
+
+#define TAPE_NOTIFY_TIMEOUT 1000000
+
+/* internal function return codes */
+#define TE_OK 0 /* everything is fine */
+#define TE_EX 1 /* exception detected */
+#define TE_ERR 2 /* some error */
+#define TE_NS 3 /* can't read status */
+#define TE_TIM 4 /* timed out */
+#define TE_DEAD 5 /* tape drive doesn't respond */
+#define TE_END 6 /******** Archive hack *****/
+
+/* timeout timer values -- check these! */
+#define TIM_S (4*HZ) /* 4 seconds (normal cmds) */
+#define TIM_M (30*HZ) /* 30 seconds (write FM) */
+#define TIM_R (8*60*HZ) /* 8 minutes (retensioning) */
+#define TIM_F (2*3600*HZ) /* est. 1.2hr for full tape read/write+2 retens */
+
+#define TIMERON(t) timer_table[QIC02_TAPE_TIMER].expires = jiffies + (t); \
+ timer_active |= (1<<QIC02_TAPE_TIMER)
+#define TIMEROFF timer_active &= ~(1<<QIC02_TAPE_TIMER)
+#define TIMERCONT timer_active |= (1<<QIC02_TAPE_TIMER)
+
+
+typedef char flag;
+#define NO 0 /* NO must be 0 */
+#define YES 1 /* YES must be != 0 */
+
+
+#ifdef TDEBUG
+# define TPQDEB(s) s
+# define TPQPUTS(s) tpqputs(s)
+#else
+# define TPQDEB(s)
+# define TPQPUTS(s)
+#endif
+
+
+/* NR_BLK_BUF is a `tuneable parameter'. If you're really low on
+ * kernel space, you could decrease it to 1, or if you got a very
+ * slow machine, you could increase it up to 127 blocks. Less kernel
+ * buffer blocks result in more context-switching.
+ */
+#define NR_BLK_BUF 20 /* max 127 blocks */
+#define TAPE_BLKSIZE 512 /* streamer tape block size (fixed) */
+#define TPQBUF_SIZE (TAPE_BLKSIZE*NR_BLK_BUF) /* buffer size */
+
+
+#define BLOCKS_BEYOND_EW 2 /* nr of blocks after Early Warning hole */
+#define BOGUS_IRQ 32009
+
+
+/* This is internal data, filled in based on the ifc_type field given
+ * by the user. Everex is mapped to Wangtek with a different
+ * `dma_enable_value', if dmanr==3.
+ */
+struct qic02_ccb {
+ long ifc_type;
+
+ unsigned short port_stat; /* Status port address */
+ unsigned short port_ctl; /* Control port address */
+ unsigned short port_cmd; /* Command port address */
+ unsigned short port_data; /* Data port address */
+
+ /* status register bits */
+ unsigned short stat_polarity; /* invert status bits or not */
+ unsigned short stat_ready; /* drive ready */
+ unsigned short stat_exception; /* drive signals exception */
+ unsigned short stat_mask;
+ unsigned short stat_resetmask;
+ unsigned short stat_resetval;
+
+ /* control register bits */
+ unsigned short ctl_reset; /* reset drive */
+ unsigned short ctl_request; /* latch command */
+
+ /* This is used to change the DMA3 behaviour */
+ unsigned short dma_enable_value;
+};
+
+#if MODULE
+static int qic02_tape_init(void);
+#else
+extern int qic02_tape_init(void); /* for mem.c */
+#endif
+
+
+
+#endif /* CONFIG_QIC02_TAPE */
+
+#endif /* _LINUX_TPQIC02_H */
+
diff --git a/pfinet/linux-src/include/linux/tqueue.h b/pfinet/linux-src/include/linux/tqueue.h
new file mode 100644
index 00000000..d886f753
--- /dev/null
+++ b/pfinet/linux-src/include/linux/tqueue.h
@@ -0,0 +1,124 @@
+/*
+ * tqueue.h --- task queue handling for Linux.
+ *
+ * Mostly based on a proposed bottom-half replacement code written by
+ * Kai Petzke, wpp@marie.physik.tu-berlin.de.
+ *
+ * Modified for use in the Linux kernel by Theodore Ts'o,
+ * tytso@mit.edu. Any bugs are my fault, not Kai's.
+ *
+ * The original comment follows below.
+ */
+
+#ifndef _LINUX_TQUEUE_H
+#define _LINUX_TQUEUE_H
+
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/spinlock.h>
+
+/*
+ * New proposed "bottom half" handlers:
+ * (C) 1994 Kai Petzke, wpp@marie.physik.tu-berlin.de
+ *
+ * Advantages:
+ * - Bottom halfs are implemented as a linked list. You can have as many
+ * of them, as you want.
+ * - No more scanning of a bit field is required upon call of a bottom half.
+ * - Support for chained bottom half lists. The run_task_queue() function can be
+ * used as a bottom half handler. This is for example useful for bottom
+ * halfs, which want to be delayed until the next clock tick.
+ *
+ * Problems:
+ * - The queue_task_irq() inline function is only atomic with respect to itself.
+ * Problems can occur, when queue_task_irq() is called from a normal system
+ * call, and an interrupt comes in. No problems occur, when queue_task_irq()
+ * is called from an interrupt or bottom half, and interrupted, as run_task_queue()
+ * will not be executed/continued before the last interrupt returns. If in
+ * doubt, use queue_task(), not queue_task_irq().
+ * - Bottom halfs are called in the reverse order that they were linked into
+ * the list.
+ */
+
+struct tq_struct {
+ struct tq_struct *next; /* linked list of active bh's */
+ unsigned long sync; /* must be initialized to zero */
+ void (*routine)(void *); /* function to call */
+ void *data; /* argument to function */
+};
+
+typedef struct tq_struct * task_queue;
+
+#define DECLARE_TASK_QUEUE(q) task_queue q = NULL
+
+extern task_queue tq_timer, tq_immediate, tq_scheduler, tq_disk;
+
+/*
+ * To implement your own list of active bottom halfs, use the following
+ * two definitions:
+ *
+ * struct tq_struct *my_bh = NULL;
+ * struct tq_struct run_my_bh = {
+ * 0, 0, (void (*)(void *)) run_task_queue, &my_bh
+ * };
+ *
+ * To activate a bottom half on your list, use:
+ *
+ * queue_task(tq_pointer, &my_bh);
+ *
+ * To run the bottom halfs on your list put them on the immediate list by:
+ *
+ * queue_task(&run_my_bh, &tq_immediate);
+ *
+ * This allows you to do deferred procession. For example, you could
+ * have a bottom half list tq_timer, which is marked active by the timer
+ * interrupt.
+ */
+
+extern spinlock_t tqueue_lock;
+
+/*
+ * queue_task
+ */
+extern __inline__ void queue_task(struct tq_struct *bh_pointer,
+ task_queue *bh_list)
+{
+ if (!test_and_set_bit(0,&bh_pointer->sync)) {
+ unsigned long flags;
+ spin_lock_irqsave(&tqueue_lock, flags);
+ bh_pointer->next = *bh_list;
+ *bh_list = bh_pointer;
+ spin_unlock_irqrestore(&tqueue_lock, flags);
+ }
+}
+
+/*
+ * Call all "bottom halfs" on a given list.
+ */
+extern __inline__ void run_task_queue(task_queue *list)
+{
+ if (*list) {
+ unsigned long flags;
+ struct tq_struct *p;
+
+ spin_lock_irqsave(&tqueue_lock, flags);
+ p = *list;
+ *list = NULL;
+ spin_unlock_irqrestore(&tqueue_lock, flags);
+
+ while (p) {
+ void *arg;
+ void (*f) (void *);
+ struct tq_struct *save_p;
+ arg = p -> data;
+ f = p -> routine;
+ save_p = p;
+ p = p -> next;
+ mb();
+ save_p -> sync = 0;
+ (*f)(arg);
+ }
+ }
+}
+
+#endif /* _LINUX_TQUEUE_H */
diff --git a/pfinet/linux-src/include/linux/trdevice.h b/pfinet/linux-src/include/linux/trdevice.h
new file mode 100644
index 00000000..8689db32
--- /dev/null
+++ b/pfinet/linux-src/include/linux/trdevice.h
@@ -0,0 +1,40 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. NET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the Token-ring handlers.
+ *
+ * Version: @(#)eth.h 1.0.4 05/13/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * Relocated to include/linux where it belongs by Alan Cox
+ * <gw4pts@gw4pts.ampr.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * WARNING: This move may well be temporary. This file will get merged with others RSN.
+ *
+ */
+#ifndef _LINUX_TRDEVICE_H
+#define _LINUX_TRDEVICE_H
+
+
+#include <linux/if_tr.h>
+
+#ifdef __KERNEL__
+extern int tr_header(struct sk_buff *skb, struct device *dev,
+ unsigned short type, void *daddr,
+ void *saddr, unsigned len);
+extern int tr_rebuild_header(struct sk_buff *skb);
+extern unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev);
+extern struct device * init_trdev(struct device *, int);
+
+#endif
+
+#endif /* _LINUX_TRDEVICE_H */
diff --git a/pfinet/linux-src/include/linux/tty.h b/pfinet/linux-src/include/linux/tty.h
new file mode 100644
index 00000000..55aabe43
--- /dev/null
+++ b/pfinet/linux-src/include/linux/tty.h
@@ -0,0 +1,413 @@
+#ifndef _LINUX_TTY_H
+#define _LINUX_TTY_H
+
+/*
+ * 'tty.h' defines some structures used by tty_io.c and some defines.
+ */
+
+/*
+ * These constants are also useful for user-level apps (e.g., VC
+ * resizing).
+ */
+#define MIN_NR_CONSOLES 1 /* must be at least 1 */
+#define MAX_NR_CONSOLES 63 /* serial lines start at 64 */
+#define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */
+ /* Note: the ioctl VT_GETSTATE does not work for
+ consoles 16 and higher (since it returns a short) */
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/termios.h>
+#include <linux/tqueue.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_ldisc.h>
+#include <linux/serialP.h>
+
+#include <asm/system.h>
+
+
+/*
+ * Note: don't mess with NR_PTYS until you understand the tty minor
+ * number allocation game...
+ * (Note: the *_driver.minor_start values 1, 64, 128, 192 are
+ * hardcoded at present.)
+ */
+#define NR_PTYS 256 /* ptys/major */
+#define NR_LDISCS 16
+
+/*
+ * Unix98 PTY's can be defined as any multiple of NR_PTYS up to
+ * UNIX98_PTY_MAJOR_COUNT; this section defines what we need from the
+ * config options
+ */
+#ifdef CONFIG_UNIX98_PTYS
+# define UNIX98_NR_MAJORS ((CONFIG_UNIX98_PTY_COUNT+NR_PTYS-1)/NR_PTYS)
+# if UNIX98_NR_MAJORS <= 0
+# undef CONFIG_UNIX98_PTYS
+# elif UNIX98_NR_MAJORS > UNIX98_PTY_MAJOR_COUNT
+# error Too many Unix98 ptys defined
+# undef UNIX98_NR_MAJORS
+# define UNIX98_NR_MAJORS UNIX98_PTY_MAJOR_COUNT
+# endif
+#endif
+
+/*
+ * These are set up by the setup-routine at boot-time:
+ */
+
+struct screen_info {
+ unsigned char orig_x; /* 0x00 */
+ unsigned char orig_y; /* 0x01 */
+ unsigned short dontuse1; /* 0x02 -- EXT_MEM_K sits here */
+ unsigned short orig_video_page; /* 0x04 */
+ unsigned char orig_video_mode; /* 0x06 */
+ unsigned char orig_video_cols; /* 0x07 */
+ unsigned short unused2; /* 0x08 */
+ unsigned short orig_video_ega_bx; /* 0x0a */
+ unsigned short unused3; /* 0x0c */
+ unsigned char orig_video_lines; /* 0x0e */
+ unsigned char orig_video_isVGA; /* 0x0f */
+ unsigned short orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ unsigned short lfb_width; /* 0x12 */
+ unsigned short lfb_height; /* 0x14 */
+ unsigned short lfb_depth; /* 0x16 */
+ unsigned long lfb_base; /* 0x18 */
+ unsigned long lfb_size; /* 0x1c */
+ unsigned short dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
+ unsigned short lfb_linelength; /* 0x24 */
+ unsigned char red_size; /* 0x26 */
+ unsigned char red_pos; /* 0x27 */
+ unsigned char green_size; /* 0x28 */
+ unsigned char green_pos; /* 0x29 */
+ unsigned char blue_size; /* 0x2a */
+ unsigned char blue_pos; /* 0x2b */
+ unsigned char rsvd_size; /* 0x2c */
+ unsigned char rsvd_pos; /* 0x2d */
+ unsigned short vesapm_seg; /* 0x2e */
+ unsigned short vesapm_off; /* 0x30 */
+ unsigned short pages; /* 0x32 */
+ /* 0x34 -- 0x3f reserved for future expansion */
+};
+
+extern struct screen_info screen_info;
+
+#define ORIG_X (screen_info.orig_x)
+#define ORIG_Y (screen_info.orig_y)
+#define ORIG_VIDEO_MODE (screen_info.orig_video_mode)
+#define ORIG_VIDEO_COLS (screen_info.orig_video_cols)
+#define ORIG_VIDEO_EGA_BX (screen_info.orig_video_ega_bx)
+#define ORIG_VIDEO_LINES (screen_info.orig_video_lines)
+#define ORIG_VIDEO_ISVGA (screen_info.orig_video_isVGA)
+#define ORIG_VIDEO_POINTS (screen_info.orig_video_points)
+
+#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */
+#define VIDEO_TYPE_CGA 0x11 /* CGA Display */
+#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */
+#define VIDEO_TYPE_EGAC 0x21 /* EGA in Color Mode */
+#define VIDEO_TYPE_VGAC 0x22 /* VGA+ in Color Mode */
+#define VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */
+
+#define VIDEO_TYPE_TGAC 0x40 /* DEC TGA */
+
+#define VIDEO_TYPE_SUN 0x50 /* Sun frame buffer. */
+#define VIDEO_TYPE_SUNPCI 0x51 /* Sun PCI based frame buffer. */
+
+#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */
+
+#define VIDEO_TYPE_SGI 0x70 /* Various SGI graphics hardware */
+#define VIDEO_TYPE_MIPS_G364 0x71 /* MIPS Magnum 4000 G364 video */
+
+/*
+ * This character is the same as _POSIX_VDISABLE: it cannot be used as
+ * a c_cc[] character, but indicates that a particular special character
+ * isn't in use (eg VINTR has no character etc)
+ */
+#define __DISABLED_CHAR '\0'
+
+/*
+ * This is the flip buffer used for the tty driver. The buffer is
+ * located in the tty structure, and is used as a high speed interface
+ * between the tty driver and the tty line discipline.
+ */
+#define TTY_FLIPBUF_SIZE 512
+
+struct tty_flip_buffer {
+ struct tq_struct tqueue;
+ struct semaphore pty_sem;
+ char *char_buf_ptr;
+ unsigned char *flag_buf_ptr;
+ int count;
+ int buf_num;
+ unsigned char char_buf[2*TTY_FLIPBUF_SIZE];
+ char flag_buf[2*TTY_FLIPBUF_SIZE];
+ unsigned char slop[4]; /* N.B. bug overwrites buffer by 1 */
+};
+/*
+ * The pty uses char_buf and flag_buf as a contiguous buffer
+ */
+#define PTY_BUF_SIZE 4*TTY_FLIPBUF_SIZE
+
+/*
+ * When a break, frame error, or parity error happens, these codes are
+ * stuffed into the flags buffer.
+ */
+#define TTY_NORMAL 0
+#define TTY_BREAK 1
+#define TTY_FRAME 2
+#define TTY_PARITY 3
+#define TTY_OVERRUN 4
+
+#define INTR_CHAR(tty) ((tty)->termios->c_cc[VINTR])
+#define QUIT_CHAR(tty) ((tty)->termios->c_cc[VQUIT])
+#define ERASE_CHAR(tty) ((tty)->termios->c_cc[VERASE])
+#define KILL_CHAR(tty) ((tty)->termios->c_cc[VKILL])
+#define EOF_CHAR(tty) ((tty)->termios->c_cc[VEOF])
+#define TIME_CHAR(tty) ((tty)->termios->c_cc[VTIME])
+#define MIN_CHAR(tty) ((tty)->termios->c_cc[VMIN])
+#define SWTC_CHAR(tty) ((tty)->termios->c_cc[VSWTC])
+#define START_CHAR(tty) ((tty)->termios->c_cc[VSTART])
+#define STOP_CHAR(tty) ((tty)->termios->c_cc[VSTOP])
+#define SUSP_CHAR(tty) ((tty)->termios->c_cc[VSUSP])
+#define EOL_CHAR(tty) ((tty)->termios->c_cc[VEOL])
+#define REPRINT_CHAR(tty) ((tty)->termios->c_cc[VREPRINT])
+#define DISCARD_CHAR(tty) ((tty)->termios->c_cc[VDISCARD])
+#define WERASE_CHAR(tty) ((tty)->termios->c_cc[VWERASE])
+#define LNEXT_CHAR(tty) ((tty)->termios->c_cc[VLNEXT])
+#define EOL2_CHAR(tty) ((tty)->termios->c_cc[VEOL2])
+
+#define _I_FLAG(tty,f) ((tty)->termios->c_iflag & (f))
+#define _O_FLAG(tty,f) ((tty)->termios->c_oflag & (f))
+#define _C_FLAG(tty,f) ((tty)->termios->c_cflag & (f))
+#define _L_FLAG(tty,f) ((tty)->termios->c_lflag & (f))
+
+#define I_IGNBRK(tty) _I_FLAG((tty),IGNBRK)
+#define I_BRKINT(tty) _I_FLAG((tty),BRKINT)
+#define I_IGNPAR(tty) _I_FLAG((tty),IGNPAR)
+#define I_PARMRK(tty) _I_FLAG((tty),PARMRK)
+#define I_INPCK(tty) _I_FLAG((tty),INPCK)
+#define I_ISTRIP(tty) _I_FLAG((tty),ISTRIP)
+#define I_INLCR(tty) _I_FLAG((tty),INLCR)
+#define I_IGNCR(tty) _I_FLAG((tty),IGNCR)
+#define I_ICRNL(tty) _I_FLAG((tty),ICRNL)
+#define I_IUCLC(tty) _I_FLAG((tty),IUCLC)
+#define I_IXON(tty) _I_FLAG((tty),IXON)
+#define I_IXANY(tty) _I_FLAG((tty),IXANY)
+#define I_IXOFF(tty) _I_FLAG((tty),IXOFF)
+#define I_IMAXBEL(tty) _I_FLAG((tty),IMAXBEL)
+
+#define O_OPOST(tty) _O_FLAG((tty),OPOST)
+#define O_OLCUC(tty) _O_FLAG((tty),OLCUC)
+#define O_ONLCR(tty) _O_FLAG((tty),ONLCR)
+#define O_OCRNL(tty) _O_FLAG((tty),OCRNL)
+#define O_ONOCR(tty) _O_FLAG((tty),ONOCR)
+#define O_ONLRET(tty) _O_FLAG((tty),ONLRET)
+#define O_OFILL(tty) _O_FLAG((tty),OFILL)
+#define O_OFDEL(tty) _O_FLAG((tty),OFDEL)
+#define O_NLDLY(tty) _O_FLAG((tty),NLDLY)
+#define O_CRDLY(tty) _O_FLAG((tty),CRDLY)
+#define O_TABDLY(tty) _O_FLAG((tty),TABDLY)
+#define O_BSDLY(tty) _O_FLAG((tty),BSDLY)
+#define O_VTDLY(tty) _O_FLAG((tty),VTDLY)
+#define O_FFDLY(tty) _O_FLAG((tty),FFDLY)
+
+#define C_BAUD(tty) _C_FLAG((tty),CBAUD)
+#define C_CSIZE(tty) _C_FLAG((tty),CSIZE)
+#define C_CSTOPB(tty) _C_FLAG((tty),CSTOPB)
+#define C_CREAD(tty) _C_FLAG((tty),CREAD)
+#define C_PARENB(tty) _C_FLAG((tty),PARENB)
+#define C_PARODD(tty) _C_FLAG((tty),PARODD)
+#define C_HUPCL(tty) _C_FLAG((tty),HUPCL)
+#define C_CLOCAL(tty) _C_FLAG((tty),CLOCAL)
+#define C_CIBAUD(tty) _C_FLAG((tty),CIBAUD)
+#define C_CRTSCTS(tty) _C_FLAG((tty),CRTSCTS)
+
+#define L_ISIG(tty) _L_FLAG((tty),ISIG)
+#define L_ICANON(tty) _L_FLAG((tty),ICANON)
+#define L_XCASE(tty) _L_FLAG((tty),XCASE)
+#define L_ECHO(tty) _L_FLAG((tty),ECHO)
+#define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
+#define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
+#define L_ECHONL(tty) _L_FLAG((tty),ECHONL)
+#define L_NOFLSH(tty) _L_FLAG((tty),NOFLSH)
+#define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP)
+#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
+#define L_ECHOPRT(tty) _L_FLAG((tty),ECHOPRT)
+#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
+#define L_FLUSHO(tty) _L_FLAG((tty),FLUSHO)
+#define L_PENDIN(tty) _L_FLAG((tty),PENDIN)
+#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN)
+
+/*
+ * Where all of the state associated with a tty is kept while the tty
+ * is open. Since the termios state should be kept even if the tty
+ * has been closed --- for things like the baud rate, etc --- it is
+ * not stored here, but rather a pointer to the real state is stored
+ * here. Possible the winsize structure should have the same
+ * treatment, but (1) the default 80x24 is usually right and (2) it's
+ * most often used by a windowing system, which will set the correct
+ * size each time the window is created or resized anyway.
+ * IMPORTANT: since this structure is dynamically allocated, it must
+ * be no larger than 4096 bytes. Changing TTY_FLIPBUF_SIZE will change
+ * the size of this structure, and it needs to be done with care.
+ * - TYT, 9/14/92
+ */
+struct tty_struct {
+ int magic;
+ struct tty_driver driver;
+ struct tty_ldisc ldisc;
+ struct termios *termios, *termios_locked;
+ int pgrp;
+ int session;
+ kdev_t device;
+ unsigned long flags;
+ int count;
+ struct winsize winsize;
+ unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
+ unsigned char low_latency:1, warned:1;
+ unsigned char ctrl_status;
+
+ struct tty_struct *link;
+ struct fasync_struct *fasync;
+ struct tty_flip_buffer flip;
+ int max_flip_cnt;
+ int alt_speed; /* For magic substitution of 38400 bps */
+ struct wait_queue *write_wait;
+ struct wait_queue *read_wait;
+ struct tq_struct tq_hangup;
+ void *disc_data;
+ void *driver_data;
+
+#define N_TTY_BUF_SIZE 4096
+
+ /*
+ * The following is data for the N_TTY line discipline. For
+ * historical reasons, this is included in the tty structure.
+ */
+ unsigned int column;
+ unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
+ unsigned char closing:1;
+ unsigned short minimum_to_wake;
+ unsigned overrun_time;
+ int num_overrun;
+ unsigned long process_char_map[256/(8*sizeof(unsigned long))];
+ char *read_buf;
+ int read_head;
+ int read_tail;
+ int read_cnt;
+ unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))];
+ int canon_data;
+ unsigned long canon_head;
+ unsigned int canon_column;
+ struct semaphore atomic_read;
+};
+
+/* tty magic number */
+#define TTY_MAGIC 0x5401
+
+/*
+ * These bits are used in the flags field of the tty structure.
+ *
+ * So that interrupts won't be able to mess up the queues,
+ * copy_to_cooked must be atomic with respect to itself, as must
+ * tty->write. Thus, you must use the inline functions set_bit() and
+ * clear_bit() to make things atomic.
+ */
+#define TTY_THROTTLED 0
+#define TTY_IO_ERROR 1
+#define TTY_OTHER_CLOSED 2
+#define TTY_EXCLUSIVE 3
+#define TTY_DEBUG 4
+#define TTY_DO_WRITE_WAKEUP 5
+#define TTY_PUSH 6
+#define TTY_CLOSING 7
+#define TTY_DONT_FLIP 8
+#define TTY_HW_COOK_OUT 14
+#define TTY_HW_COOK_IN 15
+#define TTY_PTY_LOCK 16
+
+#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
+
+extern void tty_write_flush(struct tty_struct *);
+
+extern struct termios tty_std_termios;
+extern struct tty_struct * redirect;
+extern struct tty_ldisc ldiscs[];
+extern int fg_console, last_console, want_console;
+
+extern int kmsg_redirect;
+
+extern unsigned long con_init(unsigned long);
+
+extern int rs_init(void);
+extern int lp_init(void);
+extern int pty_init(void);
+extern int tty_init(void);
+extern int ip2_init(void);
+extern int pcxe_init(void);
+extern int pc_init(void);
+extern int vcs_init(void);
+extern int rp_init(void);
+extern int cy_init(void);
+extern int stl_init(void);
+extern int stli_init(void);
+extern int riscom8_init(void);
+extern int specialix_init(void);
+extern int espserial_init(void);
+extern int macserial_init(void);
+
+extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device,
+ const char *routine);
+extern char *tty_name(struct tty_struct *tty, char *buf);
+extern void tty_wait_until_sent(struct tty_struct * tty, long timeout);
+extern int tty_check_change(struct tty_struct * tty);
+extern void stop_tty(struct tty_struct * tty);
+extern void start_tty(struct tty_struct * tty);
+extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
+extern int tty_register_driver(struct tty_driver *driver);
+extern int tty_unregister_driver(struct tty_driver *driver);
+extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
+ int buflen);
+extern void tty_write_message(struct tty_struct *tty, char *msg);
+
+extern int is_orphaned_pgrp(int pgrp);
+extern int is_ignored(int sig);
+extern int tty_signal(int sig, struct tty_struct *tty);
+extern void tty_hangup(struct tty_struct * tty);
+extern void tty_vhangup(struct tty_struct * tty);
+extern void tty_unhangup(struct file *filp);
+extern int tty_hung_up_p(struct file * filp);
+extern void do_SAK(struct tty_struct *tty);
+extern void disassociate_ctty(int priv);
+extern void tty_flip_buffer_push(struct tty_struct *tty);
+extern int tty_get_baud_rate(struct tty_struct *tty);
+
+/* n_tty.c */
+extern struct tty_ldisc tty_ldisc_N_TTY;
+
+/* tty_ioctl.c */
+extern int n_tty_ioctl(struct tty_struct * tty, struct file * file,
+ unsigned int cmd, unsigned long arg);
+
+/* serial.c */
+
+extern long serial_console_init(long kmem_start, long kmem_end);
+
+/* pcxx.c */
+
+extern int pcxe_open(struct tty_struct *tty, struct file *filp);
+
+/* printk.c */
+
+extern void console_print(const char *);
+
+/* vt.c */
+
+extern int vt_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg);
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/pfinet/linux-src/include/linux/tty_driver.h b/pfinet/linux-src/include/linux/tty_driver.h
new file mode 100644
index 00000000..46ace283
--- /dev/null
+++ b/pfinet/linux-src/include/linux/tty_driver.h
@@ -0,0 +1,227 @@
+#ifndef _LINUX_TTY_DRIVER_H
+#define _LINUX_TTY_DRIVER_H
+
+/*
+ * This structure defines the interface between the low-level tty
+ * driver and the tty routines. The following routines can be
+ * defined; unless noted otherwise, they are optional, and can be
+ * filled in with a null pointer.
+ *
+ * int (*open)(struct tty_struct * tty, struct file * filp);
+ *
+ * This routine is called when a particular tty device is opened.
+ * This routine is mandatory; if this routine is not filled in,
+ * the attempted open will fail with ENODEV.
+ *
+ * void (*close)(struct tty_struct * tty, struct file * filp);
+ *
+ * This routine is called when a particular tty device is closed.
+ *
+ * int (*write)(struct tty_struct * tty, int from_user,
+ * const unsigned char *buf, int count);
+ *
+ * This routine is called by the kernel to write a series of
+ * characters to the tty device. The characters may come from
+ * user space or kernel space. This routine will return the
+ * number of characters actually accepted for writing. This
+ * routine is mandatory.
+ *
+ * void (*put_char)(struct tty_struct *tty, unsigned char ch);
+ *
+ * This routine is called by the kernel to write a single
+ * character to the tty device. If the kernel uses this routine,
+ * it must call the flush_chars() routine (if defined) when it is
+ * done stuffing characters into the driver. If there is no room
+ * in the queue, the character is ignored.
+ *
+ * void (*flush_chars)(struct tty_struct *tty);
+ *
+ * This routine is called by the kernel after it has written a
+ * series of characters to the tty device using put_char().
+ *
+ * int (*write_room)(struct tty_struct *tty);
+ *
+ * This routine returns the numbers of characters the tty driver
+ * will accept for queuing to be written. This number is subject
+ * to change as output buffers get emptied, or if the output flow
+ * control is acted.
+ *
+ * int (*ioctl)(struct tty_struct *tty, struct file * file,
+ * unsigned int cmd, unsigned long arg);
+ *
+ * This routine allows the tty driver to implement
+ * device-specific ioctl's. If the ioctl number passed in cmd
+ * is not recognized by the driver, it should return ENOIOCTLCMD.
+ *
+ * void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ *
+ * This routine allows the tty driver to be notified when
+ * device's termios settings have changed. Note that a
+ * well-designed tty driver should be prepared to accept the case
+ * where old == NULL, and try to do something rational.
+ *
+ * void (*set_ldisc)(struct tty_struct *tty);
+ *
+ * This routine allows the tty driver to be notified when the
+ * device's termios settings have changed.
+ *
+ * void (*throttle)(struct tty_struct * tty);
+ *
+ * This routine notifies the tty driver that input buffers for
+ * the line discipline are close to full, and it should somehow
+ * signal that no more characters should be sent to the tty.
+ *
+ * void (*unthrottle)(struct tty_struct * tty);
+ *
+ * This routine notifies the tty drivers that it should signals
+ * that characters can now be sent to the tty without fear of
+ * overrunning the input buffers of the line disciplines.
+ *
+ * void (*stop)(struct tty_struct *tty);
+ *
+ * This routine notifies the tty driver that it should stop
+ * outputting characters to the tty device.
+ *
+ * void (*start)(struct tty_struct *tty);
+ *
+ * This routine notifies the tty driver that it resume sending
+ * characters to the tty device.
+ *
+ * void (*hangup)(struct tty_struct *tty);
+ *
+ * This routine notifies the tty driver that it should hangup the
+ * tty device.
+ *
+ * void (*break_ctl)(struct tty_stuct *tty, int state);
+ *
+ * This optional routine requests the tty driver to turn on or
+ * off BREAK status on the RS-232 port. If state is -1,
+ * then the BREAK status should be turned on; if state is 0, then
+ * BREAK should be turned off.
+ *
+ * If this routine is implemented, the high-level tty driver will
+ * handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
+ * TIOCCBRK. Otherwise, these ioctls will be passed down to the
+ * driver to handle.
+ *
+ * void (*wait_until_sent)(struct tty_struct *tty, int timeout);
+ *
+ * This routine waits until the device has written out all of the
+ * characters in its transmitter FIFO.
+ *
+ * void (*send_xchar)(struct tty_struct *tty, char ch);
+ *
+ * This routine is used to send a high-priority XON/XOFF
+ * character to the device.
+ */
+
+#include <linux/fs.h>
+
+struct tty_driver {
+ int magic; /* magic number for this structure */
+ const char *driver_name;
+ const char *name;
+ int name_base; /* offset of printed name */
+ short major; /* major device number */
+ short minor_start; /* start of minor device number*/
+ short num; /* number of devices */
+ short type; /* type of tty driver */
+ short subtype; /* subtype of tty driver */
+ struct termios init_termios; /* Initial termios */
+ int flags; /* tty driver flags */
+ int *refcount; /* for loadable tty drivers */
+ struct proc_dir_entry *proc_entry; /* /proc fs entry */
+ struct tty_driver *other; /* only used for the PTY driver */
+
+ /*
+ * Pointer to the tty data structures
+ */
+ struct tty_struct **table;
+ struct termios **termios;
+ struct termios **termios_locked;
+ void *driver_state; /* only used for the PTY driver */
+
+ /*
+ * Interface routines from the upper tty layer to the tty
+ * driver.
+ */
+ int (*open)(struct tty_struct * tty, struct file * filp);
+ void (*close)(struct tty_struct * tty, struct file * filp);
+ int (*write)(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count);
+ void (*put_char)(struct tty_struct *tty, unsigned char ch);
+ void (*flush_chars)(struct tty_struct *tty);
+ int (*write_room)(struct tty_struct *tty);
+ int (*chars_in_buffer)(struct tty_struct *tty);
+ int (*ioctl)(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg);
+ void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ void (*throttle)(struct tty_struct * tty);
+ void (*unthrottle)(struct tty_struct * tty);
+ void (*stop)(struct tty_struct *tty);
+ void (*start)(struct tty_struct *tty);
+ void (*hangup)(struct tty_struct *tty);
+ void (*break_ctl)(struct tty_struct *tty, int state);
+ void (*flush_buffer)(struct tty_struct *tty);
+ void (*set_ldisc)(struct tty_struct *tty);
+ void (*wait_until_sent)(struct tty_struct *tty, int timeout);
+ void (*send_xchar)(struct tty_struct *tty, char ch);
+ int (*read_proc)(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+ int (*write_proc)(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+
+ /*
+ * linked list pointers
+ */
+ struct tty_driver *next;
+ struct tty_driver *prev;
+};
+
+/* tty driver magic number */
+#define TTY_DRIVER_MAGIC 0x5402
+
+/*
+ * tty driver flags
+ *
+ * TTY_DRIVER_RESET_TERMIOS --- requests the tty layer to reset the
+ * termios setting when the last process has closed the device.
+ * Used for PTY's, in particular.
+ *
+ * TTY_DRIVER_REAL_RAW --- if set, indicates that the driver will
+ * guarantee never not to set any special character handling
+ * flags if ((IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR ||
+ * !INPCK)). That is, if there is no reason for the driver to
+ * send notifications of parity and break characters up to the
+ * line driver, it won't do so. This allows the line driver to
+ * optimize for this case if this flag is set. (Note that there
+ * is also a promise, if the above case is true, not to signal
+ * overruns, either.)
+ */
+#define TTY_DRIVER_INSTALLED 0x0001
+#define TTY_DRIVER_RESET_TERMIOS 0x0002
+#define TTY_DRIVER_REAL_RAW 0x0004
+
+/* tty driver types */
+#define TTY_DRIVER_TYPE_SYSTEM 0x0001
+#define TTY_DRIVER_TYPE_CONSOLE 0x0002
+#define TTY_DRIVER_TYPE_SERIAL 0x0003
+#define TTY_DRIVER_TYPE_PTY 0x0004
+#define TTY_DRIVER_TYPE_SCC 0x0005 /* scc driver */
+#define TTY_DRIVER_TYPE_SYSCONS 0x0006
+
+/* system subtypes (magic, used by tty_io.c) */
+#define SYSTEM_TYPE_TTY 0x0001
+#define SYSTEM_TYPE_CONSOLE 0x0002
+#define SYSTEM_TYPE_SYSCONS 0x0003
+#define SYSTEM_TYPE_SYSPTMX 0x0004
+
+/* pty subtypes (magic, used by tty_io.c) */
+#define PTY_TYPE_MASTER 0x0001
+#define PTY_TYPE_SLAVE 0x0002
+
+/* serial subtype definitions */
+#define SERIAL_TYPE_NORMAL 1
+#define SERIAL_TYPE_CALLOUT 2
+
+#endif /* #ifdef _LINUX_TTY_DRIVER_H */
diff --git a/pfinet/linux-src/include/linux/tty_flip.h b/pfinet/linux-src/include/linux/tty_flip.h
new file mode 100644
index 00000000..948e5455
--- /dev/null
+++ b/pfinet/linux-src/include/linux/tty_flip.h
@@ -0,0 +1,35 @@
+#ifndef _LINUX_TTY_FLIP_H
+#define _LINUX_TTY_FLIP_H
+
+#ifdef INCLUDE_INLINE_FUNCS
+#define _INLINE_ extern
+#else
+#define _INLINE_ extern __inline__
+#endif
+
+_INLINE_ void tty_insert_flip_char(struct tty_struct *tty,
+ unsigned char ch, char flag)
+{
+ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+ tty->flip.count++;
+ *tty->flip.flag_buf_ptr++ = flag;
+ *tty->flip.char_buf_ptr++ = ch;
+ }
+}
+
+_INLINE_ void tty_schedule_flip(struct tty_struct *tty)
+{
+ queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+#undef _INLINE_
+
+
+#endif /* _LINUX_TTY_FLIP_H */
+
+
+
+
+
+
+
diff --git a/pfinet/linux-src/include/linux/tty_ldisc.h b/pfinet/linux-src/include/linux/tty_ldisc.h
new file mode 100644
index 00000000..501ea076
--- /dev/null
+++ b/pfinet/linux-src/include/linux/tty_ldisc.h
@@ -0,0 +1,138 @@
+#ifndef _LINUX_TTY_LDISC_H
+#define _LINUX_TTY_LDISC_H
+
+/*
+ * This structure defines the interface between the tty line discpline
+ * implementation and the tty routines. The following routines can be
+ * defined; unless noted otherwise, they are optional, and can be
+ * filled in with a null pointer.
+ *
+ * int (*open)(struct tty_struct *);
+ *
+ * This function is called when the line discpline is associated
+ * with the tty. The line discpline can use this as an
+ * opportunity to initialize any state needed by the ldisc routines.
+ *
+ * void (*close)(struct tty_struct *);
+ *
+ * This function is called when the line discpline is being
+ * shutdown, either because the tty is being closed or because
+ * the tty is being changed to use a new line discpline
+ *
+ * void (*flush_buffer)(struct tty_struct *tty);
+ *
+ * This function instructs the line discipline to clear its
+ * buffers of any input characters it may have queued to be
+ * delivered to the user mode process.
+ *
+ * ssize_t (*chars_in_buffer)(struct tty_struct *tty);
+ *
+ * This function returns the number of input characters the line
+ * iscpline may have queued up to be delivered to the user mode
+ * process.
+ *
+ * ssize_t (*read)(struct tty_struct * tty, struct file * file,
+ * unsigned char * buf, size_t nr);
+ *
+ * This function is called when the user requests to read from
+ * the tty. The line discpline will return whatever characters
+ * it has buffered up for the user. If this function is not
+ * defined, the user will receive an EIO error.
+ *
+ * ssize_t (*write)(struct tty_struct * tty, struct file * file,
+ * const unsigned char * buf, size_t nr);
+ *
+ * This function is called when the user requests to write to the
+ * tty. The line discpline will deliver the characters to the
+ * low-level tty device for transmission, optionally performing
+ * some processing on the characters first. If this function is
+ * not defined, the user will receive an EIO error.
+ *
+ * int (*ioctl)(struct tty_struct * tty, struct file * file,
+ * unsigned int cmd, unsigned long arg);
+ *
+ * This function is called when the user requests an ioctl which
+ * is not handled by the tty layer or the low-level tty driver.
+ * It is intended for ioctls which affect line discpline
+ * operation. Not that the search order for ioctls is (1) tty
+ * layer, (2) tty low-level driver, (3) line discpline. So a
+ * low-level driver can "grab" an ioctl request before the line
+ * discpline has a chance to see it.
+ *
+ * void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ *
+ * This function notifies the line discpline that a change has
+ * been made to the termios stucture.
+ *
+ * int (*poll)(struct tty_struct * tty, struct file * file,
+ * poll_table *wait);
+ *
+ * This function is called when a user attempts to select/poll on a
+ * tty device. It is solely the responsibility of the line
+ * discipline to handle poll requests.
+ *
+ * void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
+ * char *fp, int count);
+ *
+ * This function is called by the low-level tty driver to send
+ * characters received by the hardware to the line discpline for
+ * processing. <cp> is a pointer to the buffer of input
+ * character received by the device. <fp> is a pointer to a
+ * pointer of flag bytes which indicate whether a character was
+ * received with a parity error, etc.
+ *
+ * int (*receive_room)(struct tty_struct *);
+ *
+ * This function is called by the low-level tty driver to
+ * determine how many characters the line discpline can accept.
+ * The low-level driver must not send more characters than was
+ * indicated by receive_room, or the line discpline may drop
+ * those characters.
+ *
+ * void (*write_wakeup)(struct tty_struct *);
+ *
+ * This function is called by the low-level tty driver to signal
+ * that line discpline should try to send more characters to the
+ * low-level driver for transmission. If the line discpline does
+ * not have any more data to send, it can just return.
+ */
+
+#include <linux/fs.h>
+#include <linux/wait.h>
+
+struct tty_ldisc {
+ int magic;
+ char *name;
+ int num;
+ int flags;
+ /*
+ * The following routines are called from above.
+ */
+ int (*open)(struct tty_struct *);
+ void (*close)(struct tty_struct *);
+ void (*flush_buffer)(struct tty_struct *tty);
+ ssize_t (*chars_in_buffer)(struct tty_struct *tty);
+ ssize_t (*read)(struct tty_struct * tty, struct file * file,
+ unsigned char * buf, size_t nr);
+ ssize_t (*write)(struct tty_struct * tty, struct file * file,
+ const unsigned char * buf, size_t nr);
+ int (*ioctl)(struct tty_struct * tty, struct file * file,
+ unsigned int cmd, unsigned long arg);
+ void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ unsigned int (*poll)(struct tty_struct *, struct file *,
+ struct poll_table_struct *);
+
+ /*
+ * The following routines are called from below.
+ */
+ void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
+ char *fp, int count);
+ int (*receive_room)(struct tty_struct *);
+ void (*write_wakeup)(struct tty_struct *);
+};
+
+#define TTY_LDISC_MAGIC 0x5403
+
+#define LDISC_FLAG_DEFINED 0x00000001
+
+#endif /* _LINUX_TTY_LDISC_H */
diff --git a/pfinet/linux-src/include/linux/types.h b/pfinet/linux-src/include/linux/types.h
new file mode 100644
index 00000000..a53a4ccc
--- /dev/null
+++ b/pfinet/linux-src/include/linux/types.h
@@ -0,0 +1,108 @@
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#include <linux/posix_types.h>
+#include <asm/types.h>
+
+#ifndef __KERNEL_STRICT_NAMES
+
+typedef __kernel_fd_set fd_set;
+typedef __kernel_dev_t dev_t;
+typedef __kernel_ino_t ino_t;
+typedef __kernel_mode_t mode_t;
+typedef __kernel_nlink_t nlink_t;
+typedef __kernel_off_t off_t;
+typedef __kernel_pid_t pid_t;
+typedef __kernel_uid_t uid_t;
+typedef __kernel_gid_t gid_t;
+typedef __kernel_daddr_t daddr_t;
+typedef __kernel_key_t key_t;
+typedef __kernel_suseconds_t suseconds_t;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __kernel_loff_t loff_t;
+#endif
+
+/*
+ * The following typedefs are also protected by individual ifdefs for
+ * historical reasons:
+ */
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef __kernel_size_t size_t;
+#endif
+
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef __kernel_ssize_t ssize_t;
+#endif
+
+#ifndef _PTRDIFF_T
+#define _PTRDIFF_T
+typedef __kernel_ptrdiff_t ptrdiff_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef __kernel_time_t time_t;
+#endif
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef __kernel_clock_t clock_t;
+#endif
+
+#ifndef _CADDR_T
+#define _CADDR_T
+typedef __kernel_caddr_t caddr_t;
+#endif
+
+/* bsd */
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+
+/* sysv */
+typedef unsigned char unchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+
+typedef __u8 u_int8_t;
+typedef __s8 int8_t;
+typedef __u16 u_int16_t;
+typedef __s16 int16_t;
+typedef __u32 u_int32_t;
+typedef __s32 int32_t;
+
+#endif /* !(__BIT_TYPES_DEFINED__) */
+
+typedef __u8 uint8_t;
+typedef __u16 uint16_t;
+typedef __u32 uint32_t;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __u64 uint64_t;
+typedef __u64 u_int64_t;
+typedef __s64 int64_t;
+#endif
+
+#endif /* __KERNEL_STRICT_NAMES */
+
+/*
+ * Below are truly Linux-specific types that should never collide with
+ * any application/library that wants linux/types.h.
+ */
+
+struct ustat {
+ __kernel_daddr_t f_tfree;
+ __kernel_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+#endif /* _LINUX_TYPES_H */
diff --git a/pfinet/linux-src/include/linux/udp.h b/pfinet/linux-src/include/linux/udp.h
new file mode 100644
index 00000000..ab75a1e8
--- /dev/null
+++ b/pfinet/linux-src/include/linux/udp.h
@@ -0,0 +1,29 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the UDP protocol.
+ *
+ * Version: @(#)udp.h 1.0.2 04/28/93
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_UDP_H
+#define _LINUX_UDP_H
+
+
+struct udphdr {
+ __u16 source;
+ __u16 dest;
+ __u16 len;
+ __u16 check;
+};
+
+
+#endif /* _LINUX_UDP_H */
diff --git a/pfinet/linux-src/include/linux/ufs_fs.h b/pfinet/linux-src/include/linux/ufs_fs.h
new file mode 100644
index 00000000..38604163
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ufs_fs.h
@@ -0,0 +1,571 @@
+/*
+ * linux/include/linux/ufs_fs.h
+ *
+ * Copyright (C) 1996
+ * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
+ * Laboratory for Computer Science Research Computing Facility
+ * Rutgers, The State University of New Jersey
+ *
+ * Clean swab support by Fare <fare@tunes.org>
+ * just hope no one is using NNUUXXI on __?64 structure elements
+ * 64-bit clean thanks to Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ *
+ * 4.4BSD (FreeBSD) support added on February 1st 1998 by
+ * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
+ * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
+ *
+ * NeXTstep support added on February 5th 1998 by
+ * Niels Kristian Bech Jensen <nkbj@image.dk>.
+ *
+ * Write support by Daniel Pirkl <daniel.pirkl@email.cz>
+ */
+
+#ifndef __LINUX_UFS_FS_H
+#define __LINUX_UFS_FS_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/stat.h>
+
+#define UFS_BBLOCK 0
+#define UFS_BBSIZE 8192
+#define UFS_SBLOCK 8192
+#define UFS_SBSIZE 8192
+
+#define UFS_SECTOR_SIZE 512
+#define UFS_SECTOR_BITS 9
+#define UFS_MAGIC 0x00011954
+#define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */
+
+#define UFS_BSIZE 8192
+#define UFS_MINBSIZE 4096
+#define UFS_FSIZE 1024
+#define UFS_MAXFRAG (UFS_BSIZE / UFS_FSIZE)
+
+#define UFS_NDADDR 12
+#define UFS_NINDIR 3
+
+#define UFS_IND_BLOCK (UFS_NDADDR + 0)
+#define UFS_DIND_BLOCK (UFS_NDADDR + 1)
+#define UFS_TIND_BLOCK (UFS_NDADDR + 2)
+
+#define UFS_NDIR_FRAGMENT (UFS_NDADDR << uspi->s_fpbshift)
+#define UFS_IND_FRAGMENT (UFS_IND_BLOCK << uspi->s_fpbshift)
+#define UFS_DIND_FRAGMENT (UFS_DIND_BLOCK << uspi->s_fpbshift)
+#define UFS_TIND_FRAGMENT (UFS_TIND_BLOCK << uspi->s_fpbshift)
+
+#define UFS_ROOTINO 2
+#define UFS_FIRST_INO (UFS_ROOTINO + 1)
+
+#define UFS_USEEFT ((__u16)65535)
+
+#define UFS_FSOK 0x7c269d38
+#define UFS_FSACTIVE ((char)0x00)
+#define UFS_FSCLEAN ((char)0x01)
+#define UFS_FSSTABLE ((char)0x02)
+#define UFS_FSOSF1 ((char)0x03) /* is this correct for DEC OSF/1? */
+#define UFS_FSBAD ((char)0xff)
+
+/* From here to next blank line, s_flags for ufs_sb_info */
+/* endianness */
+#define UFS_BYTESEX 0x00000001 /* mask; leave room to 0xF */
+#if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN)
+/* these are for sane architectures */
+#define UFS_NATIVE_ENDIAN 0x00000000
+#define UFS_SWABBED_ENDIAN 0x00000001
+#else
+/* these are for pervert architectures */
+#define UFS_LITTLE_ENDIAN 0x00000000
+#define UFS_BIG_ENDIAN 0x00000001
+#endif
+/* directory entry encoding */
+#define UFS_DE_MASK 0x00000010 /* mask for the following */
+#define UFS_DE_OLD 0x00000000
+#define UFS_DE_44BSD 0x00000010
+/* uid encoding */
+#define UFS_UID_MASK 0x00000060 /* mask for the following */
+#define UFS_UID_OLD 0x00000000
+#define UFS_UID_44BSD 0x00000020
+#define UFS_UID_EFT 0x00000040
+/* superblock state encoding */
+#define UFS_ST_MASK 0x00000700 /* mask for the following */
+#define UFS_ST_OLD 0x00000000
+#define UFS_ST_44BSD 0x00000100
+#define UFS_ST_SUN 0x00000200
+#define UFS_ST_SUNx86 0x00000400
+/*cylinder group encoding */
+#define UFS_CG_MASK 0x00003000 /* mask for the following */
+#define UFS_CG_OLD 0x00000000
+#define UFS_CG_44BSD 0x00002000
+#define UFS_CG_SUN 0x00001000
+
+/* fs_inodefmt options */
+#define UFS_42INODEFMT -1
+#define UFS_44INODEFMT 2
+
+/* mount options */
+#define UFS_MOUNT_ONERROR 0x0000000F
+#define UFS_MOUNT_ONERROR_PANIC 0x00000001
+#define UFS_MOUNT_ONERROR_LOCK 0x00000002
+#define UFS_MOUNT_ONERROR_UMOUNT 0x00000004
+#define UFS_MOUNT_ONERROR_REPAIR 0x00000008
+
+#define UFS_MOUNT_UFSTYPE 0x000007F0
+#define UFS_MOUNT_UFSTYPE_OLD 0x00000010
+#define UFS_MOUNT_UFSTYPE_44BSD 0x00000020
+#define UFS_MOUNT_UFSTYPE_SUN 0x00000040
+#define UFS_MOUNT_UFSTYPE_NEXTSTEP 0x00000080
+#define UFS_MOUNT_UFSTYPE_NEXTSTEP_CD 0x00000100
+#define UFS_MOUNT_UFSTYPE_OPENSTEP 0x00000200
+#define UFS_MOUNT_UFSTYPE_SUNx86 0x00000400
+
+#define ufs_clear_opt(o,opt) o &= ~UFS_MOUNT_##opt
+#define ufs_set_opt(o,opt) o |= UFS_MOUNT_##opt
+#define ufs_test_opt(o,opt) ((o) & UFS_MOUNT_##opt)
+
+/*
+ * MINFREE gives the minimum acceptable percentage of file system
+ * blocks which may be free. If the freelist drops below this level
+ * only the superuser may continue to allocate blocks. This may
+ * be set to 0 if no reserve of free blocks is deemed necessary,
+ * however throughput drops by fifty percent if the file system
+ * is run at between 95% and 100% full; thus the minimum default
+ * value of fs_minfree is 5%. However, to get good clustering
+ * performance, 10% is a better choice. hence we use 10% as our
+ * default value. With 10% free space, fragmentation is not a
+ * problem, so we choose to optimize for time.
+ */
+#define UFS_MINFREE 5
+#define UFS_DEFAULTOPT UFS_OPTTIME
+
+/*
+ * Turn file system block numbers into disk block addresses.
+ * This maps file system blocks to device size blocks.
+ */
+#define ufs_fsbtodb(uspi, b) ((b) << (uspi)->s_fsbtodb)
+#define ufs_dbtofsb(uspi, b) ((b) >> (uspi)->s_fsbtodb)
+
+/*
+ * Cylinder group macros to locate things in cylinder groups.
+ * They calc file system addresses of cylinder group data structures.
+ */
+#define ufs_cgbase(c) (uspi->s_fpg * (c))
+#define ufs_cgstart(c) (ufs_cgbase(c) + uspi->s_cgoffset * ((c) & ~uspi->s_cgmask))
+#define ufs_cgsblock(c) (ufs_cgstart(c) + uspi->s_sblkno) /* super blk */
+#define ufs_cgcmin(c) (ufs_cgstart(c) + uspi->s_cblkno) /* cg block */
+#define ufs_cgimin(c) (ufs_cgstart(c) + uspi->s_iblkno) /* inode blk */
+#define ufs_cgdmin(c) (ufs_cgstart(c) + uspi->s_dblkno) /* 1st data */
+
+/*
+ * Macros for handling inode numbers:
+ * inode number to file system block offset.
+ * inode number to cylinder group number.
+ * inode number to file system block address.
+ */
+#define ufs_inotocg(x) ((x) / uspi->s_ipg)
+#define ufs_inotocgoff(x) ((x) % uspi->s_ipg)
+#define ufs_inotofsba(x) (ufs_cgimin(ufs_inotocg(x)) + ufs_inotocgoff(x) / uspi->s_inopf)
+#define ufs_inotofsbo(x) ((x) % uspi->s_inopf)
+
+/*
+ * Give cylinder group number for a file system block.
+ * Give cylinder group block number for a file system block.
+ */
+#define ufs_dtog(d) ((d) / uspi->s_fpg)
+#define ufs_dtogd(d) ((d) % uspi->s_fpg)
+
+/*
+ * Compute the cylinder and rotational position of a cyl block addr.
+ */
+#define ufs_cbtocylno(bno) \
+ ((bno) * uspi->s_nspf / uspi->s_spc)
+#define ufs_cbtorpos(bno) \
+ ((((bno) * uspi->s_nspf % uspi->s_spc / uspi->s_nsect \
+ * uspi->s_trackskew + (bno) * uspi->s_nspf % uspi->s_spc \
+ % uspi->s_nsect * uspi->s_interleave) % uspi->s_nsect \
+ * uspi->s_nrpos) / uspi->s_npsect)
+
+/*
+ * The following macros optimize certain frequently calculated
+ * quantities by using shifts and masks in place of divisions
+ * modulos and multiplications.
+ */
+#define ufs_blkoff(loc) ((loc) & uspi->s_qbmask)
+#define ufs_fragoff(loc) ((loc) & uspi->s_qfmask)
+#define ufs_lblktosize(blk) ((blk) << uspi->s_bshift)
+#define ufs_lblkno(loc) ((loc) >> uspi->s_bshift)
+#define ufs_numfrags(loc) ((loc) >> uspi->s_fshift)
+#define ufs_blkroundup(size) (((size) + uspi->s_qbmask) & uspi->s_bmask)
+#define ufs_fragroundup(size) (((size) + uspi->s_qfmask) & uspi->s_fmask)
+#define ufs_fragstoblks(frags) ((frags) >> uspi->s_fpbshift)
+#define ufs_blkstofrags(blks) ((blks) << uspi->s_fpbshift)
+#define ufs_fragnum(fsb) ((fsb) & uspi->s_fpbmask)
+#define ufs_blknum(fsb) ((fsb) & ~uspi->s_fpbmask)
+
+#define UFS_MAXNAMLEN 255
+#define UFS_MAXMNTLEN 512
+#define UFS_MAXCSBUFS 31
+#define UFS_LINK_MAX 32000
+
+/*
+ * UFS_DIR_PAD defines the directory entries boundaries
+ * (must be a multiple of 4)
+ */
+#define UFS_DIR_PAD 4
+#define UFS_DIR_ROUND (UFS_DIR_PAD - 1)
+#define UFS_DIR_REC_LEN(name_len) (((name_len) + 1 + 8 + UFS_DIR_ROUND) & ~UFS_DIR_ROUND)
+
+struct ufs_timeval {
+ __s32 tv_sec;
+ __s32 tv_usec;
+};
+
+/*
+ * File types
+ */
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+struct ufs_dir_entry {
+ __u32 d_ino; /* inode number of this entry */
+ __u16 d_reclen; /* length of this entry */
+ union {
+ __u16 d_namlen; /* actual length of d_name */
+ struct {
+ __u8 d_type; /* file type */
+ __u8 d_namlen; /* length of string in d_name */
+ } d_44;
+ } d_u;
+ __u8 d_name[UFS_MAXNAMLEN + 1]; /* file name */
+};
+
+struct ufs_csum {
+ __u32 cs_ndir; /* number of directories */
+ __u32 cs_nbfree; /* number of free blocks */
+ __u32 cs_nifree; /* number of free inodes */
+ __u32 cs_nffree; /* number of free frags */
+};
+
+/*
+ * This is the actual superblock, as it is laid out on the disk.
+ */
+struct ufs_super_block {
+ __u32 fs_link; /* UNUSED */
+ __u32 fs_rlink; /* UNUSED */
+ __u32 fs_sblkno; /* addr of super-block in filesys */
+ __u32 fs_cblkno; /* offset of cyl-block in filesys */
+ __u32 fs_iblkno; /* offset of inode-blocks in filesys */
+ __u32 fs_dblkno; /* offset of first data after cg */
+ __u32 fs_cgoffset; /* cylinder group offset in cylinder */
+ __u32 fs_cgmask; /* used to calc mod fs_ntrak */
+ __u32 fs_time; /* last time written -- time_t */
+ __u32 fs_size; /* number of blocks in fs */
+ __u32 fs_dsize; /* number of data blocks in fs */
+ __u32 fs_ncg; /* number of cylinder groups */
+ __u32 fs_bsize; /* size of basic blocks in fs */
+ __u32 fs_fsize; /* size of frag blocks in fs */
+ __u32 fs_frag; /* number of frags in a block in fs */
+/* these are configuration parameters */
+ __u32 fs_minfree; /* minimum percentage of free blocks */
+ __u32 fs_rotdelay; /* num of ms for optimal next block */
+ __u32 fs_rps; /* disk revolutions per second */
+/* these fields can be computed from the others */
+ __u32 fs_bmask; /* ``blkoff'' calc of blk offsets */
+ __u32 fs_fmask; /* ``fragoff'' calc of frag offsets */
+ __u32 fs_bshift; /* ``lblkno'' calc of logical blkno */
+ __u32 fs_fshift; /* ``numfrags'' calc number of frags */
+/* these are configuration parameters */
+ __u32 fs_maxcontig; /* max number of contiguous blks */
+ __u32 fs_maxbpg; /* max number of blks per cyl group */
+/* these fields can be computed from the others */
+ __u32 fs_fragshift; /* block to frag shift */
+ __u32 fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+ __u32 fs_sbsize; /* actual size of super block */
+ __u32 fs_csmask; /* csum block offset */
+ __u32 fs_csshift; /* csum block number */
+ __u32 fs_nindir; /* value of NINDIR */
+ __u32 fs_inopb; /* value of INOPB */
+ __u32 fs_nspf; /* value of NSPF */
+/* yet another configuration parameter */
+ __u32 fs_optim; /* optimization preference, see below */
+/* these fields are derived from the hardware */
+ union {
+ struct {
+ __u32 fs_npsect; /* # sectors/track including spares */
+ } fs_sun;
+ struct {
+ __s32 fs_state; /* file system state time stamp */
+ } fs_sunx86;
+ } fs_u1;
+ __u32 fs_interleave; /* hardware sector interleave */
+ __u32 fs_trackskew; /* sector 0 skew, per track */
+/* a unique id for this filesystem (currently unused and unmaintained) */
+/* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */
+/* Neither of those fields is used in the Tahoe code right now but */
+/* there could be problems if they are. */
+ __u32 fs_id[2]; /* file system id */
+/* sizes determined by number of cylinder groups and their sizes */
+ __u32 fs_csaddr; /* blk addr of cyl grp summary area */
+ __u32 fs_cssize; /* size of cyl grp summary area */
+ __u32 fs_cgsize; /* cylinder group size */
+/* these fields are derived from the hardware */
+ __u32 fs_ntrak; /* tracks per cylinder */
+ __u32 fs_nsect; /* sectors per track */
+ __u32 fs_spc; /* sectors per cylinder */
+/* this comes from the disk driver partitioning */
+ __u32 fs_ncyl; /* cylinders in file system */
+/* these fields can be computed from the others */
+ __u32 fs_cpg; /* cylinders per group */
+ __u32 fs_ipg; /* inodes per group */
+ __u32 fs_fpg; /* blocks per group * fs_frag */
+/* this data must be re-computed after crashes */
+ struct ufs_csum fs_cstotal; /* cylinder summary information */
+/* these fields are cleared at mount time */
+ __s8 fs_fmod; /* super block modified flag */
+ __s8 fs_clean; /* file system is clean flag */
+ __s8 fs_ronly; /* mounted read-only flag */
+ __s8 fs_flags; /* currently unused flag */
+ __s8 fs_fsmnt[UFS_MAXMNTLEN]; /* name mounted on */
+/* these fields retain the current block allocation info */
+ __u32 fs_cgrotor; /* last cg searched */
+ __u32 fs_csp[UFS_MAXCSBUFS]; /* list of fs_cs info buffers */
+ __u32 fs_maxcluster;
+ __u32 fs_cpc; /* cyl per cycle in postbl */
+ __u16 fs_opostbl[16][8]; /* old rotation block list head */
+ union {
+ struct {
+ __s32 fs_sparecon[53];/* reserved for future constants */
+ __s32 fs_reclaim;
+ __s32 fs_sparecon2[1];
+ __s32 fs_state; /* file system state time stamp */
+ __u32 fs_qbmask[2]; /* ~usb_bmask */
+ __u32 fs_qfmask[2]; /* ~usb_fmask */
+ } fs_sun;
+ struct {
+ __s32 fs_sparecon[53];/* reserved for future constants */
+ __s32 fs_reclaim;
+ __s32 fs_sparecon2[1];
+ __u32 fs_npsect; /* # sectors/track including spares */
+ __u32 fs_qbmask[2]; /* ~usb_bmask */
+ __u32 fs_qfmask[2]; /* ~usb_fmask */
+ } fs_sunx86;
+ struct {
+ __s32 fs_sparecon[50];/* reserved for future constants */
+ __s32 fs_contigsumsize;/* size of cluster summary array */
+ __s32 fs_maxsymlinklen;/* max length of an internal symlink */
+ __s32 fs_inodefmt; /* format of on-disk inodes */
+ __u32 fs_maxfilesize[2]; /* max representable file size */
+ __u32 fs_qbmask[2]; /* ~usb_bmask */
+ __u32 fs_qfmask[2]; /* ~usb_fmask */
+ __s32 fs_state; /* file system state time stamp */
+ } fs_44;
+ } fs_u2;
+ __s32 fs_postblformat; /* format of positional layout tables */
+ __s32 fs_nrpos; /* number of rotational positions */
+ __s32 fs_postbloff; /* (__s16) rotation block list head */
+ __s32 fs_rotbloff; /* (__u8) blocks for each rotation */
+ __s32 fs_magic; /* magic number */
+ __u8 fs_space[1]; /* list of blocks for each rotation */
+};
+
+/*
+ * Preference for optimization.
+ */
+#define UFS_OPTTIME 0 /* minimize allocation time */
+#define UFS_OPTSPACE 1 /* minimize disk fragmentation */
+
+/*
+ * Rotational layout table format types
+ */
+#define UFS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
+#define UFS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */
+
+/*
+ * Convert cylinder group to base address of its global summary info.
+ */
+#define fs_cs(indx) \
+ u.ufs_sb.s_csp[(indx) >> uspi->s_csshift][(indx) & ~uspi->s_csmask]
+
+/*
+ * Cylinder group block for a file system.
+ *
+ * Writable fields in the cylinder group are protected by the associated
+ * super block lock fs->fs_lock.
+ */
+#define CG_MAGIC 0x090255
+#define ufs_cg_chkmagic(ucg) (SWAB32((ucg)->cg_magic) == CG_MAGIC)
+
+/*
+ * size of this structure is 172 B
+ */
+struct ufs_cylinder_group {
+ __u32 cg_link; /* linked list of cyl groups */
+ __u32 cg_magic; /* magic number */
+ __u32 cg_time; /* time last written */
+ __u32 cg_cgx; /* we are the cgx'th cylinder group */
+ __u16 cg_ncyl; /* number of cyl's this cg */
+ __u16 cg_niblk; /* number of inode blocks this cg */
+ __u32 cg_ndblk; /* number of data blocks this cg */
+ struct ufs_csum cg_cs; /* cylinder summary information */
+ __u32 cg_rotor; /* position of last used block */
+ __u32 cg_frotor; /* position of last used frag */
+ __u32 cg_irotor; /* position of last used inode */
+ __u32 cg_frsum[UFS_MAXFRAG]; /* counts of available frags */
+ __u32 cg_btotoff; /* (__u32) block totals per cylinder */
+ __u32 cg_boff; /* (short) free block positions */
+ __u32 cg_iusedoff; /* (char) used inode map */
+ __u32 cg_freeoff; /* (u_char) free block map */
+ __u32 cg_nextfreeoff; /* (u_char) next available space */
+ union {
+ struct {
+ __u32 cg_clustersumoff; /* (u_int32) counts of avail clusters */
+ __u32 cg_clusteroff; /* (u_int8) free cluster map */
+ __u32 cg_nclusterblks; /* number of clusters this cg */
+ __u32 cg_sparecon[13]; /* reserved for future use */
+ } cg_44;
+ __u32 cg_sparecon[16]; /* reserved for future use */
+ } cg_u;
+ __u8 cg_space[1]; /* space for cylinder group maps */
+/* actually longer */
+};
+
+/*
+ * structure of an on-disk inode
+ */
+struct ufs_inode {
+ __u16 ui_mode; /* 0x0 */
+ __u16 ui_nlink; /* 0x2 */
+ union {
+ struct {
+ __u16 ui_suid; /* 0x4 */
+ __u16 ui_sgid; /* 0x6 */
+ } oldids;
+ __u32 ui_inumber; /* 0x4 lsf: inode number */
+ __u32 ui_author; /* 0x4 GNU HURD: author */
+ } ui_u1;
+ __u64 ui_size; /* 0x8 */
+ struct ufs_timeval ui_atime; /* 0x10 access */
+ struct ufs_timeval ui_mtime; /* 0x18 modification */
+ struct ufs_timeval ui_ctime; /* 0x20 creation */
+ union {
+ struct {
+ __u32 ui_db[UFS_NDADDR];/* 0x28 data blocks */
+ __u32 ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */
+ } ui_addr;
+ __u8 ui_symlink[4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
+ } ui_u2;
+ __u32 ui_flags; /* 0x64 immutable, append-only... */
+ __u32 ui_blocks; /* 0x68 blocks in use */
+ __u32 ui_gen; /* 0x6c like ext2 i_version, for NFS support */
+ union {
+ struct {
+ __u32 ui_shadow; /* 0x70 shadow inode with security data */
+ __u32 ui_uid; /* 0x74 long EFT version of uid */
+ __u32 ui_gid; /* 0x78 long EFT version of gid */
+ __u32 ui_oeftflag; /* 0x7c reserved */
+ } ui_sun;
+ struct {
+ __u32 ui_uid; /* 0x70 File owner */
+ __u32 ui_gid; /* 0x74 File group */
+ __s32 ui_spare[2]; /* 0x78 reserved */
+ } ui_44;
+ struct {
+ __u32 ui_uid; /* 0x70 */
+ __u32 ui_gid; /* 0x74 */
+ __u16 ui_modeh; /* 0x78 mode high bits */
+ __u16 ui_spare; /* 0x7A unused */
+ __u32 ui_trans; /* 0x7c filesystem translator */
+ } ui_hurd;
+ } ui_u3;
+};
+
+/* FreeBSD has these in sys/stat.h */
+/* ui_flags that can be set by a file owner */
+#define UFS_UF_SETTABLE 0x0000ffff
+#define UFS_UF_NODUMP 0x00000001 /* do not dump */
+#define UFS_UF_IMMUTABLE 0x00000002 /* immutable (can't "change") */
+#define UFS_UF_APPEND 0x00000004 /* append-only */
+#define UFS_UF_OPAQUE 0x00000008 /* directory is opaque (unionfs) */
+#define UFS_UF_NOUNLINK 0x00000010 /* can't be removed or renamed */
+/* ui_flags that only root can set */
+#define UFS_SF_SETTABLE 0xffff0000
+#define UFS_SF_ARCHIVED 0x00010000 /* archived */
+#define UFS_SF_IMMUTABLE 0x00020000 /* immutable (can't "change") */
+#define UFS_SF_APPEND 0x00040000 /* append-only */
+#define UFS_SF_NOUNLINK 0x00100000 /* can't be removed or renamed */
+
+#ifdef __KERNEL__
+
+/* acl.c */
+extern int ufs_permission (struct inode *, int);
+
+/* balloc.c */
+extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
+extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
+extern unsigned ufs_new_fragments (struct inode *, u32 *, unsigned, unsigned, unsigned, int *);
+
+/* cylinder.c */
+extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
+extern void ufs_put_cylinder (struct super_block *, unsigned);
+
+/* dir.c */
+extern struct inode_operations ufs_dir_inode_operations;
+extern struct file_operations ufs_dir_operations;
+extern int ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *, struct buffer_head *, unsigned long);
+
+/* file.c */
+extern struct inode_operations ufs_file_inode_operations;
+extern struct file_operations ufs_file_operations;
+
+/* ialloc.c */
+extern void ufs_free_inode (struct inode *inode);
+extern struct inode * ufs_new_inode (const struct inode *, int, int *);
+
+/* inode.c */
+extern int ufs_bmap (struct inode *, int);
+extern void ufs_read_inode (struct inode *);
+extern void ufs_put_inode (struct inode *);
+extern void ufs_write_inode (struct inode *);
+extern int ufs_sync_inode (struct inode *);
+extern void ufs_write_inode (struct inode *);
+extern void ufs_delete_inode (struct inode *);
+extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
+extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
+
+/* namei.c */
+extern struct dentry *ufs_lookup (struct inode *, struct dentry *);
+extern int ufs_mkdir(struct inode *, struct dentry *, int);
+extern int ufs_rmdir (struct inode *, struct dentry *);
+extern int ufs_unlink (struct inode *, struct dentry *);
+extern int ufs_create (struct inode *, struct dentry *, int);
+extern int ufs_rename (struct inode *, struct dentry *, struct inode *, struct dentry *);
+extern int ufs_mknod (struct inode *, struct dentry *, int, int);
+extern int ufs_symlink (struct inode *, struct dentry *, const char *);
+extern int ufs_link (struct dentry *, struct inode *, struct dentry *);
+
+/* super.c */
+extern struct super_operations ufs_super_ops;
+extern struct file_system_type ufs_fs_type;
+extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
+extern int init_ufs_fs(void);
+extern void ufs_write_super (struct super_block *);
+
+/* symlink.c */
+extern struct inode_operations ufs_symlink_inode_operations;
+
+/* truncate.c */
+extern void ufs_truncate (struct inode *);
+
+#endif /* __KERNEL__ */
+
+#endif /* __LINUX_UFS_FS_H */
diff --git a/pfinet/linux-src/include/linux/ufs_fs_i.h b/pfinet/linux-src/include/linux/ufs_fs_i.h
new file mode 100644
index 00000000..df4c7575
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ufs_fs_i.h
@@ -0,0 +1,32 @@
+/*
+ * linux/include/linux/ufs_fs_i.h
+ *
+ * Copyright (C) 1996
+ * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
+ * Laboratory for Computer Science Research Computing Facility
+ * Rutgers, The State University of New Jersey
+ *
+ * NeXTstep support added on February 5th 1998 by
+ * Niels Kristian Bech Jensen <nkbj@image.dk>.
+ */
+
+#ifndef _LINUX_UFS_FS_I_H
+#define _LINUX_UFS_FS_I_H
+
+struct ufs_inode_info {
+ union {
+ __u32 i_data[15];
+ __u8 i_symlink[4*15];
+ } i_u1;
+ __u64 i_size;
+ __u32 i_flags;
+ __u32 i_gen;
+ __u32 i_shadow;
+ __u32 i_uid;
+ __u32 i_gid;
+ __u32 i_oeftflag;
+ __u16 i_osync;
+ __u32 i_lastfrag;
+};
+
+#endif /* _LINUX_UFS_FS_I_H */
diff --git a/pfinet/linux-src/include/linux/ufs_fs_sb.h b/pfinet/linux-src/include/linux/ufs_fs_sb.h
new file mode 100644
index 00000000..2fc49e99
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ufs_fs_sb.h
@@ -0,0 +1,245 @@
+/*
+ * linux/include/linux/ufs_fs_sb.h
+ *
+ * Copyright (C) 1996
+ * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
+ * Laboratory for Computer Science Research Computing Facility
+ * Rutgers, The State University of New Jersey
+ *
+ * $Id: ufs_fs_sb.h,v 1.8 1998/05/06 12:04:40 jj Exp $
+ *
+ * Write support by Daniel Pirkl <daniel.pirkl@email.cz>
+ */
+
+#ifndef __LINUX_UFS_FS_SB_H
+#define __LINUX_UFS_FS_SB_H
+
+#include <linux/ufs_fs.h>
+
+/*
+ * This structure is used for reading disk structures larger
+ * than the size of fragment.
+ */
+struct ufs_buffer_head {
+ unsigned fragment; /* first fragment */
+ unsigned count; /* number of fragments */
+ struct buffer_head * bh[UFS_MAXFRAG]; /* buffers */
+};
+
+struct ufs_cg_private_info {
+ struct ufs_cylinder_group ucg;
+ __u32 c_cgx; /* number of cylidner group */
+ __u16 c_ncyl; /* number of cyl's this cg */
+ __u16 c_niblk; /* number of inode blocks this cg */
+ __u32 c_ndblk; /* number of data blocks this cg */
+ __u32 c_rotor; /* position of last used block */
+ __u32 c_frotor; /* position of last used frag */
+ __u32 c_irotor; /* position of last used inode */
+ __u32 c_btotoff; /* (__u32) block totals per cylinder */
+ __u32 c_boff; /* (short) free block positions */
+ __u32 c_iusedoff; /* (char) used inode map */
+ __u32 c_freeoff; /* (u_char) free block map */
+ __u32 c_nextfreeoff; /* (u_char) next available space */
+ __u32 c_clustersumoff;/* (u_int32) counts of avail clusters */
+ __u32 c_clusteroff; /* (u_int8) free cluster map */
+ __u32 c_nclusterblks; /* number of clusters this cg */
+};
+
+struct ufs_sb_private_info {
+ struct ufs_buffer_head s_ubh; /* buffer containing super block */
+ __u32 s_sblkno; /* offset of super-blocks in filesys */
+ __u32 s_cblkno; /* offset of cg-block in filesys */
+ __u32 s_iblkno; /* offset of inode-blocks in filesys */
+ __u32 s_dblkno; /* offset of first data after cg */
+ __u32 s_cgoffset; /* cylinder group offset in cylinder */
+ __u32 s_cgmask; /* used to calc mod fs_ntrak */
+ __u32 s_size; /* number of blocks (fragments) in fs */
+ __u32 s_dsize; /* number of data blocks in fs */
+ __u32 s_ncg; /* number of cylinder groups */
+ __u32 s_bsize; /* size of basic blocks */
+ __u32 s_fsize; /* size of fragments */
+ __u32 s_fpb; /* fragments per block */
+ __u32 s_minfree; /* minimum percentage of free blocks */
+ __u32 s_bmask; /* `blkoff'' calc of blk offsets */
+ __u32 s_fmask; /* s_fsize mask */
+ __u32 s_bshift; /* `lblkno'' calc of logical blkno */
+ __u32 s_fshift; /* s_fsize shift */
+ __u32 s_fpbshift; /* fragments per block shift */
+ __u32 s_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+ __u32 s_sbsize; /* actual size of super block */
+ __u32 s_csmask; /* csum block offset */
+ __u32 s_csshift; /* csum block number */
+ __u32 s_nindir; /* value of NINDIR */
+ __u32 s_inopb; /* value of INOPB */
+ __u32 s_nspf; /* value of NSPF */
+ __u32 s_npsect; /* # sectors/track including spares */
+ __u32 s_interleave; /* hardware sector interleave */
+ __u32 s_trackskew; /* sector 0 skew, per track */
+ __u32 s_csaddr; /* blk addr of cyl grp summary area */
+ __u32 s_cssize; /* size of cyl grp summary area */
+ __u32 s_cgsize; /* cylinder group size */
+ __u32 s_ntrak; /* tracks per cylinder */
+ __u32 s_nsect; /* sectors per track */
+ __u32 s_spc; /* sectors per cylinder */
+ __u32 s_ipg; /* inodes per group */
+ __u32 s_fpg; /* fragments per group */
+ __u32 s_cpc; /* cyl per cycle in postbl */
+ __s32 s_contigsumsize;/* size of cluster summary array, 44bsd */
+ __s64 s_qbmask; /* ~usb_bmask */
+ __s64 s_qfmask; /* ~usb_fmask */
+ __s32 s_postblformat; /* format of positional layout tables */
+ __s32 s_nrpos; /* number of rotational positions */
+ __s32 s_postbloff; /* (__s16) rotation block list head */
+ __s32 s_rotbloff; /* (__u8) blocks for each rotation */
+
+ __u32 s_fpbmask; /* fragments per block mask */
+ __u32 s_apb; /* address per block */
+ __u32 s_2apb; /* address per block^2 */
+ __u32 s_3apb; /* address per block^3 */
+ __u32 s_apbmask; /* address per block mask */
+ __u32 s_apbshift; /* address per block shift */
+ __u32 s_2apbshift; /* address per block shift * 2 */
+ __u32 s_3apbshift; /* address per block shift * 3 */
+ __u32 s_nspfshift; /* number of sector per fragment shift */
+ __u32 s_nspb; /* number of sector per block */
+ __u32 s_inopf; /* inodes per fragment */
+ __u32 s_sbbase; /* offset of NeXTstep superblock */
+ __u32 s_bpf; /* bits per fragment */
+ __u32 s_bpfshift; /* bits per fragment shift*/
+ __u32 s_bpfmask; /* bits per fragment mask */
+};
+
+
+#define UFS_MAX_GROUP_LOADED 8
+#define UFS_CGNO_EMPTY ((unsigned)-1)
+
+struct ufs_sb_info {
+ struct ufs_sb_private_info * s_uspi;
+ struct ufs_csum * s_csp[UFS_MAXCSBUFS];
+ unsigned s_swab;
+ unsigned s_flags;
+ struct buffer_head ** s_ucg;
+ struct ufs_cg_private_info * s_ucpi[UFS_MAX_GROUP_LOADED];
+ unsigned s_cgno[UFS_MAX_GROUP_LOADED];
+ unsigned short s_cg_loaded;
+ unsigned s_mount_opt;
+};
+
+/*
+ * Sizes of this structures are:
+ * ufs_super_block_first 512
+ * ufs_super_block_second 512
+ * ufs_super_block_third 356
+ */
+struct ufs_super_block_first {
+ __u32 fs_link;
+ __u32 fs_rlink;
+ __u32 fs_sblkno;
+ __u32 fs_cblkno;
+ __u32 fs_iblkno;
+ __u32 fs_dblkno;
+ __u32 fs_cgoffset;
+ __u32 fs_cgmask;
+ __u32 fs_time;
+ __u32 fs_size;
+ __u32 fs_dsize;
+ __u32 fs_ncg;
+ __u32 fs_bsize;
+ __u32 fs_fsize;
+ __u32 fs_frag;
+ __u32 fs_minfree;
+ __u32 fs_rotdelay;
+ __u32 fs_rps;
+ __u32 fs_bmask;
+ __u32 fs_fmask;
+ __u32 fs_bshift;
+ __u32 fs_fshift;
+ __u32 fs_maxcontig;
+ __u32 fs_maxbpg;
+ __u32 fs_fragshift;
+ __u32 fs_fsbtodb;
+ __u32 fs_sbsize;
+ __u32 fs_csmask;
+ __u32 fs_csshift;
+ __u32 fs_nindir;
+ __u32 fs_inopb;
+ __u32 fs_nspf;
+ __u32 fs_optim;
+ union {
+ struct {
+ __u32 fs_npsect;
+ } fs_sun;
+ struct {
+ __s32 fs_state;
+ } fs_sunx86;
+ } fs_u1;
+ __u32 fs_interleave;
+ __u32 fs_trackskew;
+ __u32 fs_id[2];
+ __u32 fs_csaddr;
+ __u32 fs_cssize;
+ __u32 fs_cgsize;
+ __u32 fs_ntrak;
+ __u32 fs_nsect;
+ __u32 fs_spc;
+ __u32 fs_ncyl;
+ __u32 fs_cpg;
+ __u32 fs_ipg;
+ __u32 fs_fpg;
+ struct ufs_csum fs_cstotal;
+ __s8 fs_fmod;
+ __s8 fs_clean;
+ __s8 fs_ronly;
+ __s8 fs_flags;
+ __s8 fs_fsmnt[UFS_MAXMNTLEN - 212];
+
+};
+
+struct ufs_super_block_second {
+ __s8 fs_fsmnt[212];
+ __u32 fs_cgrotor;
+ __u32 fs_csp[UFS_MAXCSBUFS];
+ __u32 fs_maxcluster;
+ __u32 fs_cpc;
+ __u16 fs_opostbl[82];
+};
+
+struct ufs_super_block_third {
+ __u16 fs_opostbl[46];
+ union {
+ struct {
+ __s32 fs_sparecon[53];/* reserved for future constants */
+ __s32 fs_reclaim;
+ __s32 fs_sparecon2[1];
+ __s32 fs_state; /* file system state time stamp */
+ __u32 fs_qbmask[2]; /* ~usb_bmask */
+ __u32 fs_qfmask[2]; /* ~usb_fmask */
+ } fs_sun;
+ struct {
+ __s32 fs_sparecon[53];/* reserved for future constants */
+ __s32 fs_reclaim;
+ __s32 fs_sparecon2[1];
+ __u32 fs_npsect; /* # sectors/track including spares */
+ __u32 fs_qbmask[2]; /* ~usb_bmask */
+ __u32 fs_qfmask[2]; /* ~usb_fmask */
+ } fs_sunx86;
+ struct {
+ __s32 fs_sparecon[50];/* reserved for future constants */
+ __s32 fs_contigsumsize;/* size of cluster summary array */
+ __s32 fs_maxsymlinklen;/* max length of an internal symlink */
+ __s32 fs_inodefmt; /* format of on-disk inodes */
+ __u32 fs_maxfilesize[2]; /* max representable file size */
+ __u32 fs_qbmask[2]; /* ~usb_bmask */
+ __u32 fs_qfmask[2]; /* ~usb_fmask */
+ __s32 fs_state; /* file system state time stamp */
+ } fs_44;
+ } fs_u2;
+ __s32 fs_postblformat;
+ __s32 fs_nrpos;
+ __s32 fs_postbloff;
+ __s32 fs_rotbloff;
+ __s32 fs_magic;
+ __u8 fs_space[1];
+};
+
+#endif /* __LINUX_UFS_FS_SB_H */
diff --git a/pfinet/linux-src/include/linux/uio.h b/pfinet/linux-src/include/linux/uio.h
new file mode 100644
index 00000000..beaafffd
--- /dev/null
+++ b/pfinet/linux-src/include/linux/uio.h
@@ -0,0 +1,37 @@
+#ifndef __LINUX_UIO_H
+#define __LINUX_UIO_H
+
+#include <linux/types.h>
+
+/*
+ * Berkeley style UIO structures - Alan Cox 1994.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+/* A word of warning: Our uio structure will clash with the C library one (which is now obsolete). Remove the C
+ library one from sys/uio.h if you have a very old library set */
+
+struct iovec
+{
+ void *iov_base; /* BSD uses caddr_t (1003.1g requires void *) */
+ __kernel_size_t iov_len; /* Must be size_t (1003.1g) */
+};
+
+/*
+ * UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1)
+ */
+
+#define UIO_FASTIOV 8
+#define UIO_MAXIOV 1024
+#if 0
+#define UIO_MAXIOV 16 /* Maximum iovec's in one operation
+ 16 matches BSD */
+ /* Beg pardon: BSD has 1024 --ANK */
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/ultrasound.h b/pfinet/linux-src/include/linux/ultrasound.h
new file mode 100644
index 00000000..6b7703e7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/ultrasound.h
@@ -0,0 +1,103 @@
+#ifndef _ULTRASOUND_H_
+#define _ULTRASOUND_H_
+/*
+ * ultrasound.h - Macros for programming the Gravis Ultrasound
+ * These macros are extremely device dependent
+ * and not portable.
+ */
+/*
+ * Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
+ */
+
+
+/*
+ * Private events for Gravis Ultrasound (GUS)
+ *
+ * Format:
+ * byte 0 - SEQ_PRIVATE (0xfe)
+ * byte 1 - Synthesizer device number (0-N)
+ * byte 2 - Command (see below)
+ * byte 3 - Voice number (0-31)
+ * bytes 4 and 5 - parameter P1 (unsigned short)
+ * bytes 6 and 7 - parameter P2 (unsigned short)
+ *
+ * Commands:
+ * Each command affects one voice defined in byte 3.
+ * Unused parameters (P1 and/or P2 *MUST* be initialized to zero).
+ * _GUS_NUMVOICES - Sets max. number of concurrent voices (P1=14-31, default 16)
+ * _GUS_VOICESAMPLE- ************ OBSOLETE *************
+ * _GUS_VOICEON - Starts voice (P1=voice mode)
+ * _GUS_VOICEOFF - Stops voice (no parameters)
+ * _GUS_VOICEFADE - Stops the voice smoothly.
+ * _GUS_VOICEMODE - Alters the voice mode, don't start or stop voice (P1=voice mode)
+ * _GUS_VOICEBALA - Sets voice balence (P1, 0=left, 7=middle and 15=right, default 7)
+ * _GUS_VOICEFREQ - Sets voice (sample) playback frequency (P1=Hz)
+ * _GUS_VOICEVOL - Sets voice volume (P1=volume, 0xfff=max, 0xeff=half, 0x000=off)
+ * _GUS_VOICEVOL2 - Sets voice volume (P1=volume, 0xfff=max, 0xeff=half, 0x000=off)
+ * (Like GUS_VOICEVOL but doesn't change the hw
+ * volume. It just updates volume in the voice table).
+ *
+ * _GUS_RAMPRANGE - Sets limits for volume ramping (P1=low volume, P2=high volume)
+ * _GUS_RAMPRATE - Sets the speed for volume ramping (P1=scale, P2=rate)
+ * _GUS_RAMPMODE - Sets the volume ramping mode (P1=ramping mode)
+ * _GUS_RAMPON - Starts volume ramping (no parameters)
+ * _GUS_RAMPOFF - Stops volume ramping (no parameters)
+ * _GUS_VOLUME_SCALE - Changes the volume calculation constants
+ * for all voices.
+ */
+
+#define _GUS_NUMVOICES 0x00
+#define _GUS_VOICESAMPLE 0x01 /* OBSOLETE */
+#define _GUS_VOICEON 0x02
+#define _GUS_VOICEOFF 0x03
+#define _GUS_VOICEMODE 0x04
+#define _GUS_VOICEBALA 0x05
+#define _GUS_VOICEFREQ 0x06
+#define _GUS_VOICEVOL 0x07
+#define _GUS_RAMPRANGE 0x08
+#define _GUS_RAMPRATE 0x09
+#define _GUS_RAMPMODE 0x0a
+#define _GUS_RAMPON 0x0b
+#define _GUS_RAMPOFF 0x0c
+#define _GUS_VOICEFADE 0x0d
+#define _GUS_VOLUME_SCALE 0x0e
+#define _GUS_VOICEVOL2 0x0f
+#define _GUS_VOICE_POS 0x10
+
+/*
+ * GUS API macros
+ */
+
+#define _GUS_CMD(chn, voice, cmd, p1, p2) \
+ {_SEQ_NEEDBUF(8); _seqbuf[_seqbufptr] = SEQ_PRIVATE;\
+ _seqbuf[_seqbufptr+1] = (chn); _seqbuf[_seqbufptr+2] = cmd;\
+ _seqbuf[_seqbufptr+3] = voice;\
+ *(unsigned short*)&_seqbuf[_seqbufptr+4] = p1;\
+ *(unsigned short*)&_seqbuf[_seqbufptr+6] = p2;\
+ _SEQ_ADVBUF(8);}
+
+#define GUS_NUMVOICES(chn, p1) _GUS_CMD(chn, 0, _GUS_NUMVOICES, (p1), 0)
+#define GUS_VOICESAMPLE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICESAMPLE, (p1), 0) /* OBSOLETE */
+#define GUS_VOICEON(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEON, (p1), 0)
+#define GUS_VOICEOFF(chn, voice) _GUS_CMD(chn, voice, _GUS_VOICEOFF, 0, 0)
+#define GUS_VOICEFADE(chn, voice) _GUS_CMD(chn, voice, _GUS_VOICEFADE, 0, 0)
+#define GUS_VOICEMODE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEMODE, (p1), 0)
+#define GUS_VOICEBALA(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEBALA, (p1), 0)
+#define GUS_VOICEFREQ(chn, voice, p) _GUS_CMD(chn, voice, _GUS_VOICEFREQ, \
+ (p) & 0xffff, ((p) >> 16) & 0xffff)
+#define GUS_VOICEVOL(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEVOL, (p1), 0)
+#define GUS_VOICEVOL2(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_VOICEVOL2, (p1), 0)
+#define GUS_RAMPRANGE(chn, voice, low, high) _GUS_CMD(chn, voice, _GUS_RAMPRANGE, (low), (high))
+#define GUS_RAMPRATE(chn, voice, p1, p2) _GUS_CMD(chn, voice, _GUS_RAMPRATE, (p1), (p2))
+#define GUS_RAMPMODE(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_RAMPMODE, (p1), 0)
+#define GUS_RAMPON(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_RAMPON, (p1), 0)
+#define GUS_RAMPOFF(chn, voice) _GUS_CMD(chn, voice, _GUS_RAMPOFF, 0, 0)
+#define GUS_VOLUME_SCALE(chn, voice, p1, p2) _GUS_CMD(chn, voice, _GUS_VOLUME_SCALE, (p1), (p2))
+#define GUS_VOICE_POS(chn, voice, p) _GUS_CMD(chn, voice, _GUS_VOICE_POS, \
+ (p) & 0xffff, ((p) >> 16) & 0xffff)
+
+#endif
diff --git a/pfinet/linux-src/include/linux/umsdos_fs.h b/pfinet/linux-src/include/linux/umsdos_fs.h
new file mode 100644
index 00000000..14bdb829
--- /dev/null
+++ b/pfinet/linux-src/include/linux/umsdos_fs.h
@@ -0,0 +1,188 @@
+#ifndef LINUX_UMSDOS_FS_H
+#define LINUX_UMSDOS_FS_H
+
+
+#define UMS_DEBUG 1 /* define for check_* functions */
+/*#define UMSDOS_DEBUG 1*/
+#define UMSDOS_PARANOIA 1
+
+#define UMSDOS_VERSION 0
+#define UMSDOS_RELEASE 4
+
+#define UMSDOS_ROOT_INO 1
+
+/* This is the file acting as a directory extension */
+#define UMSDOS_EMD_FILE "--linux-.---"
+#define UMSDOS_EMD_NAMELEN 12
+#define UMSDOS_PSDROOT_NAME "linux"
+#define UMSDOS_PSDROOT_LEN 5
+
+#ifndef _LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+#ifndef _LINUX_LIMITS_H
+#include <linux/limits.h>
+#endif
+#ifndef _LINUX_DIRENT_H
+#include <linux/dirent.h>
+#endif
+#ifndef _LINUX_IOCTL_H
+#include <linux/ioctl.h>
+#endif
+
+
+#ifdef __KERNEL__
+/* #Specification: convention / PRINTK Printk and printk
+ * Here is the convention for the use of printk inside fs/umsdos
+ *
+ * printk carry important message (error or status).
+ * Printk is for debugging (it is a macro defined at the beginning of
+ * most source.
+ * PRINTK is a nulled Printk macro.
+ *
+ * This convention makes the source easier to read, and Printk easier
+ * to shut off.
+ */
+# define PRINTK(x)
+# ifdef UMSDOS_DEBUG
+# define Printk(x) printk x
+# else
+# define Printk(x)
+# endif
+#endif
+
+
+struct umsdos_fake_info {
+ char fname[13];
+ int len;
+};
+
+#define UMSDOS_MAXNAME 220
+/* This structure is 256 bytes large, depending on the name, only part */
+/* of it is written to disk */
+/* nice though it would be, I can't change this and preserve backward compatibility */
+struct umsdos_dirent {
+ unsigned char name_len; /* if == 0, then this entry is not used */
+ unsigned char flags; /* UMSDOS_xxxx */
+ unsigned short nlink; /* How many hard links point to this entry */
+ uid_t uid; /* Owner user id */
+ gid_t gid; /* Group id */
+ time_t atime; /* Access time */
+ time_t mtime; /* Last modification time */
+ time_t ctime; /* Creation time */
+ dev_t rdev; /* major and minor number of a device */
+ /* special file */
+ umode_t mode; /* Standard UNIX permissions bits + type of */
+ char spare[12]; /* unused bytes for future extensions */
+ /* file, see linux/stat.h */
+ char name[UMSDOS_MAXNAME]; /* Not '\0' terminated */
+ /* but '\0' padded, so it will allow */
+ /* for adding news fields in this record */
+ /* by reducing the size of name[] */
+};
+
+#define UMSDOS_HIDDEN 1 /* Never show this entry in directory search */
+#define UMSDOS_HLINK 2 /* It is a (pseudo) hard link */
+
+/* #Specification: EMD file / record size
+ * Entry are 64 bytes wide in the EMD file. It allows for a 30 characters
+ * name. If a name is longer, contiguous entries are allocated. So a
+ * umsdos_dirent may span multiple records.
+ */
+
+#define UMSDOS_REC_SIZE 64
+
+/* Translation between MSDOS name and UMSDOS name */
+
+struct umsdos_info {
+ int msdos_reject; /* Tell if the file name is invalid for MSDOS */
+ /* See umsdos_parse */
+ struct umsdos_fake_info fake;
+ struct umsdos_dirent entry;
+ off_t f_pos; /* offset of the entry in the EMD file
+ * or offset where the entry may be store
+ * if it is a new entry
+ */
+ int recsize; /* Record size needed to store entry */
+};
+
+/* Definitions for ioctl (number randomly chosen)
+ * The next ioctl commands operate only on the DOS directory
+ * The file umsdos_progs/umsdosio.c contain a string table
+ * based on the order of those definition. Keep it in sync
+ */
+#define UMSDOS_READDIR_DOS _IO(0x04,210) /* Do a readdir of the DOS directory */
+#define UMSDOS_UNLINK_DOS _IO(0x04,211) /* Erase in the DOS directory only */
+#define UMSDOS_RMDIR_DOS _IO(0x04,212) /* rmdir in the DOS directory only */
+#define UMSDOS_STAT_DOS _IO(0x04,213) /* Get info about a file */
+
+/* The next ioctl commands operate only on the EMD file */
+#define UMSDOS_CREAT_EMD _IO(0x04,214) /* Create a file */
+#define UMSDOS_UNLINK_EMD _IO(0x04,215) /* unlink (rmdir) a file */
+#define UMSDOS_READDIR_EMD _IO(0x04,216) /* read the EMD file only. */
+#define UMSDOS_GETVERSION _IO(0x04,217) /* Get the release number of UMSDOS */
+#define UMSDOS_INIT_EMD _IO(0x04,218) /* Create the EMD file if not there */
+#define UMSDOS_DOS_SETUP _IO(0x04,219) /* Set the defaults of the MS-DOS driver. */
+
+#define UMSDOS_RENAME_DOS _IO(0x04,220) /* rename a file/directory in the DOS
+ * directory only */
+struct umsdos_ioctl {
+ struct dirent dos_dirent;
+ struct umsdos_dirent umsdos_dirent;
+ /* The following structure is used to exchange some data
+ * with utilities (umsdos_progs/util/umsdosio.c). The first
+ * releases were using struct stat from "sys/stat.h". This was
+ * causing some problem for cross compilation of the kernel
+ * Since I am not really using the structure stat, but only some field
+ * of it, I have decided to replicate the structure here
+ * for compatibility with the binaries out there
+ * FIXME PTW 1998, this has probably changed
+ */
+
+ struct {
+ dev_t st_dev;
+ unsigned short __pad1;
+ ino_t st_ino;
+ umode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ unsigned short __pad2;
+ off_t st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ time_t st_atime;
+ unsigned long __unused1;
+ time_t st_mtime;
+ unsigned long __unused2;
+ time_t st_ctime;
+ unsigned long __unused3;
+ unsigned long __unused4;
+ unsigned long __unused5;
+ } stat;
+ char version, release;
+};
+
+/* Different macros to access struct umsdos_dirent */
+#define EDM_ENTRY_ISUSED(e) ((e)->name_len!=0)
+
+#ifdef __KERNEL__
+
+#ifndef LINUX_FS_H
+#include <linux/fs.h>
+#endif
+
+extern struct inode_operations umsdos_dir_inode_operations;
+extern struct file_operations umsdos_file_operations;
+extern struct inode_operations umsdos_file_inode_operations;
+extern struct inode_operations umsdos_file_inode_operations_no_bmap;
+extern struct inode_operations umsdos_file_inode_operations_readpage;
+extern struct inode_operations umsdos_symlink_inode_operations;
+extern int init_umsdos_fs (void);
+
+#include <linux/umsdos_fs.p>
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/umsdos_fs.p b/pfinet/linux-src/include/linux/umsdos_fs.p
new file mode 100644
index 00000000..de436f0e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/umsdos_fs.p
@@ -0,0 +1,118 @@
+/* check.c 23/01/95 03.38.30 */
+void check_page_tables (void);
+
+/* dir.c 22/06/95 00.22.12 */
+int dummy_dir_read ( struct file *filp,
+ char *buf,
+ size_t size,
+ loff_t *count);
+char * umsdos_d_path(struct dentry *, char *, int);
+void umsdos_lookup_patch_new(struct dentry *, struct umsdos_info *);
+int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry);
+struct dentry *umsdos_lookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo);
+struct dentry *UMSDOS_lookup(struct inode *, struct dentry *);
+struct dentry *umsdos_lookup_dentry(struct dentry *, char *, int, int);
+struct dentry *umsdos_covered(struct dentry *, char *, int);
+
+struct dentry *umsdos_solve_hlink (struct dentry *hlink);
+
+/* emd.c 22/06/95 00.22.04 */
+ssize_t umsdos_file_write_kmem_real (struct file *filp,
+ const char *buf,
+ size_t count);
+
+ssize_t umsdos_file_read_kmem (struct file *filp,
+ char *buf,
+ size_t count);
+ssize_t umsdos_file_write_kmem (struct file *filp,
+ const char *buf,
+ size_t count);
+ssize_t umsdos_emd_dir_write (struct file *filp,
+ char *buf,
+ size_t count);
+ssize_t umsdos_emd_dir_read (struct file *filp,
+ char *buf,
+ size_t count);
+struct dentry *umsdos_get_emd_dentry(struct dentry *);
+int umsdos_have_emd(struct dentry *);
+int umsdos_make_emd(struct dentry *);
+int umsdos_emd_dir_readentry (struct file *, struct umsdos_dirent *);
+int umsdos_newentry (struct dentry *, struct umsdos_info *);
+int umsdos_newhidden (struct dentry *, struct umsdos_info *);
+int umsdos_delentry (struct dentry *, struct umsdos_info *, int);
+int umsdos_findentry (struct dentry *, struct umsdos_info *, int);
+int umsdos_isempty (struct dentry *);
+
+/* file.c 25/01/95 02.25.38 */
+
+/* inode.c 12/06/95 09.49.40 */
+void fill_new_filp (struct file *filp, struct dentry *dentry);
+void UMSDOS_read_inode (struct inode *);
+void UMSDOS_write_inode (struct inode *);
+int UMSDOS_notify_change (struct dentry *, struct iattr *attr);
+int umsdos_notify_change_locked(struct dentry *, struct iattr *attr);
+void UMSDOS_put_inode (struct inode *);
+int UMSDOS_statfs (struct super_block *, struct statfs *, int);
+struct super_block *UMSDOS_read_super (struct super_block *, void *, int);
+void UMSDOS_put_super (struct super_block *);
+
+void umsdos_setup_dir(struct dentry *);
+void umsdos_set_dirinfo_new(struct dentry *, off_t);
+void umsdos_patch_dentry_inode (struct dentry *, off_t);
+int umsdos_get_dirowner (struct inode *inode, struct inode **result);
+
+/* ioctl.c 22/06/95 00.22.08 */
+int UMSDOS_ioctl_dir (struct inode *dir,
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long data);
+
+/* mangle.c 25/01/95 02.25.38 */
+void umsdos_manglename (struct umsdos_info *info);
+int umsdos_evalrecsize (int len);
+int umsdos_parse (const char *name,int len, struct umsdos_info *info);
+
+/* namei.c 25/01/95 02.25.38 */
+void umsdos_lockcreate (struct inode *dir);
+void umsdos_startlookup (struct inode *dir);
+void umsdos_unlockcreate (struct inode *dir);
+void umsdos_endlookup (struct inode *dir);
+
+int umsdos_readlink_x ( struct dentry *dentry,
+ char *buffer,
+ int bufsiz);
+int UMSDOS_symlink (struct inode *dir,
+ struct dentry *dentry,
+ const char *symname);
+int UMSDOS_link (struct dentry *olddentry,
+ struct inode *dir,
+ struct dentry *dentry);
+int UMSDOS_create (struct inode *dir,
+ struct dentry *dentry,
+ int mode);
+
+int UMSDOS_mkdir (struct inode *dir,
+ struct dentry *dentry,
+ int mode);
+int UMSDOS_mknod (struct inode *dir,
+ struct dentry *dentry,
+ int mode,
+ int rdev);
+int UMSDOS_rmdir (struct inode *dir,struct dentry *dentry);
+int UMSDOS_unlink (struct inode *dir, struct dentry *dentry);
+int UMSDOS_rename (struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct inode *new_dir,
+ struct dentry *new_dentry);
+
+/* rdir.c 22/03/95 03.31.42 */
+struct dentry *umsdos_rlookup_x (struct inode *dir, struct dentry *dentry, int nopseudo);
+struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry);
+
+/* symlink.c 23/01/95 03.38.30 */
+
+/* check.c */
+void checkd_inode (struct inode *inode);
+void check_inode (struct inode *inode);
+void check_dentry (struct dentry *dentry);
+void check_dentry_path (struct dentry *dentry, const char *desc);
diff --git a/pfinet/linux-src/include/linux/umsdos_fs_i.h b/pfinet/linux-src/include/linux/umsdos_fs_i.h
new file mode 100644
index 00000000..111fd913
--- /dev/null
+++ b/pfinet/linux-src/include/linux/umsdos_fs_i.h
@@ -0,0 +1,75 @@
+#ifndef UMSDOS_FS_I_H
+#define UMSDOS_FS_I_H
+
+#ifndef _LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+
+#include <linux/msdos_fs_i.h>
+#include <linux/pipe_fs_i.h>
+
+/* #Specification: strategy / in memory inode
+ * Here is the information specific to the inode of the UMSDOS file
+ * system. This information is added to the end of the standard struct
+ * inode. Each file system has its own extension to struct inode,
+ * so do the umsdos file system.
+ *
+ * The strategy is to have the umsdos_inode_info as a superset of
+ * the msdos_inode_info, since most of the time the job is done
+ * by the msdos fs code.
+ *
+ * So we duplicate the msdos_inode_info, and add our own info at the
+ * end.
+ *
+ * For all file type (and directory) the inode has a reference to:
+ * the directory which hold this entry: i_dir_owner
+ * The EMD file of i_dir_owner: i_emd_owner
+ * The offset in this EMD file of the entry: pos
+ *
+ * For directory, we also have a reference to the inode of its
+ * own EMD file. Also, we have dir_locking_info to help synchronise
+ * file creation and file lookup. This data is sharing space with
+ * the pipe_inode_info not used by directory. See also msdos_fs_i.h
+ * for more information about pipe_inode_info and msdos_inode_info.
+ *
+ * Special file and fifo do have an inode which correspond to an
+ * empty MSDOS file.
+ *
+ * symlink are processed mostly like regular file. The content is the
+ * link.
+ *
+ * fifos add there own extension to the inode. I have reserved some
+ * space for fifos side by side with msdos_inode_info. This is just
+ * to for the show, because msdos_inode_info already include the
+ * pipe_inode_info.
+ *
+ * The UMSDOS specific extension is placed after the union.
+ */
+
+struct dir_locking_info {
+ struct wait_queue *p;
+ short int looking; /* How many process doing a lookup */
+ short int creating; /* Is there any creation going on here
+ * Only one at a time, although one
+ * may recursively lock, so it is a counter
+ */
+ long pid; /* pid of the process owning the creation */
+ /* lock */
+};
+
+struct umsdos_inode_info {
+ union {
+ struct msdos_inode_info msdos_info;
+ struct pipe_inode_info pipe_info;
+ struct dir_locking_info dir_info;
+ } u;
+ int i_patched; /* Inode has been patched */
+ int i_is_hlink; /* Resolved hardlink inode? */
+ unsigned long i_emd_owner; /* Is this the EMD file inode? */
+ off_t pos; /* Entry offset in the emd_owner file */
+ /* The rest is used only if this inode describes a directory */
+ struct dentry *i_emd_dentry; /* EMD dentry for this directory */
+ unsigned long i_emd_dir; /* Inode of the EMD file */
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/un.h b/pfinet/linux-src/include/linux/un.h
new file mode 100644
index 00000000..45561c56
--- /dev/null
+++ b/pfinet/linux-src/include/linux/un.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_UN_H
+#define _LINUX_UN_H
+
+#define UNIX_PATH_MAX 108
+
+struct sockaddr_un {
+ sa_family_t sun_family; /* AF_UNIX */
+ char sun_path[UNIX_PATH_MAX]; /* pathname */
+};
+
+#endif /* _LINUX_UN_H */
diff --git a/pfinet/linux-src/include/linux/unistd.h b/pfinet/linux-src/include/linux/unistd.h
new file mode 100644
index 00000000..10ed9834
--- /dev/null
+++ b/pfinet/linux-src/include/linux/unistd.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_UNISTD_H_
+#define _LINUX_UNISTD_H_
+
+extern int errno;
+
+/*
+ * Include machine specific syscallX macros
+ */
+#include <asm/unistd.h>
+
+#endif /* _LINUX_UNISTD_H_ */
diff --git a/pfinet/linux-src/include/linux/user.h b/pfinet/linux-src/include/linux/user.h
new file mode 100644
index 00000000..68daf840
--- /dev/null
+++ b/pfinet/linux-src/include/linux/user.h
@@ -0,0 +1 @@
+#include <asm/user.h>
diff --git a/pfinet/linux-src/include/linux/utime.h b/pfinet/linux-src/include/linux/utime.h
new file mode 100644
index 00000000..c6bf27b7
--- /dev/null
+++ b/pfinet/linux-src/include/linux/utime.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_UTIME_H
+#define _LINUX_UTIME_H
+
+struct utimbuf {
+ time_t actime;
+ time_t modtime;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/uts.h b/pfinet/linux-src/include/linux/uts.h
new file mode 100644
index 00000000..39e09ae1
--- /dev/null
+++ b/pfinet/linux-src/include/linux/uts.h
@@ -0,0 +1,23 @@
+#ifndef _LINUX_UTS_H
+#define _LINUX_UTS_H
+
+/*
+ * Defines for what uname() should return
+ */
+#ifndef UTS_SYSNAME
+#define UTS_SYSNAME "Linux"
+#endif
+
+#ifndef UTS_MACHINE
+#define UTS_MACHINE "unknown"
+#endif
+
+#ifndef UTS_NODENAME
+#define UTS_NODENAME "(none)" /* set by sethostname() */
+#endif
+
+#ifndef UTS_DOMAINNAME
+#define UTS_DOMAINNAME "(none)" /* set by setdomainname() */
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/utsname.h b/pfinet/linux-src/include/linux/utsname.h
new file mode 100644
index 00000000..a83503f9
--- /dev/null
+++ b/pfinet/linux-src/include/linux/utsname.h
@@ -0,0 +1,36 @@
+#ifndef _LINUX_UTSNAME_H
+#define _LINUX_UTSNAME_H
+
+#define __OLD_UTS_LEN 8
+
+struct oldold_utsname {
+ char sysname[9];
+ char nodename[9];
+ char release[9];
+ char version[9];
+ char machine[9];
+};
+
+#define __NEW_UTS_LEN 64
+
+struct old_utsname {
+ char sysname[65];
+ char nodename[65];
+ char release[65];
+ char version[65];
+ char machine[65];
+};
+
+struct new_utsname {
+ char sysname[65];
+ char nodename[65];
+ char release[65];
+ char version[65];
+ char machine[65];
+ char domainname[65];
+};
+
+extern struct new_utsname system_utsname;
+
+extern struct semaphore uts_sem;
+#endif
diff --git a/pfinet/linux-src/include/linux/vfs.h b/pfinet/linux-src/include/linux/vfs.h
new file mode 100644
index 00000000..b3a58657
--- /dev/null
+++ b/pfinet/linux-src/include/linux/vfs.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_VFS_H
+#define _LINUX_VFS_H
+
+#include <asm/statfs.h>
+
+#endif
diff --git a/pfinet/linux-src/include/linux/video_decoder.h b/pfinet/linux-src/include/linux/video_decoder.h
new file mode 100644
index 00000000..1302c7f4
--- /dev/null
+++ b/pfinet/linux-src/include/linux/video_decoder.h
@@ -0,0 +1,37 @@
+#ifndef _LINUX_VIDEO_DECODER_H
+#define _LINUX_VIDEO_DECODER_H
+
+struct video_decoder_capability { /* this name is too long */
+ __u32 flags;
+#define VIDEO_DECODER_PAL 1 /* can decode PAL signal */
+#define VIDEO_DECODER_NTSC 2 /* can decode NTSC */
+#define VIDEO_DECODER_SECAM 4 /* can decode SECAM */
+#define VIDEO_DECODER_AUTO 8 /* can autosense norm */
+#define VIDEO_DECODER_CCIR 16 /* CCIR-601 pixel rate (720 pixels per line) instead of square pixel rate */
+ int inputs; /* number of inputs */
+ int outputs; /* number of outputs */
+};
+
+/*
+DECODER_GET_STATUS returns the following flags. The only one you need is
+DECODER_STATUS_GOOD, the others are just nice things to know.
+*/
+#define DECODER_STATUS_GOOD 1 /* receiving acceptable input */
+#define DECODER_STATUS_COLOR 2 /* receiving color information */
+#define DECODER_STATUS_PAL 4 /* auto detected */
+#define DECODER_STATUS_NTSC 8 /* auto detected */
+#define DECODER_STATUS_SECAM 16 /* auto detected */
+
+
+#define DECODER_GET_CAPABILITIES _IOR('d', 1, struct video_decoder_capability)
+#define DECODER_GET_STATUS _IOR('d', 2, int)
+#define DECODER_SET_NORM _IOW('d', 3, int)
+#define DECODER_SET_INPUT _IOW('d', 4, int) /* 0 <= input < #inputs */
+#define DECODER_SET_OUTPUT _IOW('d', 5, int) /* 0 <= output < #outputs */
+#define DECODER_ENABLE_OUTPUT _IOW('d', 6, int) /* boolean output enable control */
+#define DECODER_SET_PICTURE _IOW('d', 7, struct video_picture)
+
+#define DECODER_DUMP _IO('d', 192) /* debug hook */
+
+
+#endif
diff --git a/pfinet/linux-src/include/linux/video_encoder.h b/pfinet/linux-src/include/linux/video_encoder.h
new file mode 100644
index 00000000..4b0e6907
--- /dev/null
+++ b/pfinet/linux-src/include/linux/video_encoder.h
@@ -0,0 +1,21 @@
+#ifndef _LINUX_VIDEO_ENCODER_H
+#define _LINUX_VIDEO_ENCODER_H
+
+struct video_encoder_capability { /* this name is too long */
+ __u32 flags;
+#define VIDEO_ENCODER_PAL 1 /* can encode PAL signal */
+#define VIDEO_ENCODER_NTSC 2 /* can encode NTSC */
+#define VIDEO_ENCODER_SECAM 4 /* can encode SECAM */
+#define VIDEO_ENCODER_CCIR 16 /* CCIR-601 pixel rate (720 pixels per line) instead of square pixel rate */
+ int inputs; /* number of inputs */
+ int outputs; /* number of outputs */
+};
+
+#define ENCODER_GET_CAPABILITIES _IOR('e', 1, struct video_encoder_capability)
+#define ENCODER_SET_NORM _IOW('e', 2, int)
+#define ENCODER_SET_INPUT _IOW('e', 3, int) /* 0 <= input < #inputs */
+#define ENCODER_SET_OUTPUT _IOW('e', 4, int) /* 0 <= output < #outputs */
+#define ENCODER_ENABLE_OUTPUT _IOW('e', 5, int) /* boolean output enable control */
+
+
+#endif
diff --git a/pfinet/linux-src/include/linux/videodev.h b/pfinet/linux-src/include/linux/videodev.h
new file mode 100644
index 00000000..119b60ee
--- /dev/null
+++ b/pfinet/linux-src/include/linux/videodev.h
@@ -0,0 +1,292 @@
+#ifndef __LINUX_VIDEODEV_H
+#define __LINUX_VIDEODEV_H
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+#ifdef __KERNEL__
+
+#if LINUX_VERSION_CODE >= 0x020100
+#include <linux/poll.h>
+#endif
+
+struct video_device
+{
+ char name[32];
+ int type;
+ int hardware;
+
+ int (*open)(struct video_device *, int mode);
+ void (*close)(struct video_device *);
+ long (*read)(struct video_device *, char *, unsigned long, int noblock);
+ /* Do we need a write method ? */
+ long (*write)(struct video_device *, const char *, unsigned long, int noblock);
+#if LINUX_VERSION_CODE >= 0x020100
+ unsigned int (*poll)(struct video_device *, struct file *, poll_table *);
+#endif
+ int (*ioctl)(struct video_device *, unsigned int , void *);
+ int (*mmap)(struct video_device *, const char *, unsigned long);
+ int (*initialize)(struct video_device *);
+ void *priv; /* Used to be 'private' but that upsets C++ */
+ int busy;
+ int minor;
+};
+
+extern int videodev_init(void);
+#define VIDEO_MAJOR 81
+extern int video_register_device(struct video_device *, int type);
+
+#define VFL_TYPE_GRABBER 0
+#define VFL_TYPE_VBI 1
+#define VFL_TYPE_RADIO 2
+#define VFL_TYPE_VTX 3
+
+extern void video_unregister_device(struct video_device *);
+#endif
+
+
+#define VID_TYPE_CAPTURE 1 /* Can capture */
+#define VID_TYPE_TUNER 2 /* Can tune */
+#define VID_TYPE_TELETEXT 4 /* Does teletext */
+#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */
+#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */
+#define VID_TYPE_CLIPPING 32 /* Can clip */
+#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */
+#define VID_TYPE_SCALES 128 /* Scalable */
+#define VID_TYPE_MONOCHROME 256 /* Monochrome only */
+#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */
+
+struct video_capability
+{
+ char name[32];
+ int type;
+ int channels; /* Num channels */
+ int audios; /* Num audio devices */
+ int maxwidth; /* Supported width */
+ int maxheight; /* And height */
+ int minwidth; /* Supported width */
+ int minheight; /* And height */
+};
+
+
+struct video_channel
+{
+ int channel;
+ char name[32];
+ int tuners;
+ __u32 flags;
+#define VIDEO_VC_TUNER 1 /* Channel has a tuner */
+#define VIDEO_VC_AUDIO 2 /* Channel has audio */
+ __u16 type;
+#define VIDEO_TYPE_TV 1
+#define VIDEO_TYPE_CAMERA 2
+ __u16 norm; /* Norm set by channel */
+};
+
+struct video_tuner
+{
+ int tuner;
+ char name[32];
+ ulong rangelow, rangehigh; /* Tuner range */
+ __u32 flags;
+#define VIDEO_TUNER_PAL 1
+#define VIDEO_TUNER_NTSC 2
+#define VIDEO_TUNER_SECAM 4
+#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */
+#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */
+#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */
+#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */
+#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */
+ __u16 mode; /* PAL/NTSC/SECAM/OTHER */
+#define VIDEO_MODE_PAL 0
+#define VIDEO_MODE_NTSC 1
+#define VIDEO_MODE_SECAM 2
+#define VIDEO_MODE_AUTO 3
+ __u16 signal; /* Signal strength 16bit scale */
+};
+
+struct video_picture
+{
+ __u16 brightness;
+ __u16 hue;
+ __u16 colour;
+ __u16 contrast;
+ __u16 whiteness; /* Black and white only */
+ __u16 depth; /* Capture depth */
+ __u16 palette; /* Palette in use */
+#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */
+#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */
+#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */
+#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */
+#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */
+#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */
+#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */
+#define VIDEO_PALETTE_YUYV 8
+#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */
+#define VIDEO_PALETTE_YUV420 10
+#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */
+#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
+#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
+#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
+#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */
+#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */
+#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */
+#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */
+};
+
+struct video_audio
+{
+ int audio; /* Audio channel */
+ __u16 volume; /* If settable */
+ __u16 bass, treble;
+ __u32 flags;
+#define VIDEO_AUDIO_MUTE 1
+#define VIDEO_AUDIO_MUTABLE 2
+#define VIDEO_AUDIO_VOLUME 4
+#define VIDEO_AUDIO_BASS 8
+#define VIDEO_AUDIO_TREBLE 16
+ char name[16];
+#define VIDEO_SOUND_MONO 1
+#define VIDEO_SOUND_STEREO 2
+#define VIDEO_SOUND_LANG1 4
+#define VIDEO_SOUND_LANG2 8
+ __u16 mode;
+ __u16 balance; /* Stereo balance */
+ __u16 step; /* Step actual volume uses */
+};
+
+struct video_clip
+{
+ __s32 x,y;
+ __s32 width, height;
+ struct video_clip *next; /* For user use/driver use only */
+};
+
+struct video_window
+{
+ __u32 x,y; /* Position of window */
+ __u32 width,height; /* Its size */
+ __u32 chromakey;
+ __u32 flags;
+ struct video_clip *clips; /* Set only */
+ int clipcount;
+#define VIDEO_WINDOW_INTERLACE 1
+#define VIDEO_CLIP_BITMAP -1
+/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
+#define VIDEO_CLIPMAP_SIZE (128 * 625)
+};
+
+struct video_capture
+{
+ __u32 x,y; /* Offsets into image */
+ __u32 width, height; /* Area to capture */
+ __u16 decimation; /* Decimation divder */
+ __u16 flags; /* Flags for capture */
+#define VIDEO_CAPTURE_ODD 0 /* Temporal */
+#define VIDEO_CAPTURE_EVEN 1
+};
+
+struct video_buffer
+{
+ void *base;
+ int height,width;
+ int depth;
+ int bytesperline;
+};
+
+struct video_mmap
+{
+ unsigned int frame; /* Frame (0 - n) for double buffer */
+ int height,width;
+ unsigned int format; /* should be VIDEO_PALETTE_* */
+};
+
+struct video_key
+{
+ __u8 key[8];
+ __u32 flags;
+};
+
+
+#define VIDEO_MAX_FRAME 32
+
+struct video_mbuf
+{
+ int size; /* Total memory to map */
+ int frames; /* Frames */
+ int offsets[VIDEO_MAX_FRAME];
+};
+
+
+#define VIDEO_NO_UNIT (-1)
+
+
+struct video_unit
+{
+ int video; /* Video minor */
+ int vbi; /* VBI minor */
+ int radio; /* Radio minor */
+ int audio; /* Audio minor */
+ int teletext; /* Teletext minor */
+};
+
+#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */
+#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */
+#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */
+#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */
+#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */
+#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */
+#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */
+#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */
+#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Set the video overlay window */
+#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
+#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */
+#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */
+#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */
+#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */
+#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */
+#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */
+#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */
+#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */
+#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */
+#define VIDIOCGMBUF _IOR('v', 20, struct video_mbuf) /* Memory map buffer info */
+#define VIDIOCGUNIT _IOR('v', 21, struct video_unit) /* Get attached units */
+#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get frame buffer */
+#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set frame buffer - root only */
+
+#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */
+
+
+#define VID_HARDWARE_BT848 1
+#define VID_HARDWARE_QCAM_BW 2
+#define VID_HARDWARE_PMS 3
+#define VID_HARDWARE_QCAM_C 4
+#define VID_HARDWARE_PSEUDO 5
+#define VID_HARDWARE_SAA5249 6
+#define VID_HARDWARE_AZTECH 7
+#define VID_HARDWARE_SF16MI 8
+#define VID_HARDWARE_RTRACK 9
+#define VID_HARDWARE_ZOLTRIX 10
+#define VID_HARDWARE_SAA7146 11
+#define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */
+#define VID_HARDWARE_RTRACK2 13
+#define VID_HARDWARE_PERMEDIA2 14 /* Reserved for Permedia2 */
+#define VID_HARDWARE_RIVA128 15 /* Reserved for RIVA 128 */
+#define VID_HARDWARE_PLANB 16 /* PowerMac motherboard video-in */
+#define VID_HARDWARE_BROADWAY 17 /* Broadway project */
+#define VID_HARDWARE_GEMTEK 18
+#define VID_HARDWARE_TYPHOON 19
+#define VID_HARDWARE_VINO 20 /* Reserved for SGI Indy Vino */
+#define VID_HARDWARE_CADET 21 /* Cadet radio */
+
+/*
+ * Initialiser list
+ */
+
+struct video_init
+{
+ char *name;
+ int (*init)(struct video_init *);
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/videotext.h b/pfinet/linux-src/include/linux/videotext.h
new file mode 100644
index 00000000..78faf6af
--- /dev/null
+++ b/pfinet/linux-src/include/linux/videotext.h
@@ -0,0 +1,144 @@
+#ifndef _VTX_H
+#define _VTX_H
+
+/* $Id: videotext.h,v 1.1 1998/03/30 22:26:39 alan Exp $
+ *
+ * Copyright (c) 1994-97 Martin Buck <martin-2.buck@student.uni-ulm.de>
+ * Read COPYING for more information
+ *
+ */
+
+
+/*
+ * Videotext ioctls
+ */
+#define VTXIOCGETINFO 0x7101 /* get version of driver & capabilities of vtx-chipset */
+#define VTXIOCCLRPAGE 0x7102 /* clear page-buffer */
+#define VTXIOCCLRFOUND 0x7103 /* clear bits indicating that page was found */
+#define VTXIOCPAGEREQ 0x7104 /* search for page */
+#define VTXIOCGETSTAT 0x7105 /* get status of page-buffer */
+#define VTXIOCGETPAGE 0x7106 /* get contents of page-buffer */
+#define VTXIOCSTOPDAU 0x7107 /* stop data acquisition unit */
+#define VTXIOCPUTPAGE 0x7108 /* display page on TV-screen */
+#define VTXIOCSETDISP 0x7109 /* set TV-mode */
+#define VTXIOCPUTSTAT 0x710a /* set status of TV-output-buffer */
+#define VTXIOCCLRCACHE 0x710b /* clear cache on VTX-interface (if avail.) */
+#define VTXIOCSETVIRT 0x710c /* turn on virtual mode (this disables TV-display) */
+
+
+/*
+ * Definitions for VTXIOCGETINFO
+ */
+
+#define SAA5243 0
+#define SAA5246 1
+#define SAA5249 2
+#define SAA5248 3
+#define XSTV5346 4
+
+typedef struct {
+ int version_major, version_minor; /* version of driver; if version_major changes, driver */
+ /* is not backward compatible!!! CHECK THIS!!! */
+ int numpages; /* number of page-buffers of vtx-chipset */
+ int cct_type; /* type of vtx-chipset (SAA5243, SAA5246, SAA5248 or
+ * SAA5249) */
+}
+vtx_info_t;
+
+
+/*
+ * Definitions for VTXIOC{CLRPAGE,CLRFOUND,PAGEREQ,GETSTAT,GETPAGE,STOPDAU,PUTPAGE,SETDISP}
+ */
+
+#define MIN_UNIT (1<<0)
+#define MIN_TEN (1<<1)
+#define HR_UNIT (1<<2)
+#define HR_TEN (1<<3)
+#define PG_UNIT (1<<4)
+#define PG_TEN (1<<5)
+#define PG_HUND (1<<6)
+#define PGMASK_MAX (1<<7)
+#define PGMASK_PAGE (PG_HUND | PG_TEN | PG_UNIT)
+#define PGMASK_HOUR (HR_TEN | HR_UNIT)
+#define PGMASK_MINUTE (MIN_TEN | MIN_UNIT)
+
+typedef struct
+{
+ int page; /* number of requested page (hexadecimal) */
+ int hour; /* requested hour (hexadecimal) */
+ int minute; /* requested minute (hexadecimal) */
+ int pagemask; /* mask defining which values of the above are set */
+ int pgbuf; /* buffer where page will be stored */
+ int start; /* start of requested part of page */
+ int end; /* end of requested part of page */
+ void *buffer; /* pointer to beginning of destination buffer */
+}
+vtx_pagereq_t;
+
+
+/*
+ * Definitions for VTXIOC{GETSTAT,PUTSTAT}
+ */
+
+#define VTX_PAGESIZE (40 * 24)
+#define VTX_VIRTUALSIZE (40 * 49)
+
+typedef struct
+{
+ int pagenum; /* number of page (hexadecimal) */
+ int hour; /* hour (hexadecimal) */
+ int minute; /* minute (hexadecimal) */
+ int charset; /* national charset */
+ unsigned delete : 1; /* delete page (C4) */
+ unsigned headline : 1; /* insert headline (C5) */
+ unsigned subtitle : 1; /* insert subtitle (C6) */
+ unsigned supp_header : 1; /* suppress header (C7) */
+ unsigned update : 1; /* update page (C8) */
+ unsigned inter_seq : 1; /* interrupted sequence (C9) */
+ unsigned dis_disp : 1; /* disable/suppress display (C10) */
+ unsigned serial : 1; /* serial mode (C11) */
+ unsigned notfound : 1; /* /FOUND */
+ unsigned pblf : 1; /* PBLF */
+ unsigned hamming : 1; /* hamming-error occurred */
+}
+vtx_pageinfo_t;
+
+
+/*
+ * Definitions for VTXIOCSETDISP
+ */
+
+typedef enum {
+ DISPOFF, DISPNORM, DISPTRANS, DISPINS, INTERLACE_OFFSET
+} vtxdisp_t;
+
+
+
+/*
+ * Tuner ioctls
+ */
+
+#define TUNIOCGETINFO 0x7201 /* get version of driver & capabilities of tuner */
+#define TUNIOCRESET 0x7202 /* reset tuner */
+#define TUNIOCSETFREQ 0x7203 /* set tuning frequency (unit: kHz) */
+#define TUNIOCGETFREQ 0x7204 /* get tuning frequency (unit: kHz) */
+#define TUNIOCSETCHAN 0x7205 /* set tuning channel */
+#define TUNIOCGETCHAN 0x7206 /* get tuning channel */
+
+
+typedef struct
+{
+ int version_major, version_minor; /* version of driver; if version_major changes, driver */
+ /* is not backward compatible!!! CHECK THIS!!! */
+ unsigned freq : 1; /* tuner can be set to given frequency */
+ unsigned chan : 1; /* tuner stores several channels */
+ unsigned scan : 1; /* tuner supports scanning */
+ unsigned autoscan : 1; /* tuner supports scanning with automatic stop */
+ unsigned afc : 1; /* tuner supports AFC */
+ unsigned dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, dummy7, dummy8, dummy9, dummy10,
+ dummy11 : 1;
+ int dummy12, dummy13, dummy14, dummy15, dummy16, dummy17, dummy18, dummy19;
+} tuner_info_t;
+
+
+#endif /* _VTX_H */
diff --git a/pfinet/linux-src/include/linux/vmalloc.h b/pfinet/linux-src/include/linux/vmalloc.h
new file mode 100644
index 00000000..340544fd
--- /dev/null
+++ b/pfinet/linux-src/include/linux/vmalloc.h
@@ -0,0 +1,24 @@
+#ifndef __LINUX_VMALLOC_H
+#define __LINUX_VMALLOC_H
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/pgtable.h>
+
+struct vm_struct {
+ unsigned long flags;
+ void * addr;
+ unsigned long size;
+ struct vm_struct * next;
+};
+
+struct vm_struct * get_vm_area(unsigned long size);
+void vfree(void * addr);
+void * vmalloc(unsigned long size);
+long vread(char *buf, char *addr, unsigned long count);
+void vmfree_area_pages(unsigned long address, unsigned long size);
+int vmalloc_area_pages(unsigned long address, unsigned long size);
+
+#endif
+
diff --git a/pfinet/linux-src/include/linux/vt.h b/pfinet/linux-src/include/linux/vt.h
new file mode 100644
index 00000000..9f95b0be
--- /dev/null
+++ b/pfinet/linux-src/include/linux/vt.h
@@ -0,0 +1,54 @@
+#ifndef _LINUX_VT_H
+#define _LINUX_VT_H
+
+/* 0x56 is 'V', to avoid collision with termios and kd */
+
+#define VT_OPENQRY 0x5600 /* find available vt */
+
+struct vt_mode {
+ char mode; /* vt mode */
+ char waitv; /* if set, hang on writes if not active */
+ short relsig; /* signal to raise on release req */
+ short acqsig; /* signal to raise on acquisition */
+ short frsig; /* unused (set to 0) */
+};
+#define VT_GETMODE 0x5601 /* get mode of active vt */
+#define VT_SETMODE 0x5602 /* set mode of active vt */
+#define VT_AUTO 0x00 /* auto vt switching */
+#define VT_PROCESS 0x01 /* process controls switching */
+#define VT_ACKACQ 0x02 /* acknowledge switch */
+
+struct vt_stat {
+ unsigned short v_active; /* active vt */
+ unsigned short v_signal; /* signal to send */
+ unsigned short v_state; /* vt bitmask */
+};
+#define VT_GETSTATE 0x5603 /* get global vt state info */
+#define VT_SENDSIG 0x5604 /* signal to send to bitmask of vts */
+
+#define VT_RELDISP 0x5605 /* release display */
+
+#define VT_ACTIVATE 0x5606 /* make vt active */
+#define VT_WAITACTIVE 0x5607 /* wait for vt active */
+#define VT_DISALLOCATE 0x5608 /* free memory associated to vt */
+
+struct vt_sizes {
+ unsigned short v_rows; /* number of rows */
+ unsigned short v_cols; /* number of columns */
+ unsigned short v_scrollsize; /* number of lines of scrollback */
+};
+#define VT_RESIZE 0x5609 /* set kernel's idea of screensize */
+
+struct vt_consize {
+ unsigned short v_rows; /* number of rows */
+ unsigned short v_cols; /* number of columns */
+ unsigned short v_vlin; /* number of pixel rows on screen */
+ unsigned short v_clin; /* number of pixel rows per character */
+ unsigned short v_vcol; /* number of pixel columns on screen */
+ unsigned short v_ccol; /* number of pixel columns per character */
+};
+#define VT_RESIZEX 0x560A /* set kernel's idea of screensize + more */
+#define VT_LOCKSWITCH 0x560B /* disallow vt switching */
+#define VT_UNLOCKSWITCH 0x560C /* allow vt switching */
+
+#endif /* _LINUX_VT_H */
diff --git a/pfinet/linux-src/include/linux/vt_buffer.h b/pfinet/linux-src/include/linux/vt_buffer.h
new file mode 100644
index 00000000..ca1ec519
--- /dev/null
+++ b/pfinet/linux-src/include/linux/vt_buffer.h
@@ -0,0 +1,83 @@
+/*
+ * include/linux/vt_buffer.h -- Access to VT screen buffer
+ *
+ * (c) 1998 Martin Mares <mj@ucw.cz>
+ *
+ * This is a set of macros and functions which are used in the
+ * console driver and related code to access the screen buffer.
+ * In most cases the console works with simple in-memory buffer,
+ * but when handling hardware text mode consoles, we store
+ * the foreground console directly in video memory.
+ */
+
+#ifndef _LINUX_VT_BUFFER_H_
+#define _LINUX_VT_BUFFER_H_
+
+#include <linux/config.h>
+
+#ifdef CONFIG_VGA_CONSOLE
+#include <asm/vga.h>
+#endif
+
+#ifndef VT_BUF_HAVE_RW
+#define scr_writew(val, addr) (*(addr) = (val))
+#define scr_readw(addr) (*(addr))
+#define scr_memcpyw(d, s, c) memcpy(d, s, c)
+#define scr_memmovew(d, s, c) memmove(d, s, c)
+#define VT_BUF_HAVE_MEMCPYW
+#define VT_BUF_HAVE_MEMMOVEW
+#define scr_memcpyw_from(d, s, c) memcpy(d, s, c)
+#define scr_memcpyw_to(d, s, c) memcpy(d, s, c)
+#define VT_BUF_HAVE_MEMCPYF
+#endif
+
+#ifndef VT_BUF_HAVE_MEMSETW
+extern inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
+{
+ count /= 2;
+ while (count--)
+ scr_writew(c, s++);
+}
+#endif
+
+#ifndef VT_BUF_HAVE_MEMCPYW
+extern inline void scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
+{
+ count /= 2;
+ while (count--)
+ scr_writew(scr_readw(s++), d++);
+}
+#endif
+
+#ifndef VT_BUF_HAVE_MEMMOVEW
+extern inline void scr_memmovew(u16 *d, const u16 *s, unsigned int count)
+{
+ if (d < s)
+ scr_memcpyw(d, s, count);
+ else {
+ count /= 2;
+ d += count;
+ s += count;
+ while (count--)
+ scr_writew(scr_readw(--s), --d);
+ }
+}
+#endif
+
+#ifndef VT_BUF_HAVE_MEMCPYF
+extern inline void scr_memcpyw_from(u16 *d, const u16 *s, unsigned int count)
+{
+ count /= 2;
+ while (count--)
+ *d++ = scr_readw(s++);
+}
+
+extern inline void scr_memcpyw_to(u16 *d, const u16 *s, unsigned int count)
+{
+ count /= 2;
+ while (count--)
+ scr_writew(*s++, d++);
+}
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/vt_kern.h b/pfinet/linux-src/include/linux/vt_kern.h
new file mode 100644
index 00000000..e1b72768
--- /dev/null
+++ b/pfinet/linux-src/include/linux/vt_kern.h
@@ -0,0 +1,94 @@
+#ifndef _VT_KERN_H
+#define _VT_KERN_H
+
+/*
+ * this really is an extension of the vc_cons structure in console.c, but
+ * with information needed by the vt package
+ */
+
+#include <linux/config.h>
+#include <linux/vt.h>
+
+/*
+ * Presently, a lot of graphics programs do not restore the contents of
+ * the higher font pages. Defining this flag will avoid use of them, but
+ * will lose support for PIO_FONTRESET. Note that many font operations are
+ * not likely to work with these programs anyway; they need to be
+ * fixed. The linux/Documentation directory includes a code snippet
+ * to save and restore the text font.
+ */
+#ifdef CONFIG_VGA_CONSOLE
+#define BROKEN_GRAPHICS_PROGRAMS 1
+#endif
+
+extern struct vt_struct {
+ int vc_num; /* The console number */
+ unsigned char vc_mode; /* KD_TEXT, ... */
+ struct vt_mode vt_mode;
+ int vt_pid;
+ int vt_newvt;
+ struct wait_queue *paste_wait;
+} *vt_cons[MAX_NR_CONSOLES];
+
+void (*kd_mksound)(unsigned int hz, unsigned int ticks);
+
+/* console.c */
+
+struct console_font_op;
+struct consw;
+
+int vc_allocate(unsigned int console);
+int vc_cons_allocated(unsigned int console);
+int vc_resize(unsigned int lines, unsigned int cols,
+ unsigned int first, unsigned int last);
+#define vc_resize_all(l, c) vc_resize(l, c, 0, MAX_NR_CONSOLES-1)
+#define vc_resize_con(l, c, x) vc_resize(l, c, x, x)
+void vc_disallocate(unsigned int console);
+void reset_palette(int currcons);
+void set_palette(int currcons);
+void do_blank_screen(int gfx_mode);
+void unblank_screen(void);
+void poke_blanked_console(void);
+int con_font_op(int currcons, struct console_font_op *op);
+int con_set_cmap(unsigned char *cmap);
+int con_get_cmap(unsigned char *cmap);
+void scrollback(int);
+void scrollfront(int);
+void update_region(int currcons, unsigned long start, int count);
+void redraw_screen(int new_console, int is_switch);
+#define update_screen(x) redraw_screen(x, 0)
+#define switch_screen(x) redraw_screen(x, 1)
+
+struct tty_struct;
+int tioclinux(struct tty_struct *tty, unsigned long arg);
+
+/* consolemap.c */
+
+struct unimapinit;
+struct unipair;
+
+int con_set_trans_old(unsigned char * table);
+int con_get_trans_old(unsigned char * table);
+int con_set_trans_new(unsigned short * table);
+int con_get_trans_new(unsigned short * table);
+int con_clear_unimap(int currcons, struct unimapinit *ui);
+int con_set_unimap(int currcons, ushort ct, struct unipair *list);
+int con_get_unimap(int currcons, ushort ct, ushort *uct, struct unipair *list);
+int con_set_default_unimap(int currcons);
+void con_free_unimap(int currcons);
+void con_protect_unimap(int currcons, int rdonly);
+int con_copy_unimap(int dstcons, int srccons);
+
+/* vt.c */
+
+extern unsigned int video_font_height;
+extern unsigned int default_font_height;
+extern unsigned int video_scan_lines;
+
+void complete_change_console(unsigned int new_console);
+int vt_waitactive(int vt);
+void change_console(unsigned int);
+void reset_vc(unsigned int new_console);
+int vt_waitactive(int vt);
+
+#endif /* _VT_KERN_H */
diff --git a/pfinet/linux-src/include/linux/wait.h b/pfinet/linux-src/include/linux/wait.h
new file mode 100644
index 00000000..6514693c
--- /dev/null
+++ b/pfinet/linux-src/include/linux/wait.h
@@ -0,0 +1,33 @@
+#ifndef _LINUX_WAIT_H
+#define _LINUX_WAIT_H
+
+#define WNOHANG 0x00000001
+#define WUNTRACED 0x00000002
+
+#define __WCLONE 0x80000000
+
+#ifdef __KERNEL__
+
+#include <asm/page.h>
+
+struct wait_queue {
+ struct task_struct * task;
+ struct wait_queue * next;
+};
+
+#define WAIT_QUEUE_HEAD(x) ((struct wait_queue *)((x)-1))
+
+static inline void init_waitqueue(struct wait_queue **q)
+{
+ *q = WAIT_QUEUE_HEAD(q);
+}
+
+static inline int waitqueue_active(struct wait_queue **q)
+{
+ struct wait_queue *head = *q;
+ return head && head != WAIT_QUEUE_HEAD(q);
+}
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/pfinet/linux-src/include/linux/wanpipe.h b/pfinet/linux-src/include/linux/wanpipe.h
new file mode 100644
index 00000000..aa3cb84a
--- /dev/null
+++ b/pfinet/linux-src/include/linux/wanpipe.h
@@ -0,0 +1,218 @@
+/*****************************************************************************
+* wanpipe.h WANPIPE(tm) Multiprotocol WAN Link Driver.
+* User-level API definitions.
+*
+* Author: Gene Kozin <genek@compuserve.com>
+* Jaspreet Singh <jaspreet@sangoma.com>
+*
+* Copyright: (c) 1995-1997 Sangoma Technologies Inc.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version
+* 2 of the License, or (at your option) any later version.
+* ============================================================================
+* Nov 26, 1997 Jaspreet Singh Added 'load_sharing' structure. Also added
+* 'devs_struct','dev_to_devtint_next' to 'sdla_t'
+* Nov 24, 1997 Jaspreet Singh Added 'irq_dis_if_send_count',
+* 'irq_dis_poll_count' to 'sdla_t'.
+* Nov 06, 1997 Jaspreet Singh Added a define called 'INTR_TEST_MODE'
+* Oct 20, 1997 Jaspreet Singh Added 'buff_intr_mode_unbusy' and
+* 'dlci_intr_mode_unbusy' to 'sdla_t'
+* Oct 18, 1997 Jaspreet Singh Added structure to maintain global driver
+* statistics.
+* Jan 15, 1997 Gene Kozin Version 3.1.0
+* o added UDP management stuff
+* Jan 02, 1997 Gene Kozin Version 3.0.0
+*****************************************************************************/
+#ifndef _WANPIPE_H
+#define _WANPIPE_H
+
+#include <linux/wanrouter.h>
+
+/* Defines */
+
+#ifndef PACKED
+#define PACKED __attribute__((packed))
+#endif
+
+#define WANPIPE_MAGIC 0x414C4453L /* signatire: 'SDLA' reversed */
+
+/* IOCTL numbers (up to 16) */
+#define WANPIPE_DUMP (ROUTER_USER+0) /* dump adapter's memory */
+#define WANPIPE_EXEC (ROUTER_USER+1) /* execute firmware command */
+
+/*
+ * Data structures for IOCTL calls.
+ */
+
+typedef struct sdla_dump /* WANPIPE_DUMP */
+{
+ unsigned long magic; /* for verification */
+ unsigned long offset; /* absolute adapter memory address */
+ unsigned long length; /* block length */
+ void* ptr; /* -> buffer */
+} sdla_dump_t;
+
+typedef struct sdla_exec /* WANPIPE_EXEC */
+{
+ unsigned long magic; /* for verification */
+ void* cmd; /* -> command structure */
+ void* data; /* -> data buffer */
+} sdla_exec_t;
+
+/* UDP management stuff */
+
+typedef struct wum_header
+{
+ unsigned char signature[8]; /* 00h: signature */
+ unsigned char type; /* 08h: request/reply */
+ unsigned char command; /* 09h: commnand */
+ unsigned char reserved[6]; /* 0Ah: reserved */
+} wum_header_t;
+
+/*************************************************************************
+ Data Structure for global statistics
+*************************************************************************/
+
+typedef struct global_stats
+{
+ unsigned long isr_entry;
+ unsigned long isr_already_critical;
+ unsigned long isr_rx;
+ unsigned long isr_tx;
+ unsigned long isr_intr_test;
+ unsigned long isr_spurious;
+ unsigned long isr_enable_tx_int;
+ unsigned long rx_intr_corrupt_rx_bfr;
+ unsigned long rx_intr_on_orphaned_DLCI;
+ unsigned long rx_intr_dev_not_started;
+ unsigned long tx_intr_dev_not_started;
+ unsigned long poll_entry;
+ unsigned long poll_already_critical;
+ unsigned long poll_processed;
+ unsigned long poll_tbusy_bad_status;
+ unsigned long poll_host_disable_irq;
+ unsigned long poll_host_enable_irq;
+
+} global_stats_t;
+
+/* This structure is used for maitaining a circular linked list of all
+ * interfaces(devices) per card. It is used in the Interrupt Service routine
+ * for a transmit interrupt where the start of the loop to dev_tint all
+ * interfaces changes.
+ */
+typedef struct load_sharing
+{
+ struct device* dev_ptr;
+ struct load_sharing* next;
+} load_sharing_t;
+
+/* This is used for interrupt testing */
+#define INTR_TEST_MODE 0x02
+
+#define WUM_SIGNATURE_L 0x50495046
+#define WUM_SIGNATURE_H 0x444E3845
+
+#define WUM_KILL 0x50
+#define WUM_EXEC 0x51
+
+#ifdef __KERNEL__
+/****** Kernel Interface ****************************************************/
+
+#include <linux/sdladrv.h> /* SDLA support module API definitions */
+#include <linux/sdlasfm.h> /* SDLA firmware module definitions */
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#define is_digit(ch) (((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')?1:0)
+#define is_alpha(ch) ((((ch)>=(unsigned)'a'&&(ch)<=(unsigned)'z')||\
+ ((ch)>=(unsigned)'A'&&(ch)<=(unsigned)'Z'))?1:0)
+#define is_hex_digit(ch) ((((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')||\
+ ((ch)>=(unsigned)'a'&&(ch)<=(unsigned)'f')||\
+ ((ch)>=(unsigned)'A'&&(ch)<=(unsigned)'F'))?1:0)
+
+/****** Data Structures *****************************************************/
+
+/* Adapter Data Space.
+ * This structure is needed because we handle multiple cards, otherwise
+ * static data would do it.
+ */
+typedef struct sdla
+{
+ char devname[WAN_DRVNAME_SZ+1]; /* card name */
+ sdlahw_t hw; /* hardware configuration */
+ wan_device_t wandev; /* WAN device data space */
+ unsigned open_cnt; /* number of open interfaces */
+ unsigned long state_tick; /* link state timestamp */
+ unsigned intr_mode; /* Type of Interrupt Mode */
+ char in_isr; /* interrupt-in-service flag */
+ char buff_int_mode_unbusy; /* flag for carrying out dev_tint */
+ char dlci_int_mode_unbusy; /* flag for carrying out dev_tint */
+ unsigned short irq_dis_if_send_count; /* Disabling irqs in if_send*/
+ unsigned short irq_dis_poll_count; /* Disabling irqs in poll routine*/
+ global_stats_t statistics; /* global statistics */
+
+ /* The following is used as a pointer to the structure in our
+ circular linked list which changes the start of the loop for
+ dev_tint of all interfaces */
+
+ load_sharing_t* dev_to_devtint_next;
+ load_sharing_t* devs_struct;
+
+ void* mbox; /* -> mailbox */
+ void* rxmb; /* -> receive mailbox */
+ void* flags; /* -> adapter status flags */
+ void (*isr)(struct sdla* card); /* interrupt service routine */
+ void (*poll)(struct sdla* card); /* polling routine */
+ int (*exec)(struct sdla* card, void* u_cmd, void* u_data);
+ union
+ {
+ struct
+ { /****** X.25 specific data **********/
+ unsigned lo_pvc;
+ unsigned hi_pvc;
+ unsigned lo_svc;
+ unsigned hi_svc;
+ } x;
+ struct
+ { /****** frame relay specific data ***/
+ void* rxmb_base; /* -> first Rx buffer */
+ void* rxmb_last; /* -> last Rx buffer */
+ unsigned rx_base; /* S508 receive buffer base */
+ unsigned rx_top; /* S508 receive buffer end */
+ unsigned short node_dlci[100];
+ unsigned short dlci_num;
+ } f;
+ struct /****** PPP-specific data ***********/
+ {
+ char if_name[WAN_IFNAME_SZ+1]; /* interface name */
+ void* txbuf; /* -> current Tx buffer */
+ void* txbuf_base; /* -> first Tx buffer */
+ void* txbuf_last; /* -> last Tx buffer */
+ void* rxbuf_base; /* -> first Rx buffer */
+ void* rxbuf_last; /* -> last Rx buffer */
+ unsigned rx_base; /* S508 receive buffer base */
+ unsigned rx_top; /* S508 receive buffer end */
+ } p;
+ } u;
+} sdla_t;
+
+/****** Public Functions ****************************************************/
+
+void wanpipe_open (sdla_t* card); /* wpmain.c */
+void wanpipe_close (sdla_t* card); /* wpmain.c */
+void wanpipe_set_state (sdla_t* card, int state); /* wpmain.c */
+
+int wpx_init (sdla_t* card, wandev_conf_t* conf); /* wpx.c */
+int wpf_init (sdla_t* card, wandev_conf_t* conf); /* wpf.c */
+int wpp_init (sdla_t* card, wandev_conf_t* conf); /* wpp.c */
+
+#endif /* __KERNEL__ */
+#endif /* _WANPIPE_H */
+
diff --git a/pfinet/linux-src/include/linux/wanrouter.h b/pfinet/linux-src/include/linux/wanrouter.h
new file mode 100644
index 00000000..fd63868f
--- /dev/null
+++ b/pfinet/linux-src/include/linux/wanrouter.h
@@ -0,0 +1,381 @@
+/*****************************************************************************
+* router.h Definitions for the WAN Multiprotocol Router Module.
+* This module provides API and common services for WAN Link
+* Drivers and is completely hardware-independent.
+*
+* Author: Gene Kozin <genek@compuserve.com>
+* Jaspreet Singh <jaspreet@sangoma.com>
+*
+* Copyright: (c) 1995-1997 Sangoma Technologies Inc.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version
+* 2 of the License, or (at your option) any later version.
+* ============================================================================
+* Nov 06, 1997 Jaspreet Singh Changed Router Driver version to 1.1 from 1.0
+* Oct 20, 1997 Jaspreet Singh Added 'cir','bc','be' and 'mc' to 'wanif_conf_t'
+* Added 'enable_IPX' and 'network_number' to
+* 'wan_device_t'. Also added defines for
+* UDP PACKET TYPE, Interrupt test, critical values* for RACE conditions.
+* Oct 05, 1997 Jaspreet Singh Added 'dlci_num' and 'dlci[100]' to
+* 'wan_fr_conf_t' to configure a list of dlci(s)
+* for a NODE
+* Jul 07, 1997 Jaspreet Singh Added 'ttl' to 'wandev_conf_t' & 'wan_device_t'
+* May 29, 1997 Jaspreet Singh Added 'tx_int_enabled' to 'wan_device_t'
+* May 21, 1997 Jaspreet Singh Added 'udp_port' to 'wan_device_t'
+* Apr 25, 1997 Farhan Thawar Added 'udp_port' to 'wandev_conf_t'
+* Jan 16, 1997 Gene Kozin router_devlist made public
+* Jan 02, 1997 Gene Kozin Initial version (based on wanpipe.h).
+*****************************************************************************/
+#ifndef _ROUTER_H
+#define _ROUTER_H
+
+#define ROUTER_NAME "wanrouter" /* in case we ever change it */
+#define ROUTER_VERSION 1 /* version number */
+#define ROUTER_RELEASE 1 /* release (minor version) number */
+#define ROUTER_IOCTL 'W' /* for IOCTL calls */
+#define ROUTER_MAGIC 0x524D4157L /* signature: 'WANR' reversed */
+
+/* IOCTL codes for /proc/router/<device> entries (up to 255) */
+enum router_ioctls
+{
+ ROUTER_SETUP = ROUTER_IOCTL<<8, /* configure device */
+ ROUTER_DOWN, /* shut down device */
+ ROUTER_STAT, /* get device status */
+ ROUTER_IFNEW, /* add interface */
+ ROUTER_IFDEL, /* delete interface */
+ ROUTER_IFSTAT, /* get interface status */
+ ROUTER_USER = (ROUTER_IOCTL<<8)+16, /* driver-specific calls */
+ ROUTER_USER_MAX = (ROUTER_IOCTL<<8)+31
+};
+
+/* NLPID for packet encapsulation (ISO/IEC TR 9577) */
+#define NLPID_IP 0xCC /* Internet Protocol Datagram */
+#define NLPID_SNAP 0x80 /* IEEE Subnetwork Access Protocol */
+#define NLPID_CLNP 0x81 /* ISO/IEC 8473 */
+#define NLPID_ESIS 0x82 /* ISO/IEC 9542 */
+#define NLPID_ISIS 0x83 /* ISO/IEC ISIS */
+#define NLPID_Q933 0x08 /* CCITT Q.933 */
+
+/* Miscellaneous */
+#define WAN_IFNAME_SZ 15 /* max length of the interface name */
+#define WAN_DRVNAME_SZ 15 /* max length of the link driver name */
+#define WAN_ADDRESS_SZ 31 /* max length of the WAN media address */
+
+/* Defines for UDP PACKET TYPE */
+#define UDP_PTPIPE_TYPE 0x01
+#define UDP_FPIPE_TYPE 0x02
+#define UDP_DRVSTATS_TYPE 0x03
+#define UDP_INVALID_TYPE 0x04
+
+/* Command return code */
+#define CMD_OK 0 /* normal firmware return code */
+#define CMD_TIMEOUT 0xFF /* firmware command timed out */
+
+/* UDP Packet Management */
+#define UDP_PKT_FRM_STACK 0x00
+#define UDP_PKT_FRM_NETWORK 0x01
+
+/* Maximum interrupt test counter */
+#define MAX_INTR_TEST_COUNTER 100
+
+/* Critical Values for RACE conditions*/
+#define CRITICAL_IN_ISR 0xA1
+#define CRITICAL_INTR_HANDLED 0xB1
+
+/****** Data Types **********************************************************/
+
+/*----------------------------------------------------------------------------
+ * X.25-specific link-level configuration.
+ */
+typedef struct wan_x25_conf
+{
+ unsigned lo_pvc; /* lowest permanent circuit number */
+ unsigned hi_pvc; /* highest permanent circuit number */
+ unsigned lo_svc; /* lowest switched circuit number */
+ unsigned hi_svc; /* highest switched circuit number */
+ unsigned hdlc_window; /* HDLC window size (1..7) */
+ unsigned pkt_window; /* X.25 packet window size (1..7) */
+ unsigned t1; /* HDLC timer T1, sec (1..30) */
+ unsigned t2; /* HDLC timer T2, sec (0..29) */
+ unsigned t4; /* HDLC supervisory frame timer = T4 * T1 */
+ unsigned n2; /* HDLC retransmission limit (1..30) */
+ unsigned t10_t20; /* X.25 RESTART timeout, sec (1..255) */
+ unsigned t11_t21; /* X.25 CALL timeout, sec (1..255) */
+ unsigned t12_t22; /* X.25 RESET timeout, sec (1..255) */
+ unsigned t13_t23; /* X.25 CLEAR timeout, sec (1..255) */
+ unsigned t16_t26; /* X.25 INTERRUPT timeout, sec (1..255) */
+ unsigned t28; /* X.25 REGISTRATION timeout, sec (1..255) */
+ unsigned r10_r20; /* RESTART retransmission limit (0..250) */
+ unsigned r12_r22; /* RESET retransmission limit (0..250) */
+ unsigned r13_r23; /* CLEAR retransmission limit (0..250) */
+ unsigned ccitt_compat; /* compatibility mode: 1988/1984/1980 */
+} wan_x25_conf_t;
+
+/*----------------------------------------------------------------------------
+ * Frame relay specific link-level configuration.
+ */
+typedef struct wan_fr_conf
+{
+ unsigned signalling; /* local in-channel signalling type */
+ unsigned t391; /* link integrity verification timer */
+ unsigned t392; /* polling verification timer */
+ unsigned n391; /* full status polling cycle counter */
+ unsigned n392; /* error threshold counter */
+ unsigned n393; /* monitored events counter */
+ unsigned dlci_num; /* number of DLCs (access node) */
+ unsigned dlci[100]; /* List of all DLCIs */
+} wan_fr_conf_t;
+
+/*----------------------------------------------------------------------------
+ * PPP-specific link-level configuration.
+ */
+typedef struct wan_ppp_conf
+{
+ unsigned restart_tmr; /* restart timer */
+ unsigned auth_rsrt_tmr; /* authentication timer */
+ unsigned auth_wait_tmr; /* authentication timer */
+ unsigned mdm_fail_tmr; /* modem failure timer */
+ unsigned dtr_drop_tmr; /* DTR drop timer */
+ unsigned connect_tmout; /* connection timeout */
+ unsigned conf_retry; /* max. retry */
+ unsigned term_retry; /* max. retry */
+ unsigned fail_retry; /* max. retry */
+ unsigned auth_retry; /* max. retry */
+ unsigned auth_options; /* authentication opt. */
+ unsigned ip_options; /* IP options */
+} wan_ppp_conf_t;
+
+/*----------------------------------------------------------------------------
+ * WAN device configuration. Passed to ROUTER_SETUP IOCTL.
+ */
+typedef struct wandev_conf
+{
+ unsigned magic; /* magic number (for verification) */
+ unsigned config_id; /* configuration structure identifier */
+ /****** hardware configuration ******/
+ unsigned ioport; /* adapter I/O port base */
+ unsigned long maddr; /* dual-port memory address */
+ unsigned msize; /* dual-port memory size */
+ int irq; /* interrupt request level */
+ int dma; /* DMA request level */
+ unsigned bps; /* data transfer rate */
+ unsigned mtu; /* maximum transmit unit size */
+ unsigned udp_port; /* UDP port for management */
+ unsigned char ttl; /* Time To Live for UDP security */
+ char interface; /* RS-232/V.35, etc. */
+ char clocking; /* external/internal */
+ char line_coding; /* NRZ/NRZI/FM0/FM1, etc. */
+ char station; /* DTE/DCE, primary/secondary, etc. */
+ char connection; /* permanent/switched/on-demand */
+ unsigned hw_opt[4]; /* other hardware options */
+ unsigned char enable_IPX; /* Enable or Disable IPX */
+ unsigned long network_number; /* Network Number for IPX */
+ unsigned reserved[4];
+ /****** arbitrary data ***************/
+ unsigned data_size; /* data buffer size */
+ void* data; /* data buffer, e.g. firmware */
+ union /****** protocol-specific ************/
+ {
+ wan_x25_conf_t x25; /* X.25 configuration */
+ wan_ppp_conf_t ppp; /* PPP configuration */
+ wan_fr_conf_t fr; /* frame relay configuration */
+ } u;
+} wandev_conf_t;
+
+/* 'config_id' definitions */
+#define WANCONFIG_X25 101 /* X.25 link */
+#define WANCONFIG_FR 102 /* frame relay link */
+#define WANCONFIG_PPP 103 /* synchronous PPP link */
+
+/*
+ * Configuration options defines.
+ */
+/* general options */
+#define WANOPT_OFF 0
+#define WANOPT_ON 1
+#define WANOPT_NO 0
+#define WANOPT_YES 1
+
+/* intercace options */
+#define WANOPT_RS232 0
+#define WANOPT_V35 1
+
+/* data encoding options */
+#define WANOPT_NRZ 0
+#define WANOPT_NRZI 1
+#define WANOPT_FM0 2
+#define WANOPT_FM1 3
+
+/* link type options */
+#define WANOPT_POINTTOPOINT 0 /* RTS always active */
+#define WANOPT_MULTIDROP 1 /* RTS is active when transmitting */
+
+/* clocking options */
+#define WANOPT_EXTERNAL 0
+#define WANOPT_INTERNAL 1
+
+/* station options */
+#define WANOPT_DTE 0
+#define WANOPT_DCE 1
+#define WANOPT_CPE 0
+#define WANOPT_NODE 1
+#define WANOPT_SECONDARY 0
+#define WANOPT_PRIMARY 1
+
+/* connection options */
+#define WANOPT_PERMANENT 0 /* DTR always active */
+#define WANOPT_SWITCHED 1 /* use DTR to setup link (dial-up) */
+#define WANOPT_ONDEMAND 2 /* activate DTR only before sending */
+
+/* frame relay in-channel signalling */
+#define WANOPT_FR_ANSI 0 /* ANSI T1.617 Annex D */
+#define WANOPT_FR_Q933 1 /* ITU Q.933A */
+#define WANOPT_FR_LMI 2 /* LMI */
+
+/*----------------------------------------------------------------------------
+ * WAN Link Status Info (for ROUTER_STAT IOCTL).
+ */
+typedef struct wandev_stat
+{
+ unsigned state; /* link state */
+ unsigned ndev; /* number of configured interfaces */
+
+ /* link/interface configuration */
+ unsigned connection; /* permanent/switched/on-demand */
+ unsigned media_type; /* Frame relay/PPP/X.25/SDLC, etc. */
+ unsigned mtu; /* max. transmit unit for this device */
+
+ /* physical level statistics */
+ unsigned modem_status; /* modem status */
+ unsigned rx_frames; /* received frames count */
+ unsigned rx_overruns; /* receiver overrun error count */
+ unsigned rx_crc_err; /* receive CRC error count */
+ unsigned rx_aborts; /* received aborted frames count */
+ unsigned rx_bad_length; /* unexpetedly long/short frames count */
+ unsigned rx_dropped; /* frames discarded at device level */
+ unsigned tx_frames; /* transmitted frames count */
+ unsigned tx_underruns; /* aborted transmissions (underruns) count */
+ unsigned tx_timeouts; /* transmission timeouts */
+ unsigned tx_rejects; /* other transmit errors */
+
+ /* media level statistics */
+ unsigned rx_bad_format; /* frames with invalid format */
+ unsigned rx_bad_addr; /* frames with invalid media address */
+ unsigned tx_retries; /* frames re-transmitted */
+ unsigned reserved[16]; /* reserved for future use */
+} wandev_stat_t;
+
+/* 'state' defines */
+enum wan_states
+{
+ WAN_UNCONFIGURED, /* link/channel is not configured */
+ WAN_DISCONNECTED, /* link/channel is disconnected */
+ WAN_CONNECTING, /* connection is in progress */
+ WAN_CONNECTED, /* link/channel is operational */
+ WAN_LIMIT /* for verification only */
+};
+
+/* 'modem_status' masks */
+#define WAN_MODEM_CTS 0x0001 /* CTS line active */
+#define WAN_MODEM_DCD 0x0002 /* DCD line active */
+#define WAN_MODEM_DTR 0x0010 /* DTR line active */
+#define WAN_MODEM_RTS 0x0020 /* RTS line active */
+
+/*----------------------------------------------------------------------------
+ * WAN interface (logical channel) configuration (for ROUTER_IFNEW IOCTL).
+ */
+typedef struct wanif_conf
+{
+ unsigned magic; /* magic number */
+ unsigned config_id; /* configuration identifier */
+ char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
+ char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
+ unsigned idle_timeout; /* sec, before disconnecting */
+ unsigned hold_timeout; /* sec, before re-connecting */
+ unsigned cir; /* Committed Information Rate fwd,bwd*/
+ unsigned bc; /* Committed Burst Size fwd, bwd */
+ unsigned be; /* Excess Burst Size fwd, bwd */
+ char mc; /* Multicast on or off */
+ int reserved[8]; /* reserved for future extensions */
+} wanif_conf_t;
+
+#ifdef __KERNEL__
+/****** Kernel Interface ****************************************************/
+
+#include <linux/fs.h> /* support for device drivers */
+#include <linux/proc_fs.h> /* proc filesystem pragmatics */
+#include <linux/inet.h> /* in_aton(), in_ntoa() prototypes */
+#include <linux/netdevice.h> /* support for network drivers */
+
+/*----------------------------------------------------------------------------
+ * WAN device data space.
+ */
+typedef struct wan_device
+{
+ unsigned magic; /* magic number */
+ char* name; /* -> WAN device name (ASCIIZ) */
+ void* private; /* -> driver private data */
+ /****** hardware configuration ******/
+ unsigned ioport; /* adapter I/O port base #1 */
+ void * maddr; /* dual-port memory address */
+ unsigned msize; /* dual-port memory size */
+ int irq; /* interrupt request level */
+ int dma; /* DMA request level */
+ unsigned bps; /* data transfer rate */
+ unsigned mtu; /* max physical transmit unit size */
+ unsigned udp_port; /* UDP port for management */
+ unsigned char ttl; /* Time To Live for UDP security */
+ unsigned enable_tx_int; /* Transmit Interrupt enabled or not */
+ char interface; /* RS-232/V.35, etc. */
+ char clocking; /* external/internal */
+ char line_coding; /* NRZ/NRZI/FM0/FM1, etc. */
+ char station; /* DTE/DCE, primary/secondary, etc. */
+ char connection; /* permanent/switched/on-demand */
+ unsigned hw_opt[4]; /* other hardware options */
+ unsigned char enable_IPX; /* Enable or Disable IPX */
+ unsigned long network_number; /* Network Number for IPX */
+ /****** status and statistics *******/
+ char state; /* device state */
+ unsigned modem_status; /* modem status */
+ struct enet_statistics stats; /* interface statistics */
+ unsigned reserved[16]; /* reserved for future use */
+ unsigned critical; /* critical section flag */
+ /****** device management methods ***/
+ int (*setup) (struct wan_device* wandev, wandev_conf_t* conf);
+ int (*shutdown) (struct wan_device* wandev);
+ int (*update) (struct wan_device* wandev);
+ int (*ioctl) (struct wan_device* wandev, unsigned cmd,
+ unsigned long arg);
+ int (*new_if) (struct wan_device* wandev, struct device* dev,
+ wanif_conf_t* conf);
+ int (*del_if) (struct wan_device* wandev, struct device* dev);
+ /****** maintained by the router ****/
+ struct wan_device* next; /* -> next device */
+ struct device* dev; /* list of network interfaces */
+ unsigned ndev; /* number of interfaces */
+ struct proc_dir_entry dent; /* proc filesystem entry */
+} wan_device_t;
+
+/* Public functions available for device drivers */
+extern int register_wan_device(wan_device_t* wandev);
+extern int unregister_wan_device(char* name);
+unsigned short wanrouter_type_trans(struct sk_buff* skb, struct device* dev);
+int wanrouter_encapsulate(struct sk_buff* skb, struct device* dev);
+
+/* Proc interface functions. These must not be called by the drivers! */
+extern int wanrouter_proc_init (void);
+extern void wanrouter_proc_cleanup (void);
+extern int wanrouter_proc_add (wan_device_t* wandev);
+extern int wanrouter_proc_delete (wan_device_t* wandev);
+extern int wanrouter_ioctl(
+ struct inode* inode, struct file* file,
+ unsigned int cmd, unsigned long arg)
+;
+
+/* Public Data */
+extern wan_device_t* router_devlist; /* list of registered devices */
+
+#endif /* __KERNEL__ */
+#endif /* _ROUTER_H */
diff --git a/pfinet/linux-src/include/linux/watchdog.h b/pfinet/linux-src/include/linux/watchdog.h
new file mode 100644
index 00000000..3f358258
--- /dev/null
+++ b/pfinet/linux-src/include/linux/watchdog.h
@@ -0,0 +1,40 @@
+/*
+ * Generic watchdog defines. Derived from..
+ *
+ * Berkshire PC Watchdog Defines
+ * by Ken Hollis <khollis@bitgate.com>
+ *
+ */
+
+#include <linux/ioctl.h>
+
+#define WATCHDOG_IOCTL_BASE 'W'
+
+struct watchdog_info {
+ u32 options; /* Options the card/driver supports */
+ u32 firmware_version; /* Firmware version of the card */
+ u8 identity[32]; /* Identity of the board */
+};
+
+#define WDIOC_GETSUPPORT _IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
+#define WDIOC_GETSTATUS _IOR(WATCHDOG_IOCTL_BASE, 1, int)
+#define WDIOC_GETBOOTSTATUS _IOR(WATCHDOG_IOCTL_BASE, 2, int)
+#define WDIOC_GETTEMP _IOR(WATCHDOG_IOCTL_BASE, 3, int)
+#define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int)
+#define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int)
+
+#define WDIOF_UNKNOWN -1 /* Unknown flag error */
+#define WDIOS_UNKNOWN -1 /* Unknown status error */
+
+#define WDIOF_OVERHEAT 0x0001 /* Reset due to CPU overheat */
+#define WDIOF_FANFAULT 0x0002 /* Fan failed */
+#define WDIOF_EXTERN1 0x0004 /* External relay 1 */
+#define WDIOF_EXTERN2 0x0008 /* External relay 2 */
+#define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */
+#define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */
+#define WDIOF_POWEROVER 0x0040 /* Power over voltage */
+#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */
+
+#define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */
+#define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */
+#define WDIOS_TEMPPANIC 0x0004 /* Kernel panic on temperature trip */
diff --git a/pfinet/linux-src/include/linux/wavefront.h b/pfinet/linux-src/include/linux/wavefront.h
new file mode 100644
index 00000000..f96c52d0
--- /dev/null
+++ b/pfinet/linux-src/include/linux/wavefront.h
@@ -0,0 +1,675 @@
+#ifndef __wavefront_h__
+#define __wavefront_h__
+
+/* WaveFront header file.
+ *
+ * Copyright (C) by Paul Barton-Davis 1998
+ *
+ * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
+ */
+
+#if (!defined(__GNUC__) && !defined(__GNUG__))
+
+ You will not be able to compile this file correctly without gcc, because
+ it is necessary to pack the "wavefront_alias" structure to a size
+ of 22 bytes, corresponding to 16-bit alignment (as would have been
+ the case on the original platform, MS-DOS). If this is not done,
+ then WavePatch-format files cannot be read/written correctly.
+ The method used to do this here ("__attribute__((packed)") is
+ completely compiler dependent.
+
+ All other wavefront_* types end up aligned to 32 bit values and
+ still have the same (correct) size.
+
+#else
+
+ /* However, note that as of G++ 2.7.3.2, g++ was unable to
+ correctly parse *type* __attribute__ tags. It will do the
+ right thing if we use the "packed" attribute on each struct
+ member, which has the same semantics anyway.
+ */
+
+#endif __GNUC__
+
+/***************************** WARNING ********************************
+ PLEASE DO NOT MODIFY THIS FILE IN ANY WAY THAT AFFECTS ITS ABILITY TO
+ BE USED WITH EITHER C *OR* C++.
+ **********************************************************************/
+
+#ifndef NUM_MIDIKEYS
+#define NUM_MIDIKEYS 128
+#endif NUM_MIDIKEYS
+
+#ifndef NUM_MIDICHANNELS
+#define NUM_MIDICHANNELS 16
+#endif NUM_MIDICHANNELS
+
+/* These are very useful/important. the original wavefront interface
+ was developed on a 16 bit system, where sizeof(int) = 2
+ bytes. Defining things like this makes the code much more portable, and
+ easier to understand without having to toggle back and forth
+ between a 16-bit view of the world and a 32-bit one.
+ */
+
+typedef short INT16;
+typedef unsigned short UINT16;
+typedef int INT32;
+typedef unsigned int UINT32;
+typedef char CHAR8;
+typedef unsigned char UCHAR8;
+
+/* Pseudo-commands not part of the WaveFront command set.
+ These are used for various driver controls and direct
+ hardware control.
+ */
+
+#define WFC_DEBUG_DRIVER 0
+#define WFC_FX_IOCTL 1
+#define WFC_PATCH_STATUS 2
+#define WFC_PROGRAM_STATUS 3
+#define WFC_SAMPLE_STATUS 4
+#define WFC_DISABLE_INTERRUPTS 5
+#define WFC_ENABLE_INTERRUPTS 6
+#define WFC_INTERRUPT_STATUS 7
+#define WFC_ROMSAMPLES_RDONLY 8
+#define WFC_IDENTIFY_SLOT_TYPE 9
+
+/* Wavefront synth commands
+ */
+
+#define WFC_DOWNLOAD_SAMPLE 0x80
+#define WFC_DOWNLOAD_BLOCK 0x81
+#define WFC_DOWNLOAD_MULTISAMPLE 0x82
+#define WFC_DOWNLOAD_SAMPLE_ALIAS 0x83
+#define WFC_DELETE_SAMPLE 0x84
+#define WFC_REPORT_FREE_MEMORY 0x85
+#define WFC_DOWNLOAD_PATCH 0x86
+#define WFC_DOWNLOAD_PROGRAM 0x87
+#define WFC_SET_SYNTHVOL 0x89
+#define WFC_SET_NVOICES 0x8B
+#define WFC_DOWNLOAD_DRUM 0x90
+#define WFC_GET_SYNTHVOL 0x92
+#define WFC_GET_NVOICES 0x94
+#define WFC_DISABLE_CHANNEL 0x9A
+#define WFC_ENABLE_CHANNEL 0x9B
+#define WFC_MISYNTH_OFF 0x9D
+#define WFC_MISYNTH_ON 0x9E
+#define WFC_FIRMWARE_VERSION 0x9F
+#define WFC_GET_NSAMPLES 0xA0
+#define WFC_DISABLE_DRUM_PROGRAM 0xA2
+#define WFC_UPLOAD_PATCH 0xA3
+#define WFC_UPLOAD_PROGRAM 0xA4
+#define WFC_SET_TUNING 0xA6
+#define WFC_GET_TUNING 0xA7
+#define WFC_VMIDI_ON 0xA8
+#define WFC_VMIDI_OFF 0xA9
+#define WFC_MIDI_STATUS 0xAA
+#define WFC_GET_CHANNEL_STATUS 0xAB
+#define WFC_DOWNLOAD_SAMPLE_HEADER 0xAC
+#define WFC_UPLOAD_SAMPLE_HEADER 0xAD
+#define WFC_UPLOAD_MULTISAMPLE 0xAE
+#define WFC_UPLOAD_SAMPLE_ALIAS 0xAF
+#define WFC_IDENTIFY_SAMPLE_TYPE 0xB0
+#define WFC_DOWNLOAD_EDRUM_PROGRAM 0xB1
+#define WFC_UPLOAD_EDRUM_PROGRAM 0xB2
+#define WFC_SET_EDRUM_CHANNEL 0xB3
+#define WFC_INSTOUT_LEVELS 0xB4
+#define WFC_PEAKOUT_LEVELS 0xB5
+#define WFC_REPORT_CHANNEL_PROGRAMS 0xB6
+#define WFC_HARDWARE_VERSION 0xCF
+#define WFC_UPLOAD_SAMPLE_PARAMS 0xD7
+#define WFC_DOWNLOAD_OS 0xF1
+#define WFC_NOOP 0xFF
+
+#define WF_MAX_SAMPLE 512
+#define WF_MAX_PATCH 256
+#define WF_MAX_PROGRAM 128
+
+#define WF_SECTION_MAX 44 /* longest OS section length */
+
+/* # of bytes we send to the board when sending it various kinds of
+ substantive data, such as samples, patches and programs.
+*/
+
+#define WF_PROGRAM_BYTES 32
+#define WF_PATCH_BYTES 132
+#define WF_SAMPLE_BYTES 27
+#define WF_SAMPLE_HDR_BYTES 25
+#define WF_ALIAS_BYTES 25
+#define WF_DRUM_BYTES 9
+#define WF_MSAMPLE_BYTES 259 /* (MIDI_KEYS * 2) + 3 */
+
+#define WF_ACK 0x80
+#define WF_DMA_ACK 0x81
+
+/* OR-values for MIDI status bits */
+
+#define WF_MIDI_VIRTUAL_ENABLED 0x1
+#define WF_MIDI_VIRTUAL_IS_EXTERNAL 0x2
+#define WF_MIDI_IN_TO_SYNTH_DISABLED 0x4
+
+/* slot indexes for struct address_info: makes code a little more mnemonic */
+
+#define WF_SYNTH_SLOT 0
+#define WF_INTERNAL_MIDI_SLOT 1
+#define WF_EXTERNAL_MIDI_SLOT 2
+
+/* Magic MIDI bytes used to switch I/O streams on the ICS2115 MPU401
+ emulation. Note these NEVER show up in output from the device and
+ should NEVER be used in input unless Virtual MIDI mode has been
+ disabled. If they do show up as input, the results are unpredictable.
+*/
+
+#define WF_EXTERNAL_SWITCH 0xFD
+#define WF_INTERNAL_SWITCH 0xF9
+
+/* Debugging flags */
+
+#define WF_DEBUG_CMD 0x1
+#define WF_DEBUG_DATA 0x2
+#define WF_DEBUG_LOAD_PATCH 0x4
+#define WF_DEBUG_IO 0x8
+
+/* WavePatch file format stuff */
+
+#define WF_WAVEPATCH_VERSION 120; /* Current version number (1.2) */
+#define WF_MAX_COMMENT 64 /* Comment length */
+#define WF_NUM_LAYERS 4
+#define WF_NAME_LENGTH 32
+#define WF_SOURCE_LENGTH 260
+
+#define BankFileID "Bank"
+#define DrumkitFileID "DrumKit"
+#define ProgramFileID "Program"
+
+struct wf_envelope
+{
+ UCHAR8 attack_time:7;
+ UCHAR8 Unused1:1;
+
+ UCHAR8 decay1_time:7;
+ UCHAR8 Unused2:1;
+
+ UCHAR8 decay2_time:7;
+ UCHAR8 Unused3:1;
+
+ UCHAR8 sustain_time:7;
+ UCHAR8 Unused4:1;
+
+ UCHAR8 release_time:7;
+ UCHAR8 Unused5:1;
+
+ UCHAR8 release2_time:7;
+ UCHAR8 Unused6:1;
+
+ CHAR8 attack_level;
+ CHAR8 decay1_level;
+ CHAR8 decay2_level;
+ CHAR8 sustain_level;
+ CHAR8 release_level;
+
+ UCHAR8 attack_velocity:7;
+ UCHAR8 Unused7:1;
+
+ UCHAR8 volume_velocity:7;
+ UCHAR8 Unused8:1;
+
+ UCHAR8 keyboard_scaling:7;
+ UCHAR8 Unused9:1;
+};
+typedef struct wf_envelope wavefront_envelope;
+
+struct wf_lfo
+{
+ UCHAR8 sample_number;
+
+ UCHAR8 frequency:7;
+ UCHAR8 Unused1:1;
+
+ UCHAR8 am_src:4;
+ UCHAR8 fm_src:4;
+
+ CHAR8 fm_amount;
+ CHAR8 am_amount;
+ CHAR8 start_level;
+ CHAR8 end_level;
+
+ UCHAR8 ramp_delay:7;
+ UCHAR8 wave_restart:1; /* for LFO2 only */
+
+ UCHAR8 ramp_time:7;
+ UCHAR8 Unused2:1;
+};
+typedef struct wf_lfo wavefront_lfo;
+
+struct wf_patch
+{
+ INT16 frequency_bias; /* ** THIS IS IN MOTOROLA FORMAT!! ** */
+
+ UCHAR8 amplitude_bias:7;
+ UCHAR8 Unused1:1;
+
+ UCHAR8 portamento:7;
+ UCHAR8 Unused2:1;
+
+ UCHAR8 sample_number;
+
+ UCHAR8 pitch_bend:4;
+ UCHAR8 sample_msb:1;
+ UCHAR8 Unused3:3;
+
+ UCHAR8 mono:1;
+ UCHAR8 retrigger:1;
+ UCHAR8 nohold:1;
+ UCHAR8 restart:1;
+ UCHAR8 filterconfig:2; /* SDK says "not used" */
+ UCHAR8 reuse:1;
+ UCHAR8 reset_lfo:1;
+
+ UCHAR8 fm_src2:4;
+ UCHAR8 fm_src1:4;
+
+ CHAR8 fm_amount1;
+ CHAR8 fm_amount2;
+
+ UCHAR8 am_src:4;
+ UCHAR8 Unused4:4;
+
+ CHAR8 am_amount;
+
+ UCHAR8 fc1_mode:4;
+ UCHAR8 fc2_mode:4;
+
+ CHAR8 fc1_mod_amount;
+ CHAR8 fc1_keyboard_scaling;
+ CHAR8 fc1_bias;
+ CHAR8 fc2_mod_amount;
+ CHAR8 fc2_keyboard_scaling;
+ CHAR8 fc2_bias;
+
+ UCHAR8 randomizer:7;
+ UCHAR8 Unused5:1;
+
+ struct wf_envelope envelope1;
+ struct wf_envelope envelope2;
+ struct wf_lfo lfo1;
+ struct wf_lfo lfo2;
+};
+typedef struct wf_patch wavefront_patch;
+
+struct wf_layer
+{
+ UCHAR8 patch_number;
+
+ UCHAR8 mix_level:7;
+ UCHAR8 mute:1;
+
+ UCHAR8 split_point:7;
+ UCHAR8 play_below:1;
+
+ UCHAR8 pan_mod_src:2;
+ UCHAR8 pan_or_mod:1;
+ UCHAR8 pan:4;
+ UCHAR8 split_type:1;
+};
+typedef struct wf_layer wavefront_layer;
+
+struct wf_program
+{
+ struct wf_layer layer[WF_NUM_LAYERS];
+};
+typedef struct wf_program wavefront_program;
+
+struct wf_sample_offset
+{
+ INT32 Fraction:4;
+ INT32 Integer:20;
+ INT32 Unused:8;
+};
+typedef struct wf_sample_offset wavefront_sample_offset;
+
+/* Sample slot types */
+
+#define WF_ST_SAMPLE 0
+#define WF_ST_MULTISAMPLE 1
+#define WF_ST_ALIAS 2
+#define WF_ST_EMPTY 3
+
+/* pseudo's */
+
+#define WF_ST_DRUM 4
+#define WF_ST_PROGRAM 5
+#define WF_ST_PATCH 6
+#define WF_ST_SAMPLEHDR 7
+
+#define WF_ST_MASK 0xf
+
+/* Flags for slot status. These occupy the upper bits of the same byte
+ as a sample type.
+*/
+
+#define WF_SLOT_USED 0x80 /* XXX don't rely on this being accurate */
+#define WF_SLOT_FILLED 0x40
+#define WF_SLOT_ROM 0x20
+
+#define WF_SLOT_MASK 0xf0
+
+/* channel constants */
+
+#define WF_CH_MONO 0
+#define WF_CH_LEFT 1
+#define WF_CH_RIGHT 2
+
+/* Sample formats */
+
+#define LINEAR_16BIT 0
+#define WHITE_NOISE 1
+#define LINEAR_8BIT 2
+#define MULAW_8BIT 3
+
+#define WF_SAMPLE_IS_8BIT(smpl) ((smpl)->SampleResolution&2)
+
+
+/*
+
+ Because most/all of the sample data we pass in via pointers has
+ never been copied (just mmap-ed into user space straight from the
+ disk), it would be nice to allow handling of multi-channel sample
+ data without forcing user-level extraction of the relevant bytes.
+
+ So, we need a way of specifying which channel to use (the WaveFront
+ only handles mono samples in a given slot), and the only way to do
+ this without using some struct other than wavefront_sample as the
+ interface is the awful hack of using the unused bits in a
+ wavefront_sample:
+
+ Val Meaning
+ --- -------
+ 0 no channel selection (use channel 1, sample is MONO)
+ 1 use first channel, and skip one
+ 2 use second channel, and skip one
+ 3 use third channel, and skip two
+ 4 use fourth channel, skip three
+ 5 use fifth channel, skip four
+ 6 use six channel, skip five
+
+
+ This can handle up to 4 channels, and anyone downloading >4 channels
+ of sample data just to select one of them needs to find some tools
+ like sox ...
+
+ NOTE: values 0, 1 and 2 correspond to WF_CH_* above. This is
+ important.
+
+*/
+
+#define WF_SET_CHANNEL(samp,chn) \
+ (samp)->Unused1 = chn & 0x1; \
+ (samp)->Unused2 = chn & 0x2; \
+ (samp)->Unused3 = chn & 0x4
+
+#define WF_GET_CHANNEL(samp) \
+ (((samp)->Unused3 << 2)|((samp)->Unused2<<1)|(samp)->Unused1)
+
+typedef struct wf_sample {
+ struct wf_sample_offset sampleStartOffset;
+ struct wf_sample_offset loopStartOffset;
+ struct wf_sample_offset loopEndOffset;
+ struct wf_sample_offset sampleEndOffset;
+ INT16 FrequencyBias;
+ UCHAR8 SampleResolution:2; /* sample_format */
+ UCHAR8 Unused1:1;
+ UCHAR8 Loop:1;
+ UCHAR8 Bidirectional:1;
+ UCHAR8 Unused2:1;
+ UCHAR8 Reverse:1;
+ UCHAR8 Unused3:1;
+} wavefront_sample;
+
+typedef struct wf_multisample {
+ INT16 NumberOfSamples; /* log2 of the number of samples */
+ INT16 SampleNumber[NUM_MIDIKEYS];
+} wavefront_multisample;
+
+typedef struct wf_alias {
+ INT16 OriginalSample __attribute__ ((packed));
+
+ struct wf_sample_offset sampleStartOffset __attribute__ ((packed));
+ struct wf_sample_offset loopStartOffset __attribute__ ((packed));
+ struct wf_sample_offset sampleEndOffset __attribute__ ((packed));
+ struct wf_sample_offset loopEndOffset __attribute__ ((packed));
+
+ INT16 FrequencyBias __attribute__ ((packed));
+
+ UCHAR8 SampleResolution:2 __attribute__ ((packed));
+ UCHAR8 Unused1:1 __attribute__ ((packed));
+ UCHAR8 Loop:1 __attribute__ ((packed));
+ UCHAR8 Bidirectional:1 __attribute__ ((packed));
+ UCHAR8 Unused2:1 __attribute__ ((packed));
+ UCHAR8 Reverse:1 __attribute__ ((packed));
+ UCHAR8 Unused3:1 __attribute__ ((packed));
+
+ /* This structure is meant to be padded only to 16 bits on their
+ original. Of course, whoever wrote their documentation didn't
+ realize that sizeof(struct) can be >=
+ sum(sizeof(struct-fields)) and so thought that giving a C level
+ description of the structs used in WavePatch files was
+ sufficient. I suppose it was, as long as you remember the
+ standard 16->32 bit issues.
+ */
+
+ UCHAR8 sixteen_bit_padding __attribute__ ((packed));
+} wavefront_alias;
+
+typedef struct wf_drum {
+ UCHAR8 PatchNumber;
+ UCHAR8 MixLevel:7;
+ UCHAR8 Unmute:1;
+ UCHAR8 Group:4;
+ UCHAR8 Unused1:4;
+ UCHAR8 PanModSource:2;
+ UCHAR8 PanModulated:1;
+ UCHAR8 PanAmount:4;
+ UCHAR8 Unused2:1;
+} wavefront_drum;
+
+typedef struct wf_drumkit {
+ struct wf_drum drum[NUM_MIDIKEYS];
+} wavefront_drumkit;
+
+typedef struct wf_channel_programs {
+ UCHAR8 Program[NUM_MIDICHANNELS];
+} wavefront_channel_programs;
+
+/* How to get MIDI channel status from the data returned by
+ a WFC_GET_CHANNEL_STATUS command (a struct wf_channel_programs)
+*/
+
+#define WF_CHANNEL_STATUS(ch,wcp) (wcp)[(ch/7)] & (1<<((ch)%7))
+
+typedef union wf_any {
+ wavefront_sample s;
+ wavefront_multisample ms;
+ wavefront_alias a;
+ wavefront_program pr;
+ wavefront_patch p;
+ wavefront_drum d;
+} wavefront_any;
+
+/* Hannu Solvainen hoped that his "patch_info" struct in soundcard.h
+ might work for other wave-table based patch loading situations.
+ Alas, his fears were correct. The WaveFront doesn't even come with
+ just "patches", but several different kind of structures that
+ control the sound generation process.
+ */
+
+typedef struct wf_patch_info {
+
+ /* the first two fields are used by the OSS "patch loading" interface
+ only, and are unused by the current user-level library.
+ */
+
+ INT16 key; /* Use WAVEFRONT_PATCH here */
+ UINT16 devno; /* fill in when sending */
+ UCHAR8 subkey; /* WF_ST_{SAMPLE,ALIAS,etc.} */
+
+#define WAVEFRONT_FIND_FREE_SAMPLE_SLOT 999
+
+ UINT16 number; /* patch/sample/prog number */
+
+ UINT32 size; /* size of any data included in
+ one of the fields in `hdrptr', or
+ as `dataptr'.
+
+ NOTE: for actual samples, this is
+ the size of the *SELECTED CHANNEL*
+ even if more data is actually available.
+
+ So, a stereo sample (2 channels) of
+ 6000 bytes total has `size' = 3000.
+
+ See the macros and comments for
+ WF_{GET,SET}_CHANNEL above.
+
+ */
+ wavefront_any *hdrptr; /* user-space ptr to hdr bytes */
+ UINT16 *dataptr; /* actual sample data */
+
+ wavefront_any hdr; /* kernel-space copy of hdr bytes */
+} wavefront_patch_info;
+
+/* The maximum number of bytes we will ever move to or from user space
+ in response to a WFC_* command. This obviously doesn't cover
+ actual sample data.
+*/
+
+#define WF_MAX_READ sizeof(wavefront_multisample)
+#define WF_MAX_WRITE sizeof(wavefront_multisample)
+
+/*
+ This allows us to execute any WF command except the download/upload
+ ones, which are handled differently due to copyin/copyout issues as
+ well as data-nybbling to/from the card.
+ */
+
+typedef struct wavefront_control {
+ int cmd; /* WFC_* */
+ char status; /* return status to user-space */
+ unsigned char rbuf[WF_MAX_READ]; /* bytes read from card */
+ unsigned char wbuf[WF_MAX_WRITE]; /* bytes written to card */
+} wavefront_control;
+
+#define WFCTL_WFCMD 0x1
+#define WFCTL_LOAD_SPP 0x2
+
+/* Modulator table */
+
+#define WF_MOD_LFO1 0
+#define WF_MOD_LFO2 1
+#define WF_MOD_ENV1 2
+#define WF_MOD_ENV2 3
+#define WF_MOD_KEYBOARD 4
+#define WF_MOD_LOGKEY 5
+#define WF_MOD_VELOCITY 6
+#define WF_MOD_LOGVEL 7
+#define WF_MOD_RANDOM 8
+#define WF_MOD_PRESSURE 9
+#define WF_MOD_MOD_WHEEL 10
+#define WF_MOD_1 WF_MOD_MOD_WHEEL
+#define WF_MOD_BREATH 11
+#define WF_MOD_2 WF_MOD_BREATH
+#define WF_MOD_FOOT 12
+#define WF_MOD_4 WF_MOD_FOOT
+#define WF_MOD_VOLUME 13
+#define WF_MOD_7 WF_MOD_VOLUME
+#define WF_MOD_PAN 14
+#define WF_MOD_10 WF_MOD_PAN
+#define WF_MOD_EXPR 15
+#define WF_MOD_11 WF_MOD_EXPR
+
+/* FX-related material */
+
+typedef struct wf_fx_info {
+ int request; /* see list below */
+ int data[4]; /* we don't need much */
+} wavefront_fx_info;
+
+/* support for each of these will be forthcoming once I or someone
+ else has figured out which of the addresses on page 6 and page 7 of
+ the YSS225 control each parameter. Incidentally, these come from
+ the Windows driver interface, but again, Turtle Beach didn't
+ document the API to use them.
+*/
+
+#define WFFX_SETOUTGAIN 0
+#define WFFX_SETSTEREOOUTGAIN 1
+#define WFFX_SETREVERBIN1GAIN 2
+#define WFFX_SETREVERBIN2GAIN 3
+#define WFFX_SETREVERBIN3GAIN 4
+#define WFFX_SETCHORUSINPORT 5
+#define WFFX_SETREVERBIN1PORT 6
+#define WFFX_SETREVERBIN2PORT 7
+#define WFFX_SETREVERBIN3PORT 8
+#define WFFX_SETEFFECTPORT 9
+#define WFFX_SETAUXPORT 10
+#define WFFX_SETREVERBTYPE 11
+#define WFFX_SETREVERBDELAY 12
+#define WFFX_SETCHORUSLFO 13
+#define WFFX_SETCHORUSPMD 14
+#define WFFX_SETCHORUSAMD 15
+#define WFFX_SETEFFECT 16
+#define WFFX_SETBASEALL 17
+#define WFFX_SETREVERBALL 18
+#define WFFX_SETCHORUSALL 20
+#define WFFX_SETREVERBDEF 22
+#define WFFX_SETCHORUSDEF 23
+#define WFFX_DELAYSETINGAIN 24
+#define WFFX_DELAYSETFBGAIN 25
+#define WFFX_DELAYSETFBLPF 26
+#define WFFX_DELAYSETGAIN 27
+#define WFFX_DELAYSETTIME 28
+#define WFFX_DELAYSETFBTIME 29
+#define WFFX_DELAYSETALL 30
+#define WFFX_DELAYSETDEF 32
+#define WFFX_SDELAYSETINGAIN 33
+#define WFFX_SDELAYSETFBGAIN 34
+#define WFFX_SDELAYSETFBLPF 35
+#define WFFX_SDELAYSETGAIN 36
+#define WFFX_SDELAYSETTIME 37
+#define WFFX_SDELAYSETFBTIME 38
+#define WFFX_SDELAYSETALL 39
+#define WFFX_SDELAYSETDEF 41
+#define WFFX_DEQSETINGAIN 42
+#define WFFX_DEQSETFILTER 43
+#define WFFX_DEQSETALL 44
+#define WFFX_DEQSETDEF 46
+#define WFFX_MUTE 47
+#define WFFX_FLANGESETBALANCE 48
+#define WFFX_FLANGESETDELAY 49
+#define WFFX_FLANGESETDWFFX_TH 50
+#define WFFX_FLANGESETFBGAIN 51
+#define WFFX_FLANGESETINGAIN 52
+#define WFFX_FLANGESETLFO 53
+#define WFFX_FLANGESETALL 54
+#define WFFX_FLANGESETDEF 56
+#define WFFX_PITCHSETSHIFT 57
+#define WFFX_PITCHSETBALANCE 58
+#define WFFX_PITCHSETALL 59
+#define WFFX_PITCHSETDEF 61
+#define WFFX_SRSSETINGAIN 62
+#define WFFX_SRSSETSPACE 63
+#define WFFX_SRSSETCENTER 64
+#define WFFX_SRSSETGAIN 65
+#define WFFX_SRSSETMODE 66
+#define WFFX_SRSSETDEF 68
+
+/* Allow direct user-space control over FX memory/coefficient data.
+ In theory this could be used to download the FX microprogram,
+ but it would be a little slower, and involve some wierd code.
+ */
+
+#define WFFX_MEMSET 69
+
+#endif __wavefront_h__
diff --git a/pfinet/linux-src/include/linux/wireless.h b/pfinet/linux-src/include/linux/wireless.h
new file mode 100644
index 00000000..acc0619e
--- /dev/null
+++ b/pfinet/linux-src/include/linux/wireless.h
@@ -0,0 +1,397 @@
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version : 8 28.7.99
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands. This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ * net/core/dev.c (two place + add include)
+ * net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ * net/core/dev.c (two other places)
+ * include/linux/netdevice.h (one place)
+ * include/linux/proc_fs.h (one place)
+ *
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+#include <linux/types.h> /* for "caddr_t" et al */
+#include <linux/socket.h> /* for "struct sockaddr" et al */
+#include <linux/if.h> /* for IFNAMSIZ and co... */
+
+/**************************** CONSTANTS ****************************/
+
+/* --------------------------- VERSION --------------------------- */
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT 8
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
+ * - Encryption renamed to Encode to avoid US regulation problems
+ * - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ * - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ * - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ * - Changed my e-mail address
+ * - More 802.11 support (nickname, rate, rts, frag)
+ * - List index in frequencies
+ */
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Basic operations */
+#define SIOCSIWNAME 0x8B00 /* Unused ??? */
+#define SIOCGIWNAME 0x8B01 /* get name */
+#define SIOCSIWNWID 0x8B02 /* set network id */
+#define SIOCGIWNWID 0x8B03 /* get network id */
+#define SIOCSIWFREQ 0x8B04 /* set channel/frequency */
+#define SIOCGIWFREQ 0x8B05 /* get channel/frequency */
+#define SIOCSIWENCODE 0x8B06 /* set encoding info */
+#define SIOCGIWENCODE 0x8B07 /* get encoding info */
+#define SIOCSIWSENS 0x8B08 /* set sensitivity */
+#define SIOCGIWSENS 0x8B09 /* get sensitivity */
+
+/* Informative stuff */
+#define SIOCSIWRANGE 0x8B0A /* Unused ??? */
+#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */
+#define SIOCSIWPRIV 0x8B0C /* Unused ??? */
+#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
+
+/* Mobile IP support */
+#define SIOCSIWSPY 0x8B10 /* set spy addresses */
+#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
+
+/* Access Point manipulation */
+#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
+#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
+#define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
+#define SIOCGIWESSID 0x8B1B /* get ESSID */
+#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */
+#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE...
+ * The "flags" member indicate if the ESSID is active or not (promiscuous).
+ */
+
+/* Other parameters usefull in 802.11 and some other devices */
+#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
+#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
+#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST 0x8B00
+#define SIOCIWLAST 0x8B25
+
+/* Even : get (world access), odd : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCDEVPRIVATE -> SIOCDEVPRIVATE + 0xF
+ */
+
+#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */
+#define IW_PRIV_TYPE_NONE 0x0000
+#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
+#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
+#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT 0x5000
+
+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */
+
+#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+#define IW_MAX_FREQUENCIES 16
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+#define IW_MAX_BITRATES 8
+
+/* Maximum of address that you may set with SPY */
+#define IW_MAX_SPY 8
+
+/* Maximum of address that you may get in the
+ list of access points in range */
+#define IW_MAX_AP 8
+
+/* Maximum size of the ESSID and NICKN strings */
+#define IW_ESSID_MAX_SIZE 32
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ * A frequency
+ * For numbers lower than 10^9, we encode the number in 'm' and
+ * set 'e' to 0
+ * For number greater than 10^9, we divide it by the lowest power
+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ * The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq
+{
+ __u32 m; /* Mantissa */
+ __u16 e; /* Exponent */
+ __u8 i; /* List index (when in range struct) */
+};
+
+/*
+ * Quality of the link
+ */
+struct iw_quality
+{
+ __u8 qual; /* link quality (SNR or better...) */
+ __u8 level; /* signal level */
+ __u8 noise; /* noise level */
+ __u8 updated; /* Flags to know if updated */
+};
+
+/*
+ * Packet discarded in the wireless adapter due to
+ * "wireless" specific problems...
+ */
+struct iw_discarded
+{
+ __u32 nwid; /* Wrong nwid */
+ __u32 code; /* Unable to code/decode */
+ __u32 misc; /* Others cases */
+};
+
+/*
+ * Encoding information (setting and so on)
+ * Encoding might be hardware encryption, scrambing or others
+ */
+struct iw_encoding
+{
+ __u8 method; /* Algorithm number / key used */
+ __u64 code; /* Data/key used for algorithm */
+};
+
+/*
+ * Generic format for parameters
+ */
+struct iw_param
+{
+ __s32 value; /* The value of the parameter itself */
+ __u8 fixed; /* Hardware should not use auto select */
+};
+
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics
+{
+ __u8 status; /* Status
+ * - device dependent for now */
+
+ struct iw_quality qual; /* Quality of the link
+ * (instant/mean/max) */
+ struct iw_discarded discard; /* Packet discarded counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ *
+ * Note that it should fit on the same memory footprint !
+ * You should check this when increasing the above structures (16 octets)
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ */
+struct iwreq
+{
+ union
+ {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
+ } ifr_ifrn;
+
+ /* Data part */
+ union
+ {
+ /* Config - generic */
+ char name[IFNAMSIZ];
+ /* Name : used to verify the presence of wireless extensions.
+ * Name of the protocol/provider... */
+
+ struct /* network id (or domain) : used to to */
+ { /* create logical channels on the air */
+ __u32 nwid; /* value */
+ __u8 on; /* active/unactive nwid */
+ } nwid;
+
+ struct iw_freq freq; /* frequency or channel :
+ * 0-1000 = channel
+ * > 1000 = frequency in Hz */
+
+ struct iw_encoding encoding; /* Encoding stuff */
+
+ __u32 sensitivity; /* Obsolete, but compatible */
+ struct iw_param sens; /* signal level threshold */
+ struct iw_param bitrate; /* default bit rate */
+ struct iw_param rts; /* RTS threshold threshold */
+ struct iw_param frag; /* Fragmentation threshold */
+
+ struct sockaddr ap_addr; /* Access point address */
+
+ struct /* For all data bigger than 16 octets */
+ {
+ caddr_t pointer; /* Pointer to the data
+ * (in user space) */
+ __u16 length; /* fields or byte size */
+ __u16 flags; /* Optional params */
+ } data;
+ } u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ * For those ioctl which want to exchange mode data that what could
+ * fit in the above structure...
+ */
+
+/*
+ * Range of parameters
+ */
+
+struct iw_range
+{
+ /* Informative stuff (to choose between different interface) */
+ __u32 throughput; /* To give an idea... */
+ /* In theory this value should be the maximum benchmarked
+ * TCP/IP throughput, because with most of these devices the
+ * bit rate is meaningless (overhead an co) to estimate how
+ * fast the connection will go and pick the fastest one.
+ * I suggest people to play with Netperf or any benchmark...
+ */
+
+ /* NWID (or domain id) */
+ __u32 min_nwid; /* Minimal NWID we are able to set */
+ __u32 max_nwid; /* Maximal NWID we are able to set */
+
+ /* Frequency */
+ __u16 num_channels; /* Number of channels [0; num - 1] */
+ __u8 num_frequency; /* Number of entry in the list */
+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers */
+
+ /* signal level threshold range */
+ __s32 sensitivity;
+
+ /* Quality of link & SNR stuff */
+ struct iw_quality max_qual; /* Quality of the link */
+
+ /* Encoder stuff */
+ struct iw_encoding max_encoding; /* Encoding max range */
+
+ /* Rates */
+ __u8 num_bitrates; /* Number of entries in the list */
+ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */
+
+ /* RTS threshold */
+ __s32 min_rts; /* Minimal RTS threshold */
+ __s32 max_rts; /* Maximal RTS threshold */
+
+ /* Frag threshold */
+ __s32 min_frag; /* Minimal frag threshold */
+ __s32 max_frag; /* Maximal frag threshold */
+};
+
+/*
+ * Private ioctl interface information
+ */
+
+struct iw_priv_args
+{
+ __u32 cmd; /* Number of the ioctl to issue */
+ __u16 set_args; /* Type and number of args */
+ __u16 get_args; /* Type and number of args */
+ char name[IFNAMSIZ]; /* Name of the extension */
+};
+
+#endif /* _LINUX_WIRELESS_H */
diff --git a/pfinet/linux-src/include/linux/wrapper.h b/pfinet/linux-src/include/linux/wrapper.h
new file mode 100644
index 00000000..d8a73117
--- /dev/null
+++ b/pfinet/linux-src/include/linux/wrapper.h
@@ -0,0 +1,40 @@
+#ifndef _WRAPPER_H_
+#define _WRAPPER_H_
+#define wait_handle struct wait_queue
+#define file_handle struct file
+#define inode_handle struct inode
+#define select_table_handle select_table
+#define vm_area_handle struct vm_area_struct
+#define file_operation_handle file_operations
+
+#define connect_wrapper(x) 0
+#define current_got_fatal_signal() (signal_pending(current))
+#define current_set_timeout(val) current->timeout = val
+
+#define module_interruptible_sleep_on interruptible_sleep_on
+#define module_wake_up wake_up
+#define module_select_wait select_wait
+#define module_register_chrdev register_chrdev
+#define module_unregister_chrdev unregister_chrdev
+#define module_register_blkdev register_blkdev
+#define module_unregister_blkdev unregister_blkdev
+
+#define inode_get_rdev(i) i->i_rdev
+#define inode_get_count(i) i->i_count
+#define inode_inc_count(i) i->i_count++
+#define inode_dec_count(i) i->i_count--
+
+#define file_get_flags(f) f->f_flags
+
+#define vma_set_inode(v,i) v->vm_inode = i
+#define vma_get_flags(v) v->vm_flags
+#define vma_get_offset(v) v->vm_offset
+#define vma_get_start(v) v->vm_start
+#define vma_get_end(v) v->vm_end
+#define vma_get_page_prot(v) v->vm_page_prot
+
+#define mem_map_reserve(p) set_bit(PG_reserved, &mem_map[p].flags)
+#define mem_map_unreserve(p) clear_bit(PG_reserved, &mem_map[p].flags)
+#define mem_map_inc_count(p) atomic_inc(&(mem_map[p].count))
+#define mem_map_dec_count(p) atomic_dec(&(mem_map[p].count))
+#endif
diff --git a/pfinet/linux-src/include/linux/x25.h b/pfinet/linux-src/include/linux/x25.h
new file mode 100644
index 00000000..6f3f300b
--- /dev/null
+++ b/pfinet/linux-src/include/linux/x25.h
@@ -0,0 +1,93 @@
+/*
+ * These are the public elements of the Linux kernel X.25 implementation.
+ */
+
+#ifndef X25_KERNEL_H
+#define X25_KERNEL_H
+
+#define SIOCX25GSUBSCRIP (SIOCPROTOPRIVATE + 0)
+#define SIOCX25SSUBSCRIP (SIOCPROTOPRIVATE + 1)
+#define SIOCX25GFACILITIES (SIOCPROTOPRIVATE + 2)
+#define SIOCX25SFACILITIES (SIOCPROTOPRIVATE + 3)
+#define SIOCX25GCALLUSERDATA (SIOCPROTOPRIVATE + 4)
+#define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5)
+#define SIOCX25GCAUSEDIAG (SIOCPROTOPRIVATE + 6)
+
+/*
+ * Values for {get,set}sockopt.
+ */
+#define X25_QBITINCL 1
+
+/*
+ * X.25 Packet Size values.
+ */
+#define X25_PS16 4
+#define X25_PS32 5
+#define X25_PS64 6
+#define X25_PS128 7
+#define X25_PS256 8
+#define X25_PS512 9
+#define X25_PS1024 10
+#define X25_PS2048 11
+#define X25_PS4096 12
+
+/*
+ * An X.121 address, it is held as ASCII text, null terminated, up to 15
+ * digits and a null terminator.
+ */
+typedef struct {
+ char x25_addr[16];
+} x25_address;
+
+/*
+ * Linux X.25 Address structure, used for bind, and connect mostly.
+ */
+struct sockaddr_x25 {
+ sa_family_t sx25_family; /* Must be AF_X25 */
+ x25_address sx25_addr; /* X.121 Address */
+};
+
+/*
+ * DTE/DCE subscription options.
+ */
+struct x25_subscrip_struct {
+ char device[200];
+ unsigned int extended;
+};
+
+/*
+ * Routing table control structure.
+ */
+struct x25_route_struct {
+ x25_address address;
+ unsigned int sigdigits;
+ char device[200];
+};
+
+/*
+ * Facilities structure.
+ */
+struct x25_facilities {
+ unsigned int winsize_in, winsize_out;
+ unsigned int pacsize_in, pacsize_out;
+ unsigned int throughput;
+ unsigned int reverse;
+};
+
+/*
+ * Call User Data structure.
+ */
+struct x25_calluserdata {
+ unsigned int cudlength;
+ unsigned char cuddata[128];
+};
+
+/*
+ * Call clearing Cause and Diagnostic structure.
+ */
+struct x25_causediag {
+ unsigned char cause;
+ unsigned char diagnostic;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/linux/yam.h b/pfinet/linux-src/include/linux/yam.h
new file mode 100644
index 00000000..7fe28228
--- /dev/null
+++ b/pfinet/linux-src/include/linux/yam.h
@@ -0,0 +1,82 @@
+/*****************************************************************************/
+
+/*
+ * yam.h -- YAM radio modem driver.
+ *
+ * Copyright (C) 1998 Frederic Rible F1OAT (frible@teaser.fr)
+ * Adapted from baycom.c driver written by Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ *
+ */
+
+/*****************************************************************************/
+
+#define SIOCYAMRESERVED (0)
+#define SIOCYAMSCFG (1) /* Set configuration */
+#define SIOCYAMGCFG (2) /* Get configuration */
+#define SIOCYAMSMCS (3) /* Set mcs data */
+
+#define YAM_IOBASE (1 << 0)
+#define YAM_IRQ (1 << 1)
+#define YAM_BITRATE (1 << 2) /* Bit rate of radio port ->57600 */
+#define YAM_MODE (1 << 3) /* 0=simplex 1=duplex 2=duplex+tempo */
+#define YAM_HOLDDLY (1 << 4) /* duplex tempo (sec) */
+#define YAM_TXDELAY (1 << 5) /* Tx Delay (ms) */
+#define YAM_TXTAIL (1 << 6) /* Tx Tail (ms) */
+#define YAM_PERSIST (1 << 7) /* Persist (ms) */
+#define YAM_SLOTTIME (1 << 8) /* Slottime (ms) */
+#define YAM_BAUDRATE (1 << 9) /* Baud rate of rs232 port ->115200 */
+
+#define YAM_MAXBITRATE 57600
+#define YAM_MAXBAUDRATE 115200
+#define YAM_MAXMODE 2
+#define YAM_MAXHOLDDLY 99
+#define YAM_MAXTXDELAY 999
+#define YAM_MAXTXTAIL 999
+#define YAM_MAXPERSIST 255
+#define YAM_MAXSLOTTIME 999
+
+#define YAM_FPGA_SIZE 5302
+
+struct yamcfg {
+ unsigned int mask; /* Mask of commands */
+ unsigned int iobase; /* IO Base of COM port */
+ unsigned int irq; /* IRQ of COM port */
+ unsigned int bitrate; /* Bit rate of radio port */
+ unsigned int baudrate; /* Baud rate of the RS232 port */
+ unsigned int txdelay; /* TxDelay */
+ unsigned int txtail; /* TxTail */
+ unsigned int persist; /* Persistence */
+ unsigned int slottime; /* Slottime */
+ unsigned int mode; /* mode 0 (simp), 1(Dupl), 2(Dupl+delay) */
+ unsigned int holddly; /* PTT delay in FullDuplex 2 mode */
+};
+
+struct yamdrv_ioctl_cfg {
+ int cmd;
+ struct yamcfg cfg;
+};
+
+struct yamdrv_ioctl_mcs {
+ int cmd;
+ int bitrate;
+ unsigned char bits[YAM_FPGA_SIZE];
+};
diff --git a/pfinet/linux-src/include/linux/zftape.h b/pfinet/linux-src/include/linux/zftape.h
new file mode 100644
index 00000000..ec5d2ffe
--- /dev/null
+++ b/pfinet/linux-src/include/linux/zftape.h
@@ -0,0 +1,87 @@
+#ifndef _ZFTAPE_H
+#define _ZFTAPE_H
+
+/*
+ * Copyright (C) 1996, 1997 Claus-Justus Heine.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *
+ * $Source: /homes/cvs/ftape-stacked/include/linux/zftape.h,v $
+ * $Revision: 1.12 $
+ * $Date: 1997/10/21 11:02:37 $
+ *
+ * Special ioctl and other global info for the zftape VFS
+ * interface for the QIC-40/80/3010/3020 floppy-tape driver for
+ * Linux.
+ */
+
+#define ZFTAPE_VERSION "zftape for " FTAPE_VERSION
+
+#include <linux/ftape.h>
+
+#define ZFTAPE_LABEL "Ftape - The Linux Floppy Tape Project!"
+
+/* Bits of the minor device number that control the operation mode */
+#define ZFT_Q80_MODE (1 << 3)
+#define ZFT_ZIP_MODE (1 << 4)
+#define ZFT_RAW_MODE (1 << 5)
+#define ZFT_MINOR_OP_MASK (ZFT_Q80_MODE | \
+ ZFT_ZIP_MODE | \
+ ZFT_RAW_MODE)
+#define ZFT_MINOR_MASK (FTAPE_SEL_MASK | \
+ ZFT_MINOR_OP_MASK | \
+ FTAPE_NO_REWIND)
+
+#ifdef ZFT_OBSOLETE
+struct mtblksz {
+ unsigned int mt_blksz;
+};
+#define MTIOC_ZFTAPE_GETBLKSZ _IOR('m', 104, struct mtblksz)
+#endif
+
+#ifdef __KERNEL__
+
+extern int zft_init(void);
+
+extern inline __s64 zft_div_blksz(__s64 value, __u32 blk_sz)
+{
+ if (blk_sz == 1) {
+ return value;
+ } else {
+ return (__s64)(((__u32)(value >> 10) + (blk_sz >> 10) - 1)
+ / (blk_sz >> 10));
+ }
+}
+
+extern inline __s64 zft_mul_blksz(__s64 value, __u32 blk_sz)
+{
+ if (blk_sz == 1) {
+ return value;
+ } else {
+ /* if blk_sz != 1, then it is a multiple of 1024. In
+ * this case, `value' will also fit into 32 bits.
+ *
+ * Actually, this limits the capacity to 42
+ * bits. This is (2^32)*1024, roughly a thousand
+ * times 2GB, or 3 Terabytes. Hopefully this is enough
+ */
+ return(__s64)(((__u32)(value)*(blk_sz>>10))<<10);
+ }
+}
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/linux/zorro.h b/pfinet/linux-src/include/linux/zorro.h
new file mode 100644
index 00000000..9ec9ca71
--- /dev/null
+++ b/pfinet/linux-src/include/linux/zorro.h
@@ -0,0 +1,736 @@
+/*
+ * linux/zorro.h -- Amiga AutoConfig (Zorro) Bus Definitions
+ *
+ * Copyright (C) 1995-1998 Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _LINUX_ZORRO_H
+#define _LINUX_ZORRO_H
+
+#ifndef __ASSEMBLY__
+
+ /*
+ * Known Zorro Boards
+ *
+ * Each Zorro board has a 32-bit ID of the form
+ *
+ * mmmmmmmmmmmmmmmmppppppppeeeeeeee
+ *
+ * with
+ *
+ * mmmmmmmmmmmmmmmm 16-bit Manufacturer ID (assigned by CBM (sigh))
+ * pppppppp 8-bit Product ID (assigned by manufacturer)
+ * eeeeeeee 8-bit Extended Product ID (currently only used
+ * for some GVP boards)
+ */
+
+
+#define ZORRO_MANUF(id) ((id) >> 16)
+#define ZORRO_PROD(id) (((id) >> 8) & 0xff)
+#define ZORRO_EPC(id) ((id) & 0xff)
+
+#define ZORRO_ID(manuf, prod, epc) \
+ ((ZORRO_MANUF_##manuf << 16) | ((prod) << 8) | (epc))
+
+typedef __u32 zorro_id;
+
+
+#define ZORRO_MANUF_PACIFIC_PERIPHERALS 0x00D3
+#define ZORRO_PROD_PACIFIC_PERIPHERALS_SE_2000_A500 ZORRO_ID(PACIFIC_PERIPHERALS, 0x00, 0)
+#define ZORRO_PROD_PACIFIC_PERIPHERALS_SCSI ZORRO_ID(PACIFIC_PERIPHERALS, 0x0A, 0)
+
+#define ZORRO_MANUF_MACROSYSTEMS_USA_2 0x0100
+#define ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE ZORRO_ID(MACROSYSTEMS_USA_2, 0x13, 0)
+
+#define ZORRO_MANUF_KUPKE_1 0x00DD
+#define ZORRO_PROD_KUPKE_GOLEM_RAM_BOX_2MB ZORRO_ID(KUPKE_1, 0x00, 0)
+
+#define ZORRO_MANUF_MEMPHIS 0x0100
+#define ZORRO_PROD_MEMPHIS_STORMBRINGER ZORRO_ID(MEMPHIS, 0x00, 0)
+
+#define ZORRO_MANUF_3_STATE 0x0200
+#define ZORRO_PROD_3_STATE_MEGAMIX_2000 ZORRO_ID(3_STATE, 0x02, 0)
+
+#define ZORRO_MANUF_COMMODORE_BRAUNSCHWEIG 0x0201
+#define ZORRO_PROD_CBM_A2088_A2286 ZORRO_ID(COMMODORE_BRAUNSCHWEIG, 0x01, 0)
+#define ZORRO_PROD_CBM_A2286 ZORRO_ID(COMMODORE_BRAUNSCHWEIG, 0x02, 0)
+#define ZORRO_PROD_CBM_A4091_1 ZORRO_ID(COMMODORE_BRAUNSCHWEIG, 0x54, 0)
+#define ZORRO_PROD_CBM_A2386SX_1 ZORRO_ID(COMMODORE_BRAUNSCHWEIG, 0x67, 0)
+
+#define ZORRO_MANUF_COMMODORE_WEST_CHESTER_1 0x0202
+#define ZORRO_PROD_CBM_A2090A ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x01, 0)
+#define ZORRO_PROD_CBM_A590_A2091_1 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x02, 0)
+#define ZORRO_PROD_CBM_A590_A2091_2 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x03, 0)
+#define ZORRO_PROD_CBM_A2090B ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x04, 0)
+#define ZORRO_PROD_CBM_A2060 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x09, 0)
+#define ZORRO_PROD_CBM_A590_A2052_A2058_A2091 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x0A, 0)
+#define ZORRO_PROD_CBM_A560_RAM ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x20, 0)
+#define ZORRO_PROD_CBM_A2232_PROTOTYPE ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x45, 0)
+#define ZORRO_PROD_CBM_A2232 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x46, 0)
+#define ZORRO_PROD_CBM_A2620 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x50, 0)
+#define ZORRO_PROD_CBM_A2630 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x51, 0)
+#define ZORRO_PROD_CBM_A4091_2 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x54, 0)
+#define ZORRO_PROD_CBM_A2065_1 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x5A, 0)
+#define ZORRO_PROD_CBM_ROMULATOR ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x60, 0)
+#define ZORRO_PROD_CBM_A3000_TEST_FIXTURE ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x61, 0)
+#define ZORRO_PROD_CBM_A2386SX_2 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x67, 0)
+#define ZORRO_PROD_CBM_A2065_2 ZORRO_ID(COMMODORE_WEST_CHESTER_1, 0x70, 0)
+
+#define ZORRO_MANUF_COMMODORE_WEST_CHESTER_2 0x0203
+#define ZORRO_PROD_CBM_A2090A_CM ZORRO_ID(COMMODORE_WEST_CHESTER_2, 0x03, 0)
+
+#define ZORRO_MANUF_PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2 0x02F4
+#define ZORRO_PROD_PPS_EXP8000 ZORRO_ID(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS_2, 0x02, 0)
+
+#define ZORRO_MANUF_KOLFF_COMPUTER_SUPPLIES 0x02FF
+#define ZORRO_PROD_KCS_POWER_PC_BOARD ZORRO_ID(KOLFF_COMPUTER_SUPPLIES, 0x00, 0)
+
+#define ZORRO_MANUF_CARDCO_1 0x03EC
+#define ZORRO_PROD_CARDCO_KRONOS_2000_1 ZORRO_ID(CARDCO_1, 0x04, 0)
+#define ZORRO_PROD_CARDCO_A1000_1 ZORRO_ID(CARDCO_1, 0x0C, 0)
+#define ZORRO_PROD_CARDCO_ESCORT ZORRO_ID(CARDCO_1, 0x0E, 0)
+#define ZORRO_PROD_CARDCO_A2410 ZORRO_ID(CARDCO_1, 0xF5, 0)
+
+#define ZORRO_MANUF_A_SQUARED 0x03ED
+#define ZORRO_PROD_A_SQUARED_LIVE_2000 ZORRO_ID(A_SQUARED, 0x01, 0)
+
+#define ZORRO_MANUF_COMSPEC_COMMUNICATIONS 0x03EE
+#define ZORRO_PROD_COMSPEC_COMMUNICATIONS_AX2000 ZORRO_ID(COMSPEC_COMMUNICATIONS, 0x01, 0)
+
+#define ZORRO_MANUF_ANAKIN_RESEARCH 0x03F1
+#define ZORRO_PROD_ANAKIN_RESEARCH_EASYL ZORRO_ID(ANAKIN_RESEARCH, 0x01, 0)
+
+#define ZORRO_MANUF_MICROBOTICS 0x03F2
+#define ZORRO_PROD_MICROBOTICS_STARBOARD_II ZORRO_ID(MICROBOTICS, 0x00, 0)
+#define ZORRO_PROD_MICROBOTICS_STARDRIVE ZORRO_ID(MICROBOTICS, 0x02, 0)
+#define ZORRO_PROD_MICROBOTICS_8_UP_A ZORRO_ID(MICROBOTICS, 0x03, 0)
+#define ZORRO_PROD_MICROBOTICS_8_UP_Z ZORRO_ID(MICROBOTICS, 0x04, 0)
+#define ZORRO_PROD_MICROBOTICS_DELTA_RAM ZORRO_ID(MICROBOTICS, 0x20, 0)
+#define ZORRO_PROD_MICROBOTICS_8_STAR_RAM ZORRO_ID(MICROBOTICS, 0x40, 0)
+#define ZORRO_PROD_MICROBOTICS_8_STAR ZORRO_ID(MICROBOTICS, 0x41, 0)
+#define ZORRO_PROD_MICROBOTICS_VXL_RAM_32 ZORRO_ID(MICROBOTICS, 0x44, 0)
+#define ZORRO_PROD_MICROBOTICS_VXL_68030 ZORRO_ID(MICROBOTICS, 0x45, 0)
+#define ZORRO_PROD_MICROBOTICS_DELTA ZORRO_ID(MICROBOTICS, 0x60, 0)
+#define ZORRO_PROD_MICROBOTICS_MBX_1200_1200Z_RAM ZORRO_ID(MICROBOTICS, 0x81, 0)
+#define ZORRO_PROD_MICROBOTICS_HARDFRAME_2000_1 ZORRO_ID(MICROBOTICS, 0x96, 0)
+#define ZORRO_PROD_MICROBOTICS_HARDFRAME_2000_2 ZORRO_ID(MICROBOTICS, 0x9E, 0)
+#define ZORRO_PROD_MICROBOTICS_MBX_1200_1200Z ZORRO_ID(MICROBOTICS, 0xC1, 0)
+
+#define ZORRO_MANUF_ACCESS_ASSOCIATES_ALEGRA 0x03F4
+
+#define ZORRO_MANUF_EXPANSION_TECHNOLOGIES 0x03F6
+
+#define ZORRO_MANUF_ASDG 0x03FF
+#define ZORRO_PROD_ASDG_MEMORY_1 ZORRO_ID(ASDG, 0x01, 0)
+#define ZORRO_PROD_ASDG_MEMORY_2 ZORRO_ID(ASDG, 0x02, 0)
+#define ZORRO_PROD_ASDG_EB920_LAN_ROVER ZORRO_ID(ASDG, 0xFE, 0)
+#define ZORRO_PROD_ASDG_GPIB_DUALIEEE488_TWIN_X ZORRO_ID(ASDG, 0xFF, 0)
+
+#define ZORRO_MANUF_IMTRONICS_1 0x0404
+#define ZORRO_PROD_IMTRONICS_HURRICANE_2800_1 ZORRO_ID(IMTRONICS_1, 0x39, 0)
+#define ZORRO_PROD_IMTRONICS_HURRICANE_2800_2 ZORRO_ID(IMTRONICS_1, 0x57, 0)
+
+#define ZORRO_MANUF_CBM_UNIVERSITY_OF_LOWELL 0x0406
+#define ZORRO_PROD_CBM_A2410 ZORRO_ID(CBM_UNIVERSITY_OF_LOWELL, 0x00, 0)
+
+#define ZORRO_MANUF_AMERISTAR 0x041D
+#define ZORRO_PROD_AMERISTAR_A2065 ZORRO_ID(AMERISTAR, 0x01, 0)
+#define ZORRO_PROD_AMERISTAR_A560 ZORRO_ID(AMERISTAR, 0x09, 0)
+#define ZORRO_PROD_AMERISTAR_A4066 ZORRO_ID(AMERISTAR, 0x0A, 0)
+
+#define ZORRO_MANUF_SUPRA 0x0420
+#define ZORRO_PROD_SUPRA_SUPRADRIVE_4x4 ZORRO_ID(SUPRA, 0x01, 0)
+#define ZORRO_PROD_SUPRA_1000_RAM ZORRO_ID(SUPRA, 0x02, 0)
+#define ZORRO_PROD_SUPRA_2000_DMA ZORRO_ID(SUPRA, 0x03, 0)
+#define ZORRO_PROD_SUPRA_500 ZORRO_ID(SUPRA, 0x05, 0)
+#define ZORRO_PROD_SUPRA_500_SCSI ZORRO_ID(SUPRA, 0x08, 0)
+#define ZORRO_PROD_SUPRA_500XP_2000_RAM ZORRO_ID(SUPRA, 0x09, 0)
+#define ZORRO_PROD_SUPRA_500RX_2000_RAM ZORRO_ID(SUPRA, 0x0A, 0)
+#define ZORRO_PROD_SUPRA_2400ZI ZORRO_ID(SUPRA, 0x0B, 0)
+#define ZORRO_PROD_SUPRA_500XP_SUPRADRIVE_WORDSYNC ZORRO_ID(SUPRA, 0x0C, 0)
+#define ZORRO_PROD_SUPRA_SUPRADRIVE_WORDSYNC_II ZORRO_ID(SUPRA, 0x0D, 0)
+#define ZORRO_PROD_SUPRA_2400ZIPLUS ZORRO_ID(SUPRA, 0x10, 0)
+
+#define ZORRO_MANUF_COMPUTER_SYSTEMS_ASSOCIATES 0x0422
+#define ZORRO_PROD_CSA_MAGNUM ZORRO_ID(COMPUTER_SYSTEMS_ASSOCIATES, 0x11, 0)
+#define ZORRO_PROD_CSA_12_GAUGE ZORRO_ID(COMPUTER_SYSTEMS_ASSOCIATES, 0x15, 0)
+
+#define ZORRO_MANUF_MARC_MICHAEL_GROTH 0x0439
+
+#define ZORRO_MANUF_M_TECH 0x0502
+#define ZORRO_PROD_MTEC_AT500_1 ZORRO_ID(M_TECH, 0x03, 0)
+
+#define ZORRO_MANUF_GREAT_VALLEY_PRODUCTS_1 0x06E1
+#define ZORRO_PROD_GVP_IMPACT_SERIES_I ZORRO_ID(GREAT_VALLEY_PRODUCTS_1, 0x08, 0)
+
+#define ZORRO_MANUF_BYTEBOX 0x07DA
+#define ZORRO_PROD_BYTEBOX_A500 ZORRO_ID(BYTEBOX, 0x00, 0)
+
+#define ZORRO_MANUF_DKB_POWER_COMPUTING 0x07DC
+#define ZORRO_PROD_DKB_POWER_COMPUTING_SECUREKEY ZORRO_ID(DKB_POWER_COMPUTING, 0x09, 0)
+#define ZORRO_PROD_DKB_POWER_COMPUTING_DKM_3128 ZORRO_ID(DKB_POWER_COMPUTING, 0x0E, 0)
+#define ZORRO_PROD_DKB_POWER_COMPUTING_RAPID_FIRE ZORRO_ID(DKB_POWER_COMPUTING, 0x0F, 0)
+#define ZORRO_PROD_DKB_POWER_COMPUTING_DKM_1202 ZORRO_ID(DKB_POWER_COMPUTING, 0x10, 0)
+#define ZORRO_PROD_DKB_POWER_COMPUTING_COBRA_VIPER_II_68EC030 ZORRO_ID(DKB_POWER_COMPUTING, 0x12, 0)
+#define ZORRO_PROD_DKB_POWER_COMPUTING_WILDFIRE_060_1 ZORRO_ID(DKB_POWER_COMPUTING, 0x17, 0)
+#define ZORRO_PROD_DKB_POWER_COMPUTING_WILDFIRE_060_2 ZORRO_ID(DKB_POWER_COMPUTING, 0xFF, 0)
+
+#define ZORRO_MANUF_GREAT_VALLEY_PRODUCTS_2 0x07E1
+#define ZORRO_PROD_GVP_IMPACT_SERIES_I_4K ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x01, 0)
+#define ZORRO_PROD_GVP_IMPACT_SERIES_I_16K_2 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x02, 0)
+#define ZORRO_PROD_GVP_IMPACT_SERIES_I_16K_3 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x03, 0)
+#define ZORRO_PROD_GVP_IMPACT_3001_IDE_1 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x08, 0)
+#define ZORRO_PROD_GVP_IMPACT_3001_RAM ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x09, 0)
+#define ZORRO_PROD_GVP_IMPACT_SERIES_II_RAM_1 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0A, 0)
+#define ZORRO_PROD_GVP_EPC_BASE ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0)
+#define ZORRO_PROD_GVP_GFORCE_040_1 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0x20)
+#define ZORRO_PROD_GVP_GFORCE_040_SCSI_1 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0x30)
+#define ZORRO_PROD_GVP_A1291 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0x40)
+#define ZORRO_PROD_GVP_COMBO_030_R4 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0x60)
+#define ZORRO_PROD_GVP_COMBO_030_R4_SCSI ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0x70)
+#define ZORRO_PROD_GVP_PHONEPAK ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0x78)
+#define ZORRO_PROD_GVP_IO_EXTENDER ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0x98)
+#define ZORRO_PROD_GVP_GFORCE_030 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0xa0)
+#define ZORRO_PROD_GVP_GFORCE_030_SCSI ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0xb0)
+#define ZORRO_PROD_GVP_A530 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0xc0)
+#define ZORRO_PROD_GVP_A530_SCSI ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0xd0)
+#define ZORRO_PROD_GVP_COMBO_030_R3 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0xe0)
+#define ZORRO_PROD_GVP_COMBO_030_R3_SCSI ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0xf0)
+#define ZORRO_PROD_GVP_SERIES_II ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0B, 0xf8)
+#define ZORRO_PROD_GVP_IMPACT_3001_IDE_2 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0D, 0)
+/*#define ZORRO_PROD_GVP_A2000_030 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0D, 0)*/
+/*#define ZORRO_PROD_GVP_GFORCE_040_SCSI_2 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x0D, 0)*/
+#define ZORRO_PROD_GVP_GFORCE_040_060 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x16, 0)
+#define ZORRO_PROD_GVP_IMPACT_VISION_24 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0x20, 0)
+#define ZORRO_PROD_GVP_GFORCE_040_2 ZORRO_ID(GREAT_VALLEY_PRODUCTS_2, 0xFF, 0)
+
+#define ZORRO_MANUF_CALIFORNIA_ACCESS_SYNERGY 0x07E5
+#define ZORRO_PROD_CALIFORNIA_ACCESS_SYNERGY_MALIBU ZORRO_ID(CALIFORNIA_ACCESS_SYNERGY, 0x01, 0)
+
+#define ZORRO_MANUF_XETEC 0x07E6
+#define ZORRO_PROD_XETEC_FASTCARD ZORRO_ID(XETEC, 0x01, 0)
+#define ZORRO_PROD_XETEC_FASTCARD_RAM ZORRO_ID(XETEC, 0x02, 0)
+#define ZORRO_PROD_XETEC_FASTCARD_PLUS ZORRO_ID(XETEC, 0x03, 0)
+
+#define ZORRO_MANUF_PROGRESSIVE_PERIPHERALS_AND_SYSTEMS 0x07EA
+#define ZORRO_PROD_PPS_MERCURY ZORRO_ID(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS, 0x00, 0)
+#define ZORRO_PROD_PPS_A3000_68040 ZORRO_ID(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS, 0x01, 0)
+#define ZORRO_PROD_PPS_A2000_68040 ZORRO_ID(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS, 0x69, 0)
+#define ZORRO_PROD_PPS_ZEUS ZORRO_ID(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS, 0x96, 0)
+#define ZORRO_PROD_PPS_A500_68040 ZORRO_ID(PROGRESSIVE_PERIPHERALS_AND_SYSTEMS, 0xBB, 0)
+
+#define ZORRO_MANUF_XEBEC 0x07EC
+
+#define ZORRO_MANUF_SPIRIT_TECHNOLOGY 0x07F2
+#define ZORRO_PROD_SPIRIT_TECHNOLOGY_INSIDER_IN1000 ZORRO_ID(SPIRIT_TECHNOLOGY, 0x01, 0)
+#define ZORRO_PROD_SPIRIT_TECHNOLOGY_INSIDER_IN500 ZORRO_ID(SPIRIT_TECHNOLOGY, 0x02, 0)
+#define ZORRO_PROD_SPIRIT_TECHNOLOGY_SIN500 ZORRO_ID(SPIRIT_TECHNOLOGY, 0x03, 0)
+#define ZORRO_PROD_SPIRIT_TECHNOLOGY_HDA_506 ZORRO_ID(SPIRIT_TECHNOLOGY, 0x04, 0)
+#define ZORRO_PROD_SPIRIT_TECHNOLOGY_AX_S ZORRO_ID(SPIRIT_TECHNOLOGY, 0x05, 0)
+#define ZORRO_PROD_SPIRIT_TECHNOLOGY_OCTABYTE ZORRO_ID(SPIRIT_TECHNOLOGY, 0x06, 0)
+#define ZORRO_PROD_SPIRIT_TECHNOLOGY_INMATE ZORRO_ID(SPIRIT_TECHNOLOGY, 0x08, 0)
+
+#define ZORRO_MANUF_SPIRIT_TECHNOLOGY_2 0x07F3
+
+#define ZORRO_MANUF_BSC_ALFADATA_1 0x07FE
+#define ZORRO_PROD_BSC_ALF_3_1 ZORRO_ID(BSC_ALFADATA_1, 0x03, 0)
+
+#define ZORRO_MANUF_BSC_ALFADATA_2 0x0801
+#define ZORRO_PROD_BSC_ALF_2_1 ZORRO_ID(BSC_ALFADATA_2, 0x01, 0)
+#define ZORRO_PROD_BSC_ALF_2_2 ZORRO_ID(BSC_ALFADATA_2, 0x02, 0)
+#define ZORRO_PROD_BSC_ALF_3_2 ZORRO_ID(BSC_ALFADATA_2, 0x03, 0)
+
+#define ZORRO_MANUF_CARDCO_2 0x0802
+#define ZORRO_PROD_CARDCO_KRONOS_2000_2 ZORRO_ID(CARDCO_2, 0x04, 0)
+#define ZORRO_PROD_CARDCO_A1000_2 ZORRO_ID(CARDCO_2, 0x0C, 0)
+
+#define ZORRO_MANUF_JOCHHEIM 0x0804
+#define ZORRO_PROD_JOCHHEIM_RAM ZORRO_ID(JOCHHEIM, 0x01, 0)
+
+#define ZORRO_MANUF_CHECKPOINT_TECHNOLOGIES 0x0807
+#define ZORRO_PROD_CHECKPOINT_TECHNOLOGIES_SERIAL_SOLUTION ZORRO_ID(CHECKPOINT_TECHNOLOGIES, 0x00, 0)
+
+#define ZORRO_MANUF_EDOTRONIK 0x0810
+#define ZORRO_PROD_EDOTRONIK_IEEE_488 ZORRO_ID(EDOTRONIK, 0x01, 0)
+#define ZORRO_PROD_EDOTRONIK_8032 ZORRO_ID(EDOTRONIK, 0x02, 0)
+#define ZORRO_PROD_EDOTRONIK_MULTISERIAL ZORRO_ID(EDOTRONIK, 0x03, 0)
+#define ZORRO_PROD_EDOTRONIK_VIDEODIGITIZER ZORRO_ID(EDOTRONIK, 0x04, 0)
+#define ZORRO_PROD_EDOTRONIK_PARALLEL_IO ZORRO_ID(EDOTRONIK, 0x05, 0)
+#define ZORRO_PROD_EDOTRONIK_PIC_PROTOYPING ZORRO_ID(EDOTRONIK, 0x06, 0)
+#define ZORRO_PROD_EDOTRONIK_ADC ZORRO_ID(EDOTRONIK, 0x07, 0)
+#define ZORRO_PROD_EDOTRONIK_VME ZORRO_ID(EDOTRONIK, 0x08, 0)
+#define ZORRO_PROD_EDOTRONIK_DSP96000 ZORRO_ID(EDOTRONIK, 0x09, 0)
+
+#define ZORRO_MANUF_NES_INC 0x0813
+#define ZORRO_PROD_NES_INC_RAM ZORRO_ID(NES_INC, 0x00, 0)
+
+#define ZORRO_MANUF_ICD 0x0817
+#define ZORRO_PROD_ICD_ADVANTAGE_2000_SCSI ZORRO_ID(ICD, 0x01, 0)
+#define ZORRO_PROD_ICD_ADVANTAGE_IDE ZORRO_ID(ICD, 0x03, 0)
+#define ZORRO_PROD_ICD_ADVANTAGE_2080_RAM ZORRO_ID(ICD, 0x04, 0)
+
+#define ZORRO_MANUF_KUPKE_2 0x0819
+#define ZORRO_PROD_KUPKE_OMTI ZORRO_ID(KUPKE_2, 0x01, 0)
+#define ZORRO_PROD_KUPKE_SCSI_II ZORRO_ID(KUPKE_2, 0x02, 0)
+#define ZORRO_PROD_KUPKE_GOLEM_BOX ZORRO_ID(KUPKE_2, 0x03, 0)
+#define ZORRO_PROD_KUPKE_030_882 ZORRO_ID(KUPKE_2, 0x04, 0)
+#define ZORRO_PROD_KUPKE_SCSI_AT ZORRO_ID(KUPKE_2, 0x05, 0)
+
+#define ZORRO_MANUF_GREAT_VALLEY_PRODUCTS_3 0x081D
+#define ZORRO_PROD_GVP_A2000_RAM8 ZORRO_ID(GREAT_VALLEY_PRODUCTS_3, 0x09, 0)
+#define ZORRO_PROD_GVP_IMPACT_SERIES_II_RAM_2 ZORRO_ID(GREAT_VALLEY_PRODUCTS_3, 0x0A, 0)
+
+#define ZORRO_MANUF_INTERWORKS_NETWORK 0x081E
+
+#define ZORRO_MANUF_HARDITAL_SYNTHESIS 0x0820
+#define ZORRO_PROD_HARDITAL_SYNTHESIS_TQM_68030_68882 ZORRO_ID(HARDITAL_SYNTHESIS, 0x14, 0)
+
+#define ZORRO_MANUF_APPLIED_ENGINEERING 0x0828
+#define ZORRO_PROD_APPLIED_ENGINEERING_DL2000 ZORRO_ID(APPLIED_ENGINEERING, 0x10, 0)
+#define ZORRO_PROD_APPLIED_ENGINEERING_RAM_WORKS ZORRO_ID(APPLIED_ENGINEERING, 0xE0, 0)
+
+#define ZORRO_MANUF_BSC_ALFADATA_3 0x082C
+#define ZORRO_PROD_BSC_OKTAGON_2008 ZORRO_ID(BSC_ALFADATA_3, 0x05, 0)
+#define ZORRO_PROD_BSC_TANDEM_AT_2008_508 ZORRO_ID(BSC_ALFADATA_3, 0x06, 0)
+#define ZORRO_PROD_BSC_ALFA_RAM_1200 ZORRO_ID(BSC_ALFADATA_3, 0x07, 0)
+#define ZORRO_PROD_BSC_OKTAGON_2008_RAM ZORRO_ID(BSC_ALFADATA_3, 0x08, 0)
+#define ZORRO_PROD_BSC_MULTIFACE_I ZORRO_ID(BSC_ALFADATA_3, 0x10, 0)
+#define ZORRO_PROD_BSC_MULTIFACE_II ZORRO_ID(BSC_ALFADATA_3, 0x11, 0)
+#define ZORRO_PROD_BSC_MULTIFACE_III ZORRO_ID(BSC_ALFADATA_3, 0x12, 0)
+#define ZORRO_PROD_BSC_FRAMEMASTER_II ZORRO_ID(BSC_ALFADATA_3, 0x20, 0)
+#define ZORRO_PROD_BSC_GRAFFITI_RAM ZORRO_ID(BSC_ALFADATA_3, 0x21, 0)
+#define ZORRO_PROD_BSC_GRAFFITI_REG ZORRO_ID(BSC_ALFADATA_3, 0x22, 0)
+#define ZORRO_PROD_BSC_ISDN_MASTERCARD ZORRO_ID(BSC_ALFADATA_3, 0x40, 0)
+#define ZORRO_PROD_BSC_ISDN_MASTERCARD_II ZORRO_ID(BSC_ALFADATA_3, 0x41, 0)
+
+#define ZORRO_MANUF_PHOENIX 0x0835
+#define ZORRO_PROD_PHOENIX_ST506 ZORRO_ID(PHOENIX, 0x21, 0)
+#define ZORRO_PROD_PHOENIX_SCSI ZORRO_ID(PHOENIX, 0x22, 0)
+#define ZORRO_PROD_PHOENIX_RAM ZORRO_ID(PHOENIX, 0xBE, 0)
+
+#define ZORRO_MANUF_ADVANCED_STORAGE_SYSTEMS 0x0836
+#define ZORRO_PROD_ADVANCED_STORAGE_SYSTEMS_NEXUS ZORRO_ID(ADVANCED_STORAGE_SYSTEMS, 0x01, 0)
+#define ZORRO_PROD_ADVANCED_STORAGE_SYSTEMS_NEXUS_RAM ZORRO_ID(ADVANCED_STORAGE_SYSTEMS, 0x08, 0)
+
+#define ZORRO_MANUF_IMPULSE 0x0838
+#define ZORRO_PROD_IMPULSE_FIRECRACKER_24 ZORRO_ID(IMPULSE, 0x00, 0)
+
+#define ZORRO_MANUF_IVS 0x0840
+#define ZORRO_PROD_IVS_GRANDSLAM_PIC_2 ZORRO_ID(IVS, 0x02, 0)
+#define ZORRO_PROD_IVS_GRANDSLAM_PIC_1 ZORRO_ID(IVS, 0x04, 0)
+#define ZORRO_PROD_IVS_OVERDRIVE ZORRO_ID(IVS, 0x10, 0)
+#define ZORRO_PROD_IVS_TRUMPCARD_CLASSIC ZORRO_ID(IVS, 0x30, 0)
+#define ZORRO_PROD_IVS_TRUMPCARD_PRO_GRANDSLAM ZORRO_ID(IVS, 0x34, 0)
+#define ZORRO_PROD_IVS_META_4 ZORRO_ID(IVS, 0x40, 0)
+#define ZORRO_PROD_IVS_WAVETOOLS ZORRO_ID(IVS, 0xBF, 0)
+#define ZORRO_PROD_IVS_VECTOR_1 ZORRO_ID(IVS, 0xF3, 0)
+#define ZORRO_PROD_IVS_VECTOR_2 ZORRO_ID(IVS, 0xF4, 0)
+
+#define ZORRO_MANUF_VECTOR_1 0x0841
+#define ZORRO_PROD_VECTOR_CONNECTION_1 ZORRO_ID(VECTOR_1, 0xE3, 0)
+
+#define ZORRO_MANUF_XPERT_PRODEV 0x0845
+#define ZORRO_PROD_XPERT_PRODEV_VISIONA_RAM ZORRO_ID(XPERT_PRODEV, 0x01, 0)
+#define ZORRO_PROD_XPERT_PRODEV_VISIONA_REG ZORRO_ID(XPERT_PRODEV, 0x02, 0)
+#define ZORRO_PROD_XPERT_PRODEV_MERLIN_RAM ZORRO_ID(XPERT_PRODEV, 0x03, 0)
+#define ZORRO_PROD_XPERT_PRODEV_MERLIN_REG_1 ZORRO_ID(XPERT_PRODEV, 0x04, 0)
+#define ZORRO_PROD_XPERT_PRODEV_MERLIN_REG_2 ZORRO_ID(XPERT_PRODEV, 0xC9, 0)
+
+#define ZORRO_MANUF_HYDRA_SYSTEMS 0x0849
+#define ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET ZORRO_ID(HYDRA_SYSTEMS, 0x01, 0)
+
+#define ZORRO_MANUF_SUNRIZE_INDUSTRIES 0x084F
+#define ZORRO_PROD_SUNRIZE_INDUSTRIES_AD1012 ZORRO_ID(SUNRIZE_INDUSTRIES, 0x01, 0)
+#define ZORRO_PROD_SUNRIZE_INDUSTRIES_AD516 ZORRO_ID(SUNRIZE_INDUSTRIES, 0x02, 0)
+#define ZORRO_PROD_SUNRIZE_INDUSTRIES_DD512 ZORRO_ID(SUNRIZE_INDUSTRIES, 0x03, 0)
+
+#define ZORRO_MANUF_TRICERATOPS 0x0850
+#define ZORRO_PROD_TRICERATOPS_MULTI_IO ZORRO_ID(TRICERATOPS, 0x01, 0)
+
+#define ZORRO_MANUF_APPLIED_MAGIC 0x0851
+#define ZORRO_PROD_APPLIED_MAGIC_DMI_RESOLVER ZORRO_ID(APPLIED_MAGIC, 0x01, 0)
+#define ZORRO_PROD_APPLIED_MAGIC_DIGITAL_BROADCASTER ZORRO_ID(APPLIED_MAGIC, 0x06, 0)
+
+#define ZORRO_MANUF_GFX_BASE 0x085E
+#define ZORRO_PROD_GFX_BASE_GDA_1_VRAM ZORRO_ID(GFX_BASE, 0x00, 0)
+#define ZORRO_PROD_GFX_BASE_GDA_1 ZORRO_ID(GFX_BASE, 0x01, 0)
+
+#define ZORRO_MANUF_ROCTEC 0x0860
+#define ZORRO_PROD_ROCTEC_RH_800C ZORRO_ID(ROCTEC, 0x01, 0)
+#define ZORRO_PROD_ROCTEC_RH_800C_RAM ZORRO_ID(ROCTEC, 0x01, 0)
+
+#define ZORRO_MANUF_KATO 0x0861
+#define ZORRO_PROD_KATO_MELODY ZORRO_ID(KATO, 0x80, 0)
+/* ID clash!! */
+#define ZORRO_MANUF_HELFRICH_1 0x0861
+#define ZORRO_PROD_HELFRICH_RAINBOW_II ZORRO_ID(HELFRICH_1, 0x20, 0)
+#define ZORRO_PROD_HELFRICH_RAINBOW_III ZORRO_ID(HELFRICH_1, 0x21, 0)
+
+#define ZORRO_MANUF_ATLANTIS 0x0862
+
+#define ZORRO_MANUF_PROTAR 0x0864
+
+#define ZORRO_MANUF_ACS 0x0865
+
+#define ZORRO_MANUF_SOFTWARE_RESULTS_ENTERPRISES 0x0866
+#define ZORRO_PROD_SOFTWARE_RESULTS_ENTERPRISES_GOLDEN_GATE_2_BUS_PLUS ZORRO_ID(SOFTWARE_RESULTS_ENTERPRISES, 0x01, 0)
+
+#define ZORRO_MANUF_MASOBOSHI 0x086D
+#define ZORRO_PROD_MASOBOSHI_MASTER_CARD_SC201 ZORRO_ID(MASOBOSHI, 0x03, 0)
+#define ZORRO_PROD_MASOBOSHI_MASTER_CARD_MC702 ZORRO_ID(MASOBOSHI, 0x04, 0)
+#define ZORRO_PROD_MASOBOSHI_MVD_819 ZORRO_ID(MASOBOSHI, 0x07, 0)
+
+#define ZORRO_MANUF_MAINHATTAN_DATA 0x086F
+#define ZORRO_PROD_MAINHATTAN_DATA_IDE ZORRO_ID(MAINHATTAN_DATA, 0x01, 0)
+
+#define ZORRO_MANUF_VILLAGE_TRONIC 0x0877
+#define ZORRO_PROD_VILLAGE_TRONIC_DOMINO_RAM ZORRO_ID(VILLAGE_TRONIC, 0x01, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_DOMINO_REG ZORRO_ID(VILLAGE_TRONIC, 0x02, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_DOMINO_16M_PROTOTYPE ZORRO_ID(VILLAGE_TRONIC, 0x03, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM ZORRO_ID(VILLAGE_TRONIC, 0x0B, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG ZORRO_ID(VILLAGE_TRONIC, 0x0C, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE ZORRO_ID(VILLAGE_TRONIC, 0x0D, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG ZORRO_ID(VILLAGE_TRONIC, 0x17, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3 ZORRO_ID(VILLAGE_TRONIC, 0x18, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_ARIADNE ZORRO_ID(VILLAGE_TRONIC, 0xC9, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2 ZORRO_ID(VILLAGE_TRONIC, 0xCA, 0)
+
+#define ZORRO_MANUF_UTILITIES_UNLIMITED 0x087B
+#define ZORRO_PROD_UTILITIES_UNLIMITED_EMPLANT_DELUXE ZORRO_ID(UTILITIES_UNLIMITED, 0x15, 0)
+#define ZORRO_PROD_UTILITIES_UNLIMITED_EMPLANT_DELUXE2 ZORRO_ID(UTILITIES_UNLIMITED, 0x20, 0)
+
+#define ZORRO_MANUF_AMITRIX 0x0880
+#define ZORRO_PROD_AMITRIX_MULTI_IO ZORRO_ID(AMITRIX, 0x01, 0)
+#define ZORRO_PROD_AMITRIX_CD_RAM ZORRO_ID(AMITRIX, 0x02, 0)
+
+#define ZORRO_MANUF_ARMAX 0x0885
+#define ZORRO_PROD_ARMAX_OMNIBUS ZORRO_ID(ARMAX, 0x00, 0)
+
+#define ZORRO_MANUF_ZEUS 0x088D
+#define ZORRO_PROD_ZEUS_SPIDER ZORRO_ID(ZEUS, 0x04, 0)
+
+#define ZORRO_MANUF_NEWTEK 0x088F
+#define ZORRO_PROD_NEWTEK_VIDEOTOASTER ZORRO_ID(NEWTEK, 0x00, 0)
+
+#define ZORRO_MANUF_M_TECH_GERMANY 0x0890
+#define ZORRO_PROD_MTEC_AT500_2 ZORRO_ID(M_TECH_GERMANY, 0x01, 0)
+#define ZORRO_PROD_MTEC_68030 ZORRO_ID(M_TECH_GERMANY, 0x03, 0)
+#define ZORRO_PROD_MTEC_68020I ZORRO_ID(M_TECH_GERMANY, 0x06, 0)
+#define ZORRO_PROD_MTEC_A1200_T68030_RTC ZORRO_ID(M_TECH_GERMANY, 0x20, 0)
+#define ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530 ZORRO_ID(M_TECH_GERMANY, 0x21, 0)
+#define ZORRO_PROD_MTEC_8_MB_RAM ZORRO_ID(M_TECH_GERMANY, 0x22, 0)
+#define ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE ZORRO_ID(M_TECH_GERMANY, 0x24, 0)
+
+#define ZORRO_MANUF_GREAT_VALLEY_PRODUCTS_4 0x0891
+#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x01, 0)
+#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x02, 0)
+
+#define ZORRO_MANUF_APOLLO_1 0x0892
+#define ZORRO_PROD_APOLLO_A1200 ZORRO_ID(APOLLO_1, 0x01, 0)
+
+#define ZORRO_MANUF_HELFRICH_2 0x0893
+#define ZORRO_PROD_HELFRICH_PICCOLO_RAM ZORRO_ID(HELFRICH_2, 0x05, 0)
+#define ZORRO_PROD_HELFRICH_PICCOLO_REG ZORRO_ID(HELFRICH_2, 0x06, 0)
+#define ZORRO_PROD_HELFRICH_PEGGY_PLUS_MPEG ZORRO_ID(HELFRICH_2, 0x07, 0)
+#define ZORRO_PROD_HELFRICH_VIDEOCRUNCHER ZORRO_ID(HELFRICH_2, 0x08, 0)
+#define ZORRO_PROD_HELFRICH_SD64_RAM ZORRO_ID(HELFRICH_2, 0x0A, 0)
+#define ZORRO_PROD_HELFRICH_SD64_REG ZORRO_ID(HELFRICH_2, 0x0B, 0)
+
+#define ZORRO_MANUF_MACROSYSTEMS_USA 0x089B
+#define ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx ZORRO_ID(MACROSYSTEMS_USA, 0x13, 0)
+
+#define ZORRO_MANUF_ELBOX_COMPUTER 0x089E
+#define ZORRO_PROD_ELBOX_COMPUTER_1200_4 ZORRO_ID(ELBOX_COMPUTER, 0x06, 0)
+
+#define ZORRO_MANUF_HARMS_PROFESSIONAL 0x0A00
+#define ZORRO_PROD_HARMS_PROFESSIONAL_030_PLUS ZORRO_ID(HARMS_PROFESSIONAL, 0x10, 0)
+#define ZORRO_PROD_HARMS_PROFESSIONAL_3500 ZORRO_ID(HARMS_PROFESSIONAL, 0xD0, 0)
+
+#define ZORRO_MANUF_MICRONIK 0x0A50
+#define ZORRO_PROD_MICRONIK_RCA_120 ZORRO_ID(MICRONIK, 0x0A, 0)
+
+#define ZORRO_MANUF_MICRONIK2 0x0F0F
+#define ZORRO_PROD_MICRONIK2_Z3I ZORRO_ID(MICRONIK2, 0x01, 0)
+
+#define ZORRO_MANUF_MEGAMICRO 0x1000
+#define ZORRO_PROD_MEGAMICRO_SCRAM_500 ZORRO_ID(MEGAMICRO, 0x03, 0)
+#define ZORRO_PROD_MEGAMICRO_SCRAM_500_RAM ZORRO_ID(MEGAMICRO, 0x04, 0)
+
+#define ZORRO_MANUF_IMTRONICS_2 0x1028
+#define ZORRO_PROD_IMTRONICS_HURRICANE_2800_3 ZORRO_ID(IMTRONICS_2, 0x39, 0)
+#define ZORRO_PROD_IMTRONICS_HURRICANE_2800_4 ZORRO_ID(IMTRONICS_2, 0x57, 0)
+
+/* unofficial ID */
+#define ZORRO_MANUF_INDIVIDUAL_COMPUTERS 0x1212
+#define ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA ZORRO_ID(INDIVIDUAL_COMPUTERS, 0x00, 0)
+#define ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL ZORRO_ID(INDIVIDUAL_COMPUTERS, 0x2A, 0)
+
+#define ZORRO_MANUF_KUPKE_3 0x1248
+#define ZORRO_PROD_KUPKE_GOLEM_HD_3000 ZORRO_ID(KUPKE_3, 0x01, 0)
+
+#define ZORRO_MANUF_ITH 0x1388
+#define ZORRO_PROD_ITH_ISDN_MASTER_II ZORRO_ID(ITH, 0x01, 0)
+
+#define ZORRO_MANUF_VMC 0x1389
+#define ZORRO_PROD_VMC_ISDN_BLASTER_Z2 ZORRO_ID(VMC, 0x01, 0)
+#define ZORRO_PROD_VMC_HYPERCOM_4 ZORRO_ID(VMC, 0x02, 0)
+
+#define ZORRO_MANUF_INFORMATION 0x157C
+#define ZORRO_PROD_INFORMATION_ISDN_ENGINE_I ZORRO_ID(INFORMATION, 0x64, 0)
+
+#define ZORRO_MANUF_VORTEX 0x2017
+#define ZORRO_PROD_VORTEX_GOLDEN_GATE_80386SX ZORRO_ID(VORTEX, 0x07, 0)
+#define ZORRO_PROD_VORTEX_GOLDEN_GATE_RAM ZORRO_ID(VORTEX, 0x08, 0)
+#define ZORRO_PROD_VORTEX_GOLDEN_GATE_80486 ZORRO_ID(VORTEX, 0x09, 0)
+
+#define ZORRO_MANUF_EXPANSION_SYSTEMS 0x2062
+#define ZORRO_PROD_EXPANSION_SYSTEMS_DATAFLYER_4000SX ZORRO_ID(EXPANSION_SYSTEMS, 0x01, 0)
+#define ZORRO_PROD_EXPANSION_SYSTEMS_DATAFLYER_4000SX_RAM ZORRO_ID(EXPANSION_SYSTEMS, 0x02, 0)
+
+#define ZORRO_MANUF_READYSOFT 0x2100
+#define ZORRO_PROD_READYSOFT_AMAX_II_IV ZORRO_ID(READYSOFT, 0x01, 0)
+
+#define ZORRO_MANUF_PHASE5 0x2140
+#define ZORRO_PROD_PHASE5_BLIZZARD_RAM ZORRO_ID(PHASE5, 0x01, 0)
+#define ZORRO_PROD_PHASE5_BLIZZARD ZORRO_ID(PHASE5, 0x02, 0)
+#define ZORRO_PROD_PHASE5_BLIZZARD_1220_IV ZORRO_ID(PHASE5, 0x06, 0)
+#define ZORRO_PROD_PHASE5_FASTLANE_Z3_RAM ZORRO_ID(PHASE5, 0x0A, 0)
+#define ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060 ZORRO_ID(PHASE5, 0x0B, 0)
+#define ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM ZORRO_ID(PHASE5, 0x0C, 0)
+#define ZORRO_PROD_PHASE5_BLIZZARD_1230 ZORRO_ID(PHASE5, 0x0D, 0)
+#define ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260 ZORRO_ID(PHASE5, 0x11, 0)
+#define ZORRO_PROD_PHASE5_BLIZZARD_2060 ZORRO_ID(PHASE5, 0x18, 0)
+#define ZORRO_PROD_PHASE5_CYBERSTORM_MK_II ZORRO_ID(PHASE5, 0x19, 0)
+#define ZORRO_PROD_PHASE5_CYBERVISION64 ZORRO_ID(PHASE5, 0x22, 0)
+#define ZORRO_PROD_PHASE5_CYBERVISION64_3D_PROTOTYPE ZORRO_ID(PHASE5, 0x32, 0)
+#define ZORRO_PROD_PHASE5_CYBERVISION64_3D ZORRO_ID(PHASE5, 0x43, 0)
+#define ZORRO_PROD_PHASE5_CYBERSTORM_MK_III ZORRO_ID(PHASE5, 0x64, 0)
+#define ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS ZORRO_ID(PHASE5, 0x6e, 0)
+
+#define ZORRO_MANUF_DPS 0x2169
+#define ZORRO_PROD_DPS_PERSONAL_ANIMATION_RECORDER ZORRO_ID(DPS, 0x01, 0)
+
+#define ZORRO_MANUF_APOLLO_2 0x2200
+#define ZORRO_PROD_APOLLO_A620_68020_1 ZORRO_ID(APOLLO_2, 0x00, 0)
+#define ZORRO_PROD_APOLLO_A620_68020_2 ZORRO_ID(APOLLO_2, 0x01, 0)
+
+#define ZORRO_MANUF_APOLLO_3 0x2222
+#define ZORRO_PROD_APOLLO_AT_APOLLO ZORRO_ID(APOLLO_3, 0x22, 0)
+#define ZORRO_PROD_APOLLO_1230_1240_1260_2030_4040_4060 ZORRO_ID(APOLLO_3, 0x23, 0)
+
+#define ZORRO_MANUF_PETSOFF_LP 0x38A5
+#define ZORRO_PROD_PETSOFF_LP_DELFINA ZORRO_ID(PETSOFF_LP, 0x00, 0)
+#define ZORRO_PROD_PETSOFF_LP_DELFINA_LITE ZORRO_ID(PETSOFF_LP, 0x01, 0)
+
+#define ZORRO_MANUF_UWE_GERLACH 0x3FF7
+#define ZORRO_PROD_UWE_GERLACH_RAM_ROM ZORRO_ID(UWE_GERLACH, 0xd4, 0)
+
+#define ZORRO_MANUF_ACT 0x4231
+#define ZORRO_PROD_ACT_PRELUDE ZORRO_ID(ACT, 0x01, 0)
+
+#define ZORRO_MANUF_MACROSYSTEMS_GERMANY 0x4754
+#define ZORRO_PROD_MACROSYSTEMS_MAESTRO ZORRO_ID(MACROSYSTEMS_GERMANY, 0x03, 0)
+#define ZORRO_PROD_MACROSYSTEMS_VLAB ZORRO_ID(MACROSYSTEMS_GERMANY, 0x04, 0)
+#define ZORRO_PROD_MACROSYSTEMS_MAESTRO_PRO ZORRO_ID(MACROSYSTEMS_GERMANY, 0x05, 0)
+#define ZORRO_PROD_MACROSYSTEMS_RETINA ZORRO_ID(MACROSYSTEMS_GERMANY, 0x06, 0)
+#define ZORRO_PROD_MACROSYSTEMS_MULTI_EVOLUTION ZORRO_ID(MACROSYSTEMS_GERMANY, 0x08, 0)
+#define ZORRO_PROD_MACROSYSTEMS_TOCCATA ZORRO_ID(MACROSYSTEMS_GERMANY, 0x0C, 0)
+#define ZORRO_PROD_MACROSYSTEMS_RETINA_Z3 ZORRO_ID(MACROSYSTEMS_GERMANY, 0x10, 0)
+#define ZORRO_PROD_MACROSYSTEMS_VLAB_MOTION ZORRO_ID(MACROSYSTEMS_GERMANY, 0x12, 0)
+#define ZORRO_PROD_MACROSYSTEMS_ALTAIS ZORRO_ID(MACROSYSTEMS_GERMANY, 0x13, 0)
+#define ZORRO_PROD_MACROSYSTEMS_FALCON_040 ZORRO_ID(MACROSYSTEMS_GERMANY, 0xFD, 0)
+
+#define ZORRO_MANUF_COMBITEC 0x6766
+
+#define ZORRO_MANUF_SKI_PERIPHERALS 0x8000
+#define ZORRO_PROD_SKI_PERIPHERALS_MAST_FIREBALL ZORRO_ID(SKI_PERIPHERALS, 0x08, 0)
+#define ZORRO_PROD_SKI_PERIPHERALS_SCSI_DUAL_SERIAL ZORRO_ID(SKI_PERIPHERALS, 0x80, 0)
+
+#define ZORRO_MANUF_REIS_WARE_2 0xA9AD
+#define ZORRO_PROD_REIS_WARE_SCAN_KING ZORRO_ID(REIS_WARE_2, 0x11, 0)
+
+#define ZORRO_MANUF_CAMERON 0xAA01
+#define ZORRO_PROD_CAMERON_PERSONAL_A4 ZORRO_ID(CAMERON, 0x10, 0)
+
+#define ZORRO_MANUF_REIS_WARE 0xAA11
+#define ZORRO_PROD_REIS_WARE_HANDYSCANNER ZORRO_ID(REIS_WARE, 0x11, 0)
+
+#define ZORRO_MANUF_PHOENIX_2 0xB5A8
+#define ZORRO_PROD_PHOENIX_ST506_2 ZORRO_ID(PHOENIX_2, 0x21, 0)
+#define ZORRO_PROD_PHOENIX_SCSI_2 ZORRO_ID(PHOENIX_2, 0x22, 0)
+#define ZORRO_PROD_PHOENIX_RAM_2 ZORRO_ID(PHOENIX_2, 0xBE, 0)
+
+#define ZORRO_MANUF_COMBITEC_2 0xC008
+#define ZORRO_PROD_COMBITEC_HD ZORRO_ID(COMBITEC_2, 0x2A, 0)
+#define ZORRO_PROD_COMBITEC_SRAM ZORRO_ID(COMBITEC_2, 0x2B, 0)
+
+
+ /*
+ * Test and illegal Manufacturer IDs.
+ */
+
+#define ZORRO_MANUF_HACKER 0x07DB
+#define ZORRO_PROD_GENERAL_PROTOTYPE ZORRO_ID(HACKER, 0x00, 0)
+#define ZORRO_PROD_HACKER_SCSI ZORRO_ID(HACKER, 0x01, 0)
+#define ZORRO_PROD_RESOURCE_MANAGEMENT_FORCE_QUICKNET_QN2000 ZORRO_ID(HACKER, 0x02, 0)
+#define ZORRO_PROD_VECTOR_CONNECTION_2 ZORRO_ID(HACKER, 0xE0, 0)
+#define ZORRO_PROD_VECTOR_CONNECTION_3 ZORRO_ID(HACKER, 0xE1, 0)
+#define ZORRO_PROD_VECTOR_CONNECTION_4 ZORRO_ID(HACKER, 0xE2, 0)
+#define ZORRO_PROD_VECTOR_CONNECTION_5 ZORRO_ID(HACKER, 0xE3, 0)
+
+
+ /*
+ * GVP identifies most of its products through the 'extended product code'
+ * (epc). The epc has to be ANDed with the GVP_PRODMASK before the
+ * identification.
+ */
+
+#define GVP_PRODMASK (0xf8)
+#define GVP_SCSICLKMASK (0x01)
+
+enum GVP_flags {
+ GVP_IO = 0x01,
+ GVP_ACCEL = 0x02,
+ GVP_SCSI = 0x04,
+ GVP_24BITDMA = 0x08,
+ GVP_25BITDMA = 0x10,
+ GVP_NOBANK = 0x20,
+ GVP_14MHZ = 0x40,
+};
+
+
+struct Node {
+ struct Node *ln_Succ; /* Pointer to next (successor) */
+ struct Node *ln_Pred; /* Pointer to previous (predecessor) */
+ __u8 ln_Type;
+ __s8 ln_Pri; /* Priority, for sorting */
+ __s8 *ln_Name; /* ID string, null terminated */
+} __attribute__ ((packed));
+
+struct ExpansionRom {
+ /* -First 16 bytes of the expansion ROM */
+ __u8 er_Type; /* Board type, size and flags */
+ __u8 er_Product; /* Product number, assigned by manufacturer */
+ __u8 er_Flags; /* Flags */
+ __u8 er_Reserved03; /* Must be zero ($ff inverted) */
+ __u16 er_Manufacturer; /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */
+ __u32 er_SerialNumber; /* Available for use by manufacturer */
+ __u16 er_InitDiagVec; /* Offset to optional "DiagArea" structure */
+ __u8 er_Reserved0c;
+ __u8 er_Reserved0d;
+ __u8 er_Reserved0e;
+ __u8 er_Reserved0f;
+} __attribute__ ((packed));
+
+/* er_Type board type bits */
+#define ERT_TYPEMASK 0xc0
+#define ERT_ZORROII 0xc0
+#define ERT_ZORROIII 0x80
+
+/* other bits defined in er_Type */
+#define ERTB_MEMLIST 5 /* Link RAM into free memory list */
+#define ERTF_MEMLIST (1<<5)
+
+struct ConfigDev {
+ struct Node cd_Node;
+ __u8 cd_Flags; /* (read/write) */
+ __u8 cd_Pad; /* reserved */
+ struct ExpansionRom cd_Rom; /* copy of board's expansion ROM */
+ void *cd_BoardAddr; /* where in memory the board was placed */
+ __u32 cd_BoardSize; /* size of board in bytes */
+ __u16 cd_SlotAddr; /* which slot number (PRIVATE) */
+ __u16 cd_SlotSize; /* number of slots (PRIVATE) */
+ void *cd_Driver; /* pointer to node of driver */
+ struct ConfigDev *cd_NextCD; /* linked list of drivers to config */
+ __u32 cd_Unused[4]; /* for whatever the driver wants */
+} __attribute__ ((packed));
+
+#else /* __ASSEMBLY__ */
+
+LN_Succ = 0
+LN_Pred = LN_Succ+4
+LN_Type = LN_Pred+4
+LN_Pri = LN_Type+1
+LN_Name = LN_Pri+1
+LN_sizeof = LN_Name+4
+
+ER_Type = 0
+ER_Product = ER_Type+1
+ER_Flags = ER_Product+1
+ER_Reserved03 = ER_Flags+1
+ER_Manufacturer = ER_Reserved03+1
+ER_SerialNumber = ER_Manufacturer+2
+ER_InitDiagVec = ER_SerialNumber+4
+ER_Reserved0c = ER_InitDiagVec+2
+ER_Reserved0d = ER_Reserved0c+1
+ER_Reserved0e = ER_Reserved0d+1
+ER_Reserved0f = ER_Reserved0e+1
+ER_sizeof = ER_Reserved0f+1
+
+CD_Node = 0
+CD_Flags = CD_Node+LN_sizeof
+CD_Pad = CD_Flags+1
+CD_Rom = CD_Pad+1
+CD_BoardAddr = CD_Rom+ER_sizeof
+CD_BoardSize = CD_BoardAddr+4
+CD_SlotAddr = CD_BoardSize+4
+CD_SlotSize = CD_SlotAddr+2
+CD_Driver = CD_SlotSize+2
+CD_NextCD = CD_Driver+4
+CD_Unused = CD_NextCD+4
+CD_sizeof = CD_Unused+(4*4)
+
+#endif /* __ASSEMBLY__ */
+
+#ifndef __ASSEMBLY__
+
+#define ZORRO_NUM_AUTO 16
+
+#ifdef __KERNEL__
+
+extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */
+extern struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO];
+
+
+ /*
+ * Zorro Functions
+ */
+
+extern void zorro_init(void);
+extern void zorro_proc_init(void);
+
+extern unsigned int zorro_find(zorro_id id, unsigned int part, unsigned int index);
+extern const struct ConfigDev *zorro_get_board(unsigned int key);
+extern void zorro_config_board(unsigned int key, unsigned int part);
+extern void zorro_unconfig_board(unsigned int key, unsigned int part);
+
+
+ /*
+ * Bitmask indicating portions of available Zorro II RAM that are unused
+ * by the system. Every bit represents a 64K chunk, for a maximum of 8MB
+ * (128 chunks, physical 0x00200000-0x009fffff).
+ *
+ * If you want to use (= allocate) portions of this RAM, you should clear
+ * the corresponding bits.
+ */
+
+extern __u32 zorro_unused_z2ram[4];
+
+#define Z2RAM_START (0x00200000)
+#define Z2RAM_END (0x00a00000)
+#define Z2RAM_SIZE (0x00800000)
+#define Z2RAM_CHUNKSIZE (0x00010000)
+#define Z2RAM_CHUNKMASK (0x0000ffff)
+#define Z2RAM_CHUNKSHIFT (16)
+
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_ZORRO_H */
diff --git a/pfinet/linux-src/include/net/addrconf.h b/pfinet/linux-src/include/net/addrconf.h
new file mode 100644
index 00000000..d711d0d5
--- /dev/null
+++ b/pfinet/linux-src/include/net/addrconf.h
@@ -0,0 +1,158 @@
+#ifndef _ADDRCONF_H
+#define _ADDRCONF_H
+
+#define RETRANS_TIMER HZ
+
+#define MAX_RTR_SOLICITATIONS 3
+#define RTR_SOLICITATION_INTERVAL (4*HZ)
+
+#define ADDR_CHECK_FREQUENCY (120*HZ)
+
+struct prefix_info {
+ __u8 type;
+ __u8 length;
+ __u8 prefix_len;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 onlink : 1,
+ autoconf : 1,
+ reserved : 6;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 reserved : 6,
+ autoconf : 1,
+ onlink : 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __u32 valid;
+ __u32 prefered;
+ __u32 reserved2;
+
+ struct in6_addr prefix;
+};
+
+
+#ifdef __KERNEL__
+
+#include <linux/in6.h>
+#include <linux/netdevice.h>
+#include <net/if_inet6.h>
+
+#define IN6_ADDR_HSIZE 16
+
+extern void addrconf_init(void);
+extern void addrconf_cleanup(void);
+
+extern int addrconf_notify(struct notifier_block *this,
+ unsigned long event,
+ void * data);
+
+extern int addrconf_add_ifaddr(void *arg);
+extern int addrconf_del_ifaddr(void *arg);
+extern int addrconf_set_dstaddr(void *arg);
+
+extern struct inet6_ifaddr * ipv6_chk_addr(struct in6_addr *addr,
+ struct device *dev, int nd);
+extern int ipv6_get_saddr(struct dst_entry *dst,
+ struct in6_addr *daddr,
+ struct in6_addr *saddr);
+extern struct inet6_ifaddr * ipv6_get_lladdr(struct device *dev);
+
+/*
+ * multicast prototypes (mcast.c)
+ */
+extern int ipv6_sock_mc_join(struct sock *sk,
+ int ifindex,
+ struct in6_addr *addr);
+extern int ipv6_sock_mc_drop(struct sock *sk,
+ int ifindex,
+ struct in6_addr *addr);
+extern void ipv6_sock_mc_close(struct sock *sk);
+
+extern int ipv6_dev_mc_inc(struct device *dev,
+ struct in6_addr *addr);
+extern int ipv6_dev_mc_dec(struct device *dev,
+ struct in6_addr *addr);
+extern void ipv6_mc_up(struct inet6_dev *idev);
+extern void ipv6_mc_down(struct inet6_dev *idev);
+extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
+extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
+
+extern int ipv6_chk_mcast_addr(struct device *dev,
+ struct in6_addr *addr);
+
+extern void addrconf_prefix_rcv(struct device *dev,
+ u8 *opt, int len);
+
+extern struct inet6_dev * ipv6_get_idev(struct device *dev);
+
+extern void addrconf_forwarding_on(void);
+/*
+ * Hash function taken from net_alias.c
+ */
+
+static __inline__ u8 ipv6_addr_hash(struct in6_addr *addr)
+{
+ __u32 word;
+ unsigned tmp;
+
+ /*
+ * We perform the hash function over the last 64 bits of the address
+ * This will include the IEEE address token on links that support it.
+ */
+
+ word = addr->s6_addr[2] ^ addr->s6_addr32[3];
+ tmp = word ^ (word>>16);
+ tmp ^= (tmp >> 8);
+
+ return ((tmp ^ (tmp >> 4)) & 0x0f);
+}
+
+static __inline__ int ipv6_devindex_hash(int ifindex)
+{
+ return ifindex & (IN6_ADDR_HSIZE - 1);
+}
+
+/*
+ * compute link-local solicited-node multicast address
+ */
+
+extern __inline__ void addrconf_addr_solict_mult_old(struct in6_addr *addr,
+ struct in6_addr *solicited)
+{
+ ipv6_addr_set(solicited,
+ __constant_htonl(0xFF020000), 0,
+ __constant_htonl(0x1), addr->s6_addr32[3]);
+}
+
+extern __inline__ void addrconf_addr_solict_mult_new(struct in6_addr *addr,
+ struct in6_addr *solicited)
+{
+ ipv6_addr_set(solicited,
+ __constant_htonl(0xFF020000), 0,
+ __constant_htonl(0x1),
+ __constant_htonl(0xFF000000) | addr->s6_addr32[3]);
+}
+
+
+extern __inline__ void ipv6_addr_all_nodes(struct in6_addr *addr)
+{
+ ipv6_addr_set(addr,
+ __constant_htonl(0xFF020000), 0, 0,
+ __constant_htonl(0x1));
+}
+
+extern __inline__ void ipv6_addr_all_routers(struct in6_addr *addr)
+{
+ ipv6_addr_set(addr,
+ __constant_htonl(0xFF020000), 0, 0,
+ __constant_htonl(0x2));
+}
+
+extern __inline__ int ipv6_addr_is_multicast(struct in6_addr *addr)
+{
+ return (addr->s6_addr32[0] & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000);
+}
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/net/af_unix.h b/pfinet/linux-src/include/net/af_unix.h
new file mode 100644
index 00000000..06970ac6
--- /dev/null
+++ b/pfinet/linux-src/include/net/af_unix.h
@@ -0,0 +1,35 @@
+#ifndef __LINUX_NET_AFUNIX_H
+#define __LINUX_NET_AFUNIX_H
+extern void unix_proto_init(struct net_proto *pro);
+extern struct proto_ops unix_proto_ops;
+extern void unix_inflight(struct file *fp);
+extern void unix_notinflight(struct file *fp);
+typedef struct sock unix_socket;
+extern void unix_gc(void);
+
+#define UNIX_HASH_SIZE 16
+
+extern unix_socket *unix_socket_table[UNIX_HASH_SIZE+1];
+
+#define forall_unix_sockets(i, s) for (i=0; i<=UNIX_HASH_SIZE; i++) \
+ for (s=unix_socket_table[i]; s; s=s->next)
+
+struct unix_address
+{
+ atomic_t refcnt;
+ int len;
+ unsigned hash;
+ struct sockaddr_un name[0];
+};
+
+struct unix_skb_parms
+{
+ struct ucred creds; /* Skb credentials */
+ struct scm_fp_list *fp; /* Passed files */
+ unsigned attr; /* Special attributes */
+};
+
+#define UNIXCB(skb) (*(struct unix_skb_parms*)&((skb)->cb))
+#define UNIXCREDS(skb) (&UNIXCB((skb)).creds)
+
+#endif
diff --git a/pfinet/linux-src/include/net/arp.h b/pfinet/linux-src/include/net/arp.h
new file mode 100644
index 00000000..b672bacb
--- /dev/null
+++ b/pfinet/linux-src/include/net/arp.h
@@ -0,0 +1,24 @@
+/* linux/net/inet/arp.h */
+#ifndef _ARP_H
+#define _ARP_H
+
+#include <linux/if_arp.h>
+#include <net/neighbour.h>
+
+extern struct neigh_table arp_tbl;
+
+extern void arp_init(void);
+extern int arp_rcv(struct sk_buff *skb, struct device *dev,
+ struct packet_type *pt);
+extern int arp_find(unsigned char *haddr, struct sk_buff *skb);
+extern int arp_ioctl(unsigned int cmd, void *arg);
+extern void arp_send(int type, int ptype, u32 dest_ip,
+ struct device *dev, u32 src_ip,
+ unsigned char *dest_hw, unsigned char *src_hw, unsigned char *th);
+extern int arp_bind_neighbour(struct dst_entry *dst);
+extern int arp_mc_map(u32 addr, u8 *haddr, struct device *dev, int dir);
+extern void arp_ifdown(struct device *dev);
+
+extern struct neigh_ops arp_broken_ops;
+
+#endif /* _ARP_H */
diff --git a/pfinet/linux-src/include/net/atalkcall.h b/pfinet/linux-src/include/net/atalkcall.h
new file mode 100644
index 00000000..726e33cd
--- /dev/null
+++ b/pfinet/linux-src/include/net/atalkcall.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void atalk_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/include/net/ax25.h b/pfinet/linux-src/include/net/ax25.h
new file mode 100644
index 00000000..2c8d20a6
--- /dev/null
+++ b/pfinet/linux-src/include/net/ax25.h
@@ -0,0 +1,349 @@
+/*
+ * Declarations of AX.25 type objects.
+ *
+ * Alan Cox (GW4PTS) 10/11/93
+ */
+
+#ifndef _AX25_H
+#define _AX25_H
+#include <linux/config.h>
+#include <linux/ax25.h>
+
+#define AX25_T1CLAMPLO 1
+#define AX25_T1CLAMPHI (30 * HZ)
+
+#define AX25_BPQ_HEADER_LEN 16
+#define AX25_KISS_HEADER_LEN 1
+
+#define AX25_HEADER_LEN 17
+#define AX25_ADDR_LEN 7
+#define AX25_DIGI_HEADER_LEN (AX25_MAX_DIGIS * AX25_ADDR_LEN)
+#define AX25_MAX_HEADER_LEN (AX25_HEADER_LEN + AX25_DIGI_HEADER_LEN)
+
+/* AX.25 Protocol IDs */
+#define AX25_P_ROSE 0x01
+#define AX25_P_IP 0xCC
+#define AX25_P_ARP 0xCD
+#define AX25_P_TEXT 0xF0
+#define AX25_P_NETROM 0xCF
+#define AX25_P_SEGMENT 0x08
+
+/* AX.25 Segment control values */
+#define AX25_SEG_REM 0x7F
+#define AX25_SEG_FIRST 0x80
+
+#define AX25_CBIT 0x80 /* Command/Response bit */
+#define AX25_EBIT 0x01 /* HDLC Address Extension bit */
+#define AX25_HBIT 0x80 /* Has been repeated bit */
+
+#define AX25_SSSID_SPARE 0x60 /* Unused bits in SSID for standard AX.25 */
+#define AX25_ESSID_SPARE 0x20 /* Unused bits in SSID for extended AX.25 */
+#define AX25_DAMA_FLAG 0x20 /* Well, it is *NOT* unused! (dl1bke 951121 */
+
+#define AX25_COND_ACK_PENDING 0x01
+#define AX25_COND_REJECT 0x02
+#define AX25_COND_PEER_RX_BUSY 0x04
+#define AX25_COND_OWN_RX_BUSY 0x08
+#define AX25_COND_DAMA_MODE 0x10
+
+#ifndef _LINUX_NETDEVICE_H
+#include <linux/netdevice.h>
+#endif
+
+/* Upper sub-layer (LAPB) definitions */
+
+/* Control field templates */
+#define AX25_I 0x00 /* Information frames */
+#define AX25_S 0x01 /* Supervisory frames */
+#define AX25_RR 0x01 /* Receiver ready */
+#define AX25_RNR 0x05 /* Receiver not ready */
+#define AX25_REJ 0x09 /* Reject */
+#define AX25_U 0x03 /* Unnumbered frames */
+#define AX25_SABM 0x2f /* Set Asynchronous Balanced Mode */
+#define AX25_SABME 0x6f /* Set Asynchronous Balanced Mode Extended */
+#define AX25_DISC 0x43 /* Disconnect */
+#define AX25_DM 0x0f /* Disconnected mode */
+#define AX25_UA 0x63 /* Unnumbered acknowledge */
+#define AX25_FRMR 0x87 /* Frame reject */
+#define AX25_UI 0x03 /* Unnumbered information */
+
+#define AX25_PF 0x10 /* Poll/final bit for standard AX.25 */
+#define AX25_EPF 0x01 /* Poll/final bit for extended AX.25 */
+
+#define AX25_ILLEGAL 0x100 /* Impossible to be a real frame type */
+
+#define AX25_POLLOFF 0
+#define AX25_POLLON 1
+
+/* AX25 L2 C-bit */
+#define AX25_COMMAND 1
+#define AX25_RESPONSE 2
+
+/* Define Link State constants. */
+
+enum {
+ AX25_STATE_0,
+ AX25_STATE_1,
+ AX25_STATE_2,
+ AX25_STATE_3,
+ AX25_STATE_4
+};
+
+#define AX25_MODULUS 8 /* Standard AX.25 modulus */
+#define AX25_EMODULUS 128 /* Extended AX.25 modulus */
+
+enum {
+ AX25_PROTO_STD_SIMPLEX,
+ AX25_PROTO_STD_DUPLEX,
+ AX25_PROTO_DAMA_SLAVE,
+ AX25_PROTO_DAMA_MASTER
+};
+
+enum {
+ AX25_VALUES_IPDEFMODE, /* 0=DG 1=VC */
+ AX25_VALUES_AXDEFMODE, /* 0=Normal 1=Extended Seq Nos */
+ AX25_VALUES_BACKOFF, /* 0=None 1=Linear 2=Exponential */
+ AX25_VALUES_CONMODE, /* Allow connected modes - 0=No 1=no "PID text" 2=all PIDs */
+ AX25_VALUES_WINDOW, /* Default window size for standard AX.25 */
+ AX25_VALUES_EWINDOW, /* Default window size for extended AX.25 */
+ AX25_VALUES_T1, /* Default T1 timeout value */
+ AX25_VALUES_T2, /* Default T2 timeout value */
+ AX25_VALUES_T3, /* Default T3 timeout value */
+ AX25_VALUES_IDLE, /* Connected mode idle timer */
+ AX25_VALUES_N2, /* Default N2 value */
+ AX25_VALUES_PACLEN, /* AX.25 MTU */
+ AX25_VALUES_PROTOCOL, /* Std AX.25, DAMA Slave, DAMA Master */
+ AX25_VALUES_DS_TIMEOUT, /* DAMA Slave timeout */
+ AX25_MAX_VALUES /* THIS MUST REMAIN THE LAST ENTRY OF THIS LIST */
+};
+
+#define AX25_DEF_IPDEFMODE 0 /* Datagram */
+#define AX25_DEF_AXDEFMODE 0 /* Normal */
+#define AX25_DEF_BACKOFF 1 /* Linear backoff */
+#define AX25_DEF_CONMODE 2 /* Connected mode allowed */
+#define AX25_DEF_WINDOW 2 /* Window=2 */
+#define AX25_DEF_EWINDOW 32 /* Module-128 Window=32 */
+#define AX25_DEF_T1 (10 * HZ) /* T1=10s */
+#define AX25_DEF_T2 (3 * HZ) /* T2=3s */
+#define AX25_DEF_T3 (300 * HZ) /* T3=300s */
+#define AX25_DEF_N2 10 /* N2=10 */
+#define AX25_DEF_IDLE (0 * 60 * HZ) /* Idle=None */
+#define AX25_DEF_PACLEN 256 /* Paclen=256 */
+#define AX25_DEF_PROTOCOL AX25_PROTO_STD_SIMPLEX /* Standard AX.25 */
+#define AX25_DEF_DS_TIMEOUT (3 * 60 * HZ) /* DAMA timeout 3 minutes */
+
+typedef struct ax25_uid_assoc {
+ struct ax25_uid_assoc *next;
+ uid_t uid;
+ ax25_address call;
+} ax25_uid_assoc;
+
+typedef struct {
+ ax25_address calls[AX25_MAX_DIGIS];
+ unsigned char repeated[AX25_MAX_DIGIS];
+ unsigned char ndigi;
+ char lastrepeat;
+} ax25_digi;
+
+typedef struct ax25_route {
+ struct ax25_route *next;
+ ax25_address callsign;
+ struct device *dev;
+ ax25_digi *digipeat;
+ char ip_mode;
+} ax25_route;
+
+typedef struct {
+ char slave; /* slave_mode? */
+ struct timer_list slave_timer; /* timeout timer */
+ unsigned short slave_timeout; /* when? */
+} ax25_dama_info;
+
+#ifndef _LINUX_SYSCTL_H
+#include <linux/sysctl.h>
+#endif
+
+typedef struct ax25_dev {
+ struct ax25_dev *next;
+ struct device *dev;
+ struct device *forward;
+ struct ctl_table systable[AX25_MAX_VALUES+1];
+ int values[AX25_MAX_VALUES];
+#if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
+ ax25_dama_info dama;
+#endif
+} ax25_dev;
+
+typedef struct ax25_cb {
+ struct ax25_cb *next;
+ ax25_address source_addr, dest_addr;
+ ax25_digi *digipeat;
+ ax25_dev *ax25_dev;
+ unsigned char iamdigi;
+ unsigned char state, modulus, pidincl;
+ unsigned short vs, vr, va;
+ unsigned char condition, backoff;
+ unsigned char n2, n2count;
+ struct timer_list t1timer, t2timer, t3timer, idletimer;
+ unsigned long t1, t2, t3, idle, rtt;
+ unsigned short paclen, fragno, fraglen;
+ struct sk_buff_head write_queue;
+ struct sk_buff_head reseq_queue;
+ struct sk_buff_head ack_queue;
+ struct sk_buff_head frag_queue;
+ unsigned char window;
+ struct timer_list timer;
+ struct sock *sk; /* Backlink to socket */
+} ax25_cb;
+
+/* af_ax25.c */
+extern ax25_cb *volatile ax25_list;
+extern void ax25_free_cb(ax25_cb *);
+extern void ax25_insert_socket(ax25_cb *);
+struct sock *ax25_find_listener(ax25_address *, int, struct device *, int);
+struct sock *ax25_find_socket(ax25_address *, ax25_address *, int);
+extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct device *);
+extern struct sock *ax25_addr_match(ax25_address *);
+extern void ax25_send_to_raw(struct sock *, struct sk_buff *, int);
+extern void ax25_destroy_socket(ax25_cb *);
+extern ax25_cb *ax25_create_cb(void);
+extern void ax25_fillin_cb(ax25_cb *, ax25_dev *);
+extern int ax25_create(struct socket *, int);
+extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
+
+/* ax25_addr.c */
+extern ax25_address null_ax25_address;
+extern char *ax2asc(ax25_address *);
+extern ax25_address *asc2ax(char *);
+extern int ax25cmp(ax25_address *, ax25_address *);
+extern int ax25digicmp(ax25_digi *, ax25_digi *);
+extern unsigned char *ax25_addr_parse(unsigned char *, int, ax25_address *, ax25_address *, ax25_digi *, int *, int *);
+extern int ax25_addr_build(unsigned char *, ax25_address *, ax25_address *, ax25_digi *, int, int);
+extern int ax25_addr_size(ax25_digi *);
+extern void ax25_digi_invert(ax25_digi *, ax25_digi *);
+
+/* ax25_dev.c */
+extern ax25_dev *ax25_dev_list;
+extern ax25_dev *ax25_dev_ax25dev(struct device *);
+extern ax25_dev *ax25_addr_ax25dev(ax25_address *);
+extern void ax25_dev_device_up(struct device *);
+extern void ax25_dev_device_down(struct device *);
+extern int ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *);
+extern struct device *ax25_fwd_dev(struct device *);
+extern void ax25_dev_free(void);
+
+/* ax25_ds_in.c */
+extern int ax25_ds_frame_in(ax25_cb *, struct sk_buff *, int);
+
+/* ax25_ds_subr.c */
+extern void ax25_ds_nr_error_recovery(ax25_cb *);
+extern void ax25_ds_enquiry_response(ax25_cb *);
+extern void ax25_ds_establish_data_link(ax25_cb *);
+extern void ax25_dev_dama_on(ax25_dev *);
+extern void ax25_dev_dama_off(ax25_dev *);
+extern void ax25_dama_on(ax25_cb *);
+extern void ax25_dama_off(ax25_cb *);
+
+/* ax25_ds_timer.c */
+extern void ax25_ds_set_timer(ax25_dev *);
+extern void ax25_ds_del_timer(ax25_dev *);
+extern void ax25_ds_timer(ax25_cb *);
+extern void ax25_ds_t1_timeout(ax25_cb *);
+extern void ax25_ds_heartbeat_expiry(ax25_cb *);
+extern void ax25_ds_t3timer_expiry(ax25_cb *);
+extern void ax25_ds_idletimer_expiry(ax25_cb *);
+
+#include <net/ax25call.h>
+
+/* ax25_iface.c */
+extern int ax25_protocol_register(unsigned int, int (*)(struct sk_buff *, ax25_cb *));
+extern void ax25_protocol_release(unsigned int);
+extern int ax25_linkfail_register(void (*)(ax25_cb *, int));
+extern void ax25_linkfail_release(void (*)(ax25_cb *, int));
+extern int ax25_listen_register(ax25_address *, struct device *);
+extern void ax25_listen_release(ax25_address *, struct device *);
+extern int (*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
+extern int ax25_listen_mine(ax25_address *, struct device *);
+extern void ax25_link_failed(ax25_cb *, int);
+extern int ax25_protocol_is_registered(unsigned int);
+
+/* ax25_in.c */
+extern int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
+extern int ax25_kiss_rcv(struct sk_buff *, struct device *, struct packet_type *);
+
+/* ax25_ip.c */
+extern int ax25_encapsulate(struct sk_buff *, struct device *, unsigned short, void *, void *, unsigned int);
+extern int ax25_rebuild_header(struct sk_buff *);
+
+/* ax25_out.c */
+extern ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *, ax25_digi *, struct device *);
+extern void ax25_output(ax25_cb *, int, struct sk_buff *);
+extern void ax25_kick(ax25_cb *);
+extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
+extern void ax25_queue_xmit(struct sk_buff *);
+extern int ax25_check_iframes_acked(ax25_cb *, unsigned short);
+
+/* ax25_route.c */
+extern void ax25_rt_device_down(struct device *);
+extern int ax25_rt_ioctl(unsigned int, void *);
+extern int ax25_rt_get_info(char *, char **, off_t, int, int);
+extern int ax25_rt_autobind(ax25_cb *, ax25_address *);
+extern ax25_route *ax25_rt_find_route(ax25_address *, struct device *);
+extern struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *);
+extern void ax25_rt_free(void);
+
+/* ax25_std_in.c */
+extern int ax25_std_frame_in(ax25_cb *, struct sk_buff *, int);
+
+/* ax25_std_subr.c */
+extern void ax25_std_nr_error_recovery(ax25_cb *);
+extern void ax25_std_establish_data_link(ax25_cb *);
+extern void ax25_std_transmit_enquiry(ax25_cb *);
+extern void ax25_std_enquiry_response(ax25_cb *);
+extern void ax25_std_timeout_response(ax25_cb *);
+
+/* ax25_std_timer.c */
+extern void ax25_std_heartbeat_expiry(ax25_cb *);
+extern void ax25_std_t1timer_expiry(ax25_cb *);
+extern void ax25_std_t2timer_expiry(ax25_cb *);
+extern void ax25_std_t3timer_expiry(ax25_cb *);
+extern void ax25_std_idletimer_expiry(ax25_cb *);
+
+/* ax25_subr.c */
+extern void ax25_clear_queues(ax25_cb *);
+extern void ax25_frames_acked(ax25_cb *, unsigned short);
+extern void ax25_requeue_frames(ax25_cb *);
+extern int ax25_validate_nr(ax25_cb *, unsigned short);
+extern int ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);
+extern void ax25_send_control(ax25_cb *, int, int, int);
+extern void ax25_return_dm(struct device *, ax25_address *, ax25_address *, ax25_digi *);
+extern void ax25_calculate_t1(ax25_cb *);
+extern void ax25_calculate_rtt(ax25_cb *);
+extern void ax25_disconnect(ax25_cb *, int);
+
+/* ax25_timer.c */
+extern void ax25_start_heartbeat(ax25_cb *);
+extern void ax25_start_t1timer(ax25_cb *);
+extern void ax25_start_t2timer(ax25_cb *);
+extern void ax25_start_t3timer(ax25_cb *);
+extern void ax25_start_idletimer(ax25_cb *);
+extern void ax25_stop_heartbeat(ax25_cb *);
+extern void ax25_stop_t1timer(ax25_cb *);
+extern void ax25_stop_t2timer(ax25_cb *);
+extern void ax25_stop_t3timer(ax25_cb *);
+extern void ax25_stop_idletimer(ax25_cb *);
+extern int ax25_t1timer_running(ax25_cb *);
+extern unsigned long ax25_display_timer(struct timer_list *);
+
+/* ax25_uid.c */
+extern int ax25_uid_policy;
+extern ax25_address *ax25_findbyuid(uid_t);
+extern int ax25_uid_ioctl(int, struct sockaddr_ax25 *);
+extern int ax25_uid_get_info(char *, char **, off_t, int, int);
+extern void ax25_uid_free(void);
+
+/* sysctl_net_ax25.c */
+extern void ax25_register_sysctl(void);
+extern void ax25_unregister_sysctl(void);
+
+#endif
diff --git a/pfinet/linux-src/include/net/ax25call.h b/pfinet/linux-src/include/net/ax25call.h
new file mode 100644
index 00000000..68b8a70c
--- /dev/null
+++ b/pfinet/linux-src/include/net/ax25call.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void ax25_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/include/net/br.h b/pfinet/linux-src/include/net/br.h
new file mode 100644
index 00000000..4d79fc62
--- /dev/null
+++ b/pfinet/linux-src/include/net/br.h
@@ -0,0 +1,305 @@
+/*
+ * Constants and structure definitions for the bridging code
+ */
+
+#if !defined(One)
+#define Zero 0
+#define One 1
+#endif /* !defined(One) */
+
+#if !defined(TRUE)
+#define FALSE 0
+#define TRUE 1
+#endif /* !defined(TRUE) */
+
+/** port states. **/
+#define Disabled 0 /* (4.4 5) */
+#define Listening 1 /* (4.4.2) */
+#define Learning 2 /* (4.4.3) */
+#define Forwarding 3 /* (4 4 4) */
+#define Blocking 4 /* (4.4.1) */
+
+#define No_of_ports 8
+/* arbitrary choice, to allow the code below to compile */
+
+#define All_ports (No_of_ports + 1)
+
+/*
+ * We time out our entries in the FDB after this many seconds.
+ */
+#define FDB_TIMEOUT 20 /* JRP: 20s as NSC bridge code, was 300 for Linux */
+
+/*
+ * the following defines are the initial values used when the
+ * bridge is booted. These may be overridden when this bridge is
+ * not the root bridge. These are the recommended default values
+ * from the 802.1d specification.
+ */
+#define BRIDGE_MAX_AGE 20
+#define BRIDGE_HELLO_TIME 2
+#define BRIDGE_FORWARD_DELAY 15
+#define HOLD_TIME 1
+
+/* broacast/multicast storm limitation. This per source. */
+#define MAX_MCAST_PER_PERIOD 4
+#define MCAST_HOLD_TIME (10*HZ/100)
+
+#define Default_path_cost 10
+
+/*
+ * minimum increment possible to avoid underestimating age, allows for BPDU
+ * transmission time
+ */
+#define Message_age_increment 1
+
+#define No_port 0
+/*
+ * reserved value for Bridge's root port parameter indicating no root port,
+ * used when Bridge is the root - also used to indicate the source when
+ * a frame is being generated by a higher layer protocol on this host
+ */
+
+/** Configuration BPDU Parameters (4.5.1) **/
+
+typedef struct {
+ union {
+ struct {
+ unsigned short priority;
+ unsigned char ula[6];
+ } p_u;
+ unsigned int id[2];
+ } bi;
+} bridge_id_t;
+
+#define BRIDGE_PRIORITY bi.p_u.priority
+#define BRIDGE_ID_ULA bi.p_u.ula
+#define BRIDGE_ID bi.id
+
+/* JRP: on the network the flags field is between "type" and "root_id"
+ * this is unfortunated! To make the code portable to a RISC machine
+ * the pdus are now massaged a little bit for processing
+ */
+#define TOPOLOGY_CHANGE 0x01
+#define TOPOLOGY_CHANGE_ACK 0x80
+#define BRIDGE_BPDU_8021_CONFIG_SIZE 35 /* real size */
+#define BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET 4
+#define BRIDGE_BPDU_8021_PROTOCOL_ID 0
+#define BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID 0
+#define BRIDGE_LLC1_HS 3
+#define BRIDGE_LLC1_DSAP 0x42
+#define BRIDGE_LLC1_SSAP 0x42
+#define BRIDGE_LLC1_CTRL 0x03
+
+typedef struct {
+ unsigned short protocol_id;
+ unsigned char protocol_version_id;
+ unsigned char type;
+ bridge_id_t root_id; /* (4.5.1.1) */
+ unsigned int root_path_cost; /* (4.5.1.2) */
+ bridge_id_t bridge_id; /* (4.5.1.3) */
+ unsigned short port_id; /* (4.5.1.4) */
+ unsigned short message_age; /* (4.5.1.5) */
+ unsigned short max_age; /* (4.5.1.6) */
+ unsigned short hello_time; /* (4.5.1.7) */
+ unsigned short forward_delay; /* (4.5.1.8) */
+ unsigned char top_change_ack;
+ unsigned char top_change;
+} Config_bpdu;
+
+#ifdef __LITTLE_ENDIAN
+#define config_bpdu_hton(config_bpdu) \
+ (config_bpdu)->root_path_cost = htonl((config_bpdu)->root_path_cost); \
+ (config_bpdu)->port_id = htons((config_bpdu)->port_id); \
+ (config_bpdu)->message_age = htons((config_bpdu)->message_age); \
+ (config_bpdu)->max_age = htons((config_bpdu)->max_age); \
+ (config_bpdu)->hello_time = htons((config_bpdu)->hello_time); \
+ (config_bpdu)->forward_delay = htons((config_bpdu)->forward_delay);
+#else
+#define config_bpdu_hton(config_bpdu)
+#endif
+#define config_bpdu_ntoh config_bpdu_hton
+
+
+/** Topology Change Notification BPDU Parameters (4.5.2) **/
+
+typedef struct {
+ unsigned short protocol_id;
+ unsigned char protocol_version_id;
+ unsigned char type;
+} Tcn_bpdu;
+
+#define BPDU_TYPE_CONFIG 0
+#define BPDU_TYPE_TOPO_CHANGE 128
+
+/** Bridge Parameters (4.5.3) **/
+typedef struct {
+ bridge_id_t designated_root; /* (4.5.3.1) */
+ unsigned int root_path_cost; /* (4.5.3.2) */
+ unsigned int root_port; /* (4.5.3.3) */
+ unsigned short max_age; /* (4.5.3.4) */
+ unsigned short hello_time; /* (4.5.3.5) */
+ unsigned short forward_delay; /* (4.5.3.6) */
+ bridge_id_t bridge_id; /* (4.5.3.7) */
+ unsigned short bridge_max_age; /* (4.5.3.8) */
+ unsigned short bridge_hello_time; /* (4.5.3.9) */
+ unsigned short bridge_forward_delay; /* (4.5.3.10) */
+ unsigned int top_change_detected; /* (4.5.3.11) */
+ unsigned int top_change; /* (4.5.3.12) */
+ unsigned short topology_change_time; /* (4.5.3.13) */
+ unsigned short hold_time; /* (4.5.3.14) */
+} Bridge_data;
+
+/** Port Parameters (4.5.5) **/
+typedef struct {
+ unsigned short port_id; /* (4.5.5.1) */
+ unsigned int state; /* (4.5.5.2) */
+ unsigned int path_cost; /* (4.5.5.3) */
+ bridge_id_t designated_root; /* (4.5.5.4) */
+ unsigned int designated_cost; /* (4.5.5.5) */
+ bridge_id_t designated_bridge; /* (4.5.5.6) */
+ unsigned short designated_port; /* (4.5.5.7) */
+ unsigned int top_change_ack; /* (4.5.5.8) */
+ unsigned int config_pending; /* (4.5.5.9) */
+ struct device *dev;
+ struct fdb *fdb; /* head of per port fdb chain */
+} Port_data;
+
+
+
+/** types to support timers for this pseudo-implementation. **/
+typedef struct {
+ unsigned int active; /* timer in use. */
+ unsigned int value; /* current value of timer,
+ * counting up. */
+} Timer;
+
+struct fdb {
+ unsigned char ula[6];
+ unsigned char pad[2];
+ unsigned short port;
+ unsigned int timer;
+ unsigned short flags;
+#define FDB_ENT_VALID 0x01
+ unsigned short mcast_count;
+ unsigned int mcast_timer; /* oldest xxxxxcast */
+
+/* AVL tree of all addresses, sorted by address */
+ short fdb_avl_height;
+ struct fdb *fdb_avl_left;
+ struct fdb *fdb_avl_right;
+/* linked list of addresses for each port */
+ struct fdb *fdb_next;
+};
+
+/* data returned on BRCMD_DISPLAY_FDB */
+struct fdb_info {
+ unsigned char ula[6];
+ unsigned char port;
+ unsigned char flags;
+ unsigned int timer;
+};
+struct fdb_info_hdr {
+ int copied; /* nb of entries copied to user */
+ int not_copied; /* when user buffer is too small */
+ int cmd_time;
+};
+
+#define IS_BRIDGED 0x2e
+
+
+#define BR_MAX_PROTOCOLS 32
+#define BR_MAX_PROT_STATS BR_MAX_PROTOCOLS
+
+/* policy values for policy field */
+#define BR_ACCEPT 1
+#define BR_REJECT 0
+
+/* JRP: extra statistics for debug */
+typedef struct {
+ /* br_receive_frame counters */
+ int port_disable_up_stack;
+ int rcv_bpdu;
+ int notForwarding;
+ int forwarding_up_stack;
+ int unknown_state;
+
+ /* br_tx_frame counters */
+ int port_disable;
+ int port_not_disable;
+
+ /* br_forward counters */
+ int local_multicast;
+ int forwarded_multicast; /* up stack as well */
+ int flood_unicast;
+ int aged_flood_unicast;
+ int forwarded_unicast;
+ int forwarded_unicast_up_stack;
+ int forwarded_ip_up_stack;
+ int forwarded_ip_up_stack_lie; /* received on alternate device */
+ int arp_for_local_mac;
+ int drop_same_port;
+ int drop_same_port_aged;
+ int drop_multicast;
+} br_stats_counter;
+
+struct br_stat {
+ unsigned int flags;
+ Bridge_data bridge_data;
+ Port_data port_data[No_of_ports];
+ unsigned int policy;
+ unsigned int exempt_protocols;
+ unsigned short protocols[BR_MAX_PROTOCOLS];
+ unsigned short prot_id[BR_MAX_PROT_STATS]; /* Protocol encountered */
+ unsigned int prot_counter[BR_MAX_PROT_STATS]; /* How many packets ? */
+ br_stats_counter packet_cnts;
+};
+
+/* defined flags for br_stat.flags */
+#define BR_UP 0x0001 /* bridging enabled */
+#define BR_DEBUG 0x0002 /* debugging enabled */
+#define BR_PROT_STATS 0x0004 /* protocol statistics enabled */
+#define BR_STP_DISABLED 0x0008 /* Spanning tree protocol disabled */
+
+struct br_cf {
+ unsigned int cmd;
+ unsigned int arg1;
+ unsigned int arg2;
+};
+
+/* defined cmds */
+#define BRCMD_BRIDGE_ENABLE 1
+#define BRCMD_BRIDGE_DISABLE 2
+#define BRCMD_PORT_ENABLE 3 /* arg1 = port */
+#define BRCMD_PORT_DISABLE 4 /* arg1 = port */
+#define BRCMD_SET_BRIDGE_PRIORITY 5 /* arg1 = priority */
+#define BRCMD_SET_PORT_PRIORITY 6 /* arg1 = port, arg2 = priority */
+#define BRCMD_SET_PATH_COST 7 /* arg1 = port, arg2 = cost */
+#define BRCMD_DISPLAY_FDB 8 /* arg1 = port */
+#define BRCMD_ENABLE_DEBUG 9
+#define BRCMD_DISABLE_DEBUG 10
+#define BRCMD_SET_POLICY 11 /* arg1 = default policy (1==bridge all) */
+#define BRCMD_EXEMPT_PROTOCOL 12 /* arg1 = protocol (see net/if_ether.h) */
+#define BRCMD_ENABLE_PROT_STATS 13
+#define BRCMD_DISABLE_PROT_STATS 14
+#define BRCMD_ZERO_PROT_STATS 15
+#define BRCMD_TOGGLE_STP 16
+
+/* prototypes of exported bridging functions... */
+
+void br_init(void);
+int br_receive_frame(struct sk_buff *skb); /* 3.5 */
+int br_tx_frame(struct sk_buff *skb);
+int br_ioctl(unsigned int cmd, void *arg);
+int br_protocol_ok(unsigned short protocol);
+void requeue_fdb(struct fdb *node, int new_port);
+
+struct fdb *br_avl_find_addr(unsigned char addr[6]);
+struct fdb *br_avl_insert (struct fdb * new_node);
+void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,int* len, off_t offset, int length);
+int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
+void br_avl_delete_by_port(int port);
+/* externs */
+
+extern struct br_stat br_stats;
+extern Port_data port_info[];
+
diff --git a/pfinet/linux-src/include/net/checksum.h b/pfinet/linux-src/include/net/checksum.h
new file mode 100644
index 00000000..041d4760
--- /dev/null
+++ b/pfinet/linux-src/include/net/checksum.h
@@ -0,0 +1,110 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Checksumming functions for IP, TCP, UDP and so on
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Borrows very liberally from tcp.c and ip.c, see those
+ * files for more names.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Fixes:
+ *
+ * Ralf Baechle : generic ipv6 checksum
+ * <ralf@waldorf-gmbh.de>
+ */
+
+#ifndef _CHECKSUM_H
+#define _CHECKSUM_H
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <net/ip.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+
+#ifndef _HAVE_ARCH_IPV6_CSUM
+
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u16 len,
+ unsigned short proto,
+ unsigned int csum)
+{
+
+ int carry;
+ __u32 ulen;
+ __u32 uproto;
+
+ csum += saddr->s6_addr32[0];
+ carry = (csum < saddr->s6_addr32[0]);
+ csum += carry;
+
+ csum += saddr->s6_addr32[1];
+ carry = (csum < saddr->s6_addr32[1]);
+ csum += carry;
+
+ csum += saddr->s6_addr32[2];
+ carry = (csum < saddr->s6_addr32[2]);
+ csum += carry;
+
+ csum += saddr->s6_addr32[3];
+ carry = (csum < saddr->s6_addr32[3]);
+ csum += carry;
+
+ csum += daddr->s6_addr32[0];
+ carry = (csum < daddr->s6_addr32[0]);
+ csum += carry;
+
+ csum += daddr->s6_addr32[1];
+ carry = (csum < daddr->s6_addr32[1]);
+ csum += carry;
+
+ csum += daddr->s6_addr32[2];
+ carry = (csum < daddr->s6_addr32[2]);
+ csum += carry;
+
+ csum += daddr->s6_addr32[3];
+ carry = (csum < daddr->s6_addr32[3]);
+ csum += carry;
+
+ ulen = htonl((__u32) len);
+ csum += ulen;
+ carry = (csum < ulen);
+ csum += carry;
+
+ uproto = htonl(proto);
+ csum += uproto;
+ carry = (csum < uproto);
+ csum += carry;
+
+ return csum_fold(csum);
+}
+
+#endif
+
+#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
+extern __inline__
+unsigned int csum_and_copy_from_user (const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ if (verify_area(VERIFY_READ, src, len) == 0)
+ return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
+
+ if (len)
+ *err_ptr = -EFAULT;
+
+ return sum;
+}
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/net/datalink.h b/pfinet/linux-src/include/net/datalink.h
new file mode 100644
index 00000000..44e56990
--- /dev/null
+++ b/pfinet/linux-src/include/net/datalink.h
@@ -0,0 +1,16 @@
+#ifndef _NET_INET_DATALINK_H_
+#define _NET_INET_DATALINK_H_
+
+struct datalink_proto {
+ unsigned short type_len;
+ unsigned char type[8];
+ const char *string_name;
+ unsigned short header_length;
+ int (*rcvfunc)(struct sk_buff *, struct device *,
+ struct packet_type *);
+ void (*datalink_header)(struct datalink_proto *, struct sk_buff *,
+ unsigned char *);
+ struct datalink_proto *next;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/net/dst.h b/pfinet/linux-src/include/net/dst.h
new file mode 100644
index 00000000..baf4f414
--- /dev/null
+++ b/pfinet/linux-src/include/net/dst.h
@@ -0,0 +1,178 @@
+/*
+ * net/dst.h Protocol independent destination cache definitions.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ */
+
+#ifndef _NET_DST_H
+#define _NET_DST_H
+
+#include <linux/config.h>
+#include <net/neighbour.h>
+
+/*
+ * 0 - no debugging messages
+ * 1 - rare events and bugs (default)
+ * 2 - trace mode.
+ */
+#define RT_CACHE_DEBUG 0
+
+#define DST_GC_MIN (1*HZ)
+#define DST_GC_INC (5*HZ)
+#define DST_GC_MAX (120*HZ)
+
+struct sk_buff;
+
+struct dst_entry
+{
+ struct dst_entry *next;
+ atomic_t refcnt; /* tree/hash references */
+ atomic_t use; /* client references */
+ struct device *dev;
+ int obsolete;
+ unsigned long lastuse;
+ unsigned long expires;
+ unsigned mxlock;
+ unsigned pmtu;
+ unsigned window;
+ unsigned rtt;
+ unsigned long rate_last; /* rate limiting for ICMP */
+ unsigned long rate_tokens;
+
+ int error;
+
+ struct neighbour *neighbour;
+ struct hh_cache *hh;
+
+ int (*input)(struct sk_buff*);
+ int (*output)(struct sk_buff*);
+
+#ifdef CONFIG_NET_CLS_ROUTE
+ __u32 tclassid;
+#endif
+
+ struct dst_ops *ops;
+
+ char info[0];
+};
+
+
+struct dst_ops
+{
+ unsigned short family;
+ unsigned short protocol;
+ unsigned gc_thresh;
+
+ int (*gc)(void);
+ struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
+ struct dst_entry * (*reroute)(struct dst_entry *,
+ struct sk_buff *);
+ void (*destroy)(struct dst_entry *);
+ struct dst_entry * (*negative_advice)(struct dst_entry *);
+ void (*link_failure)(struct sk_buff *);
+
+ atomic_t entries;
+};
+
+#ifdef __KERNEL__
+
+extern struct dst_entry * dst_garbage_list;
+extern atomic_t dst_total;
+
+extern __inline__
+struct dst_entry * dst_clone(struct dst_entry * dst)
+{
+ if (dst)
+ atomic_inc(&dst->use);
+ return dst;
+}
+
+extern __inline__
+void dst_release(struct dst_entry * dst)
+{
+ if (dst)
+ atomic_dec(&dst->use);
+}
+
+/* The following primitive should be use if and only if
+ destination entry has just been removed from a location
+ accessed directly by hard irq.
+ */
+extern __inline__
+void dst_release_irqwait(struct dst_entry * dst)
+{
+ if (dst) {
+ synchronize_irq();
+ atomic_dec(&dst->use);
+ }
+}
+
+extern __inline__
+struct dst_entry * dst_check(struct dst_entry ** dst_p, u32 cookie)
+{
+ struct dst_entry * dst = *dst_p;
+ if (dst && dst->obsolete)
+ dst = dst->ops->check(dst, cookie);
+ return (*dst_p = dst);
+}
+
+extern __inline__
+struct dst_entry * dst_reroute(struct dst_entry ** dst_p, struct sk_buff *skb)
+{
+ struct dst_entry * dst = *dst_p;
+ if (dst && dst->obsolete)
+ dst = dst->ops->reroute(dst, skb);
+ return (*dst_p = dst);
+}
+
+
+extern void * dst_alloc(int size, struct dst_ops * ops);
+extern void __dst_free(struct dst_entry * dst);
+extern void dst_destroy(struct dst_entry * dst);
+
+extern __inline__
+void dst_free(struct dst_entry * dst)
+{
+ if (dst->obsolete > 1)
+ return;
+ if (!atomic_read(&dst->use)) {
+ dst_destroy(dst);
+ return;
+ }
+ __dst_free(dst);
+}
+
+extern __inline__ void dst_confirm(struct dst_entry *dst)
+{
+ if (dst)
+ neigh_confirm(dst->neighbour);
+}
+
+extern __inline__ void dst_negative_advice(struct dst_entry **dst_p)
+{
+ struct dst_entry * dst = *dst_p;
+ if (dst && dst->ops->negative_advice)
+ *dst_p = dst->ops->negative_advice(dst);
+}
+
+extern __inline__ void dst_link_failure(struct sk_buff *skb)
+{
+ struct dst_entry * dst = skb->dst;
+ if (dst && dst->ops && dst->ops->link_failure)
+ dst->ops->link_failure(skb);
+}
+
+extern __inline__ void dst_set_expires(struct dst_entry *dst, int timeout)
+{
+ unsigned long expires = jiffies + timeout;
+
+ if (expires == 0)
+ expires = 1;
+
+ if (dst->expires == 0 || (long)(dst->expires - expires) > 0)
+ dst->expires = expires;
+}
+#endif
+
+#endif /* _NET_DST_H */
diff --git a/pfinet/linux-src/include/net/flow.h b/pfinet/linux-src/include/net/flow.h
new file mode 100644
index 00000000..e1ce1b2a
--- /dev/null
+++ b/pfinet/linux-src/include/net/flow.h
@@ -0,0 +1,101 @@
+/*
+ *
+ * Flow based forwarding rules (usage: firewalling, etc)
+ *
+ */
+
+#ifndef _NET_FLOW_H
+#define _NET_FLOW_H
+
+struct flowi {
+ int proto; /* {TCP, UDP, ICMP} */
+
+ union {
+ struct {
+ __u32 daddr;
+ __u32 saddr;
+ } ip4_u;
+
+ struct {
+ struct in6_addr * daddr;
+ struct in6_addr * saddr;
+ __u32 flowlabel;
+ } ip6_u;
+ } nl_u;
+#define fl6_dst nl_u.ip6_u.daddr
+#define fl6_src nl_u.ip6_u.saddr
+#define fl6_flowlabel nl_u.ip6_u.flowlabel
+#define fl4_dst nl_u.ip4_u.daddr
+#define fl4_src nl_u.ip4_u.saddr
+
+ int oif;
+
+ union {
+ struct {
+ __u16 sport;
+ __u16 dport;
+ } ports;
+
+ struct {
+ __u8 type;
+ __u8 code;
+ } icmpt;
+
+ unsigned long data;
+ } uli_u;
+};
+
+#define FLOWR_NODECISION 0 /* rule not appliable to flow */
+#define FLOWR_SELECT 1 /* flow must follow this rule */
+#define FLOWR_CLEAR 2 /* priority level clears flow */
+#define FLOWR_ERROR 3
+
+struct fl_acc_args {
+ int type;
+
+
+#define FL_ARG_FORWARD 1
+#define FL_ARG_ORIGIN 2
+
+ union {
+ struct sk_buff *skb;
+ struct {
+ struct sock *sk;
+ struct flowi *flow;
+ } fl_o;
+ } fl_u;
+};
+
+
+struct pkt_filter {
+ atomic_t refcnt;
+ unsigned int offset;
+ __u32 value;
+ __u32 mask;
+ struct pkt_filter *next;
+};
+
+#define FLR_INPUT 1
+#define FLR_OUTPUT 2
+
+struct flow_filter {
+ int type;
+ union {
+ struct pkt_filter *filter;
+ struct sock *sk;
+ } u;
+};
+
+struct flow_rule {
+ struct flow_rule_ops *ops;
+ unsigned char private[0];
+};
+
+struct flow_rule_ops {
+ int (*accept)(struct rt6_info *rt,
+ struct rt6_info *rule,
+ struct fl_acc_args *args,
+ struct rt6_info **nrt);
+};
+
+#endif
diff --git a/pfinet/linux-src/include/net/icmp.h b/pfinet/linux-src/include/net/icmp.h
new file mode 100644
index 00000000..6e9c5418
--- /dev/null
+++ b/pfinet/linux-src/include/net/icmp.h
@@ -0,0 +1,42 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the ICMP module.
+ *
+ * Version: @(#)icmp.h 1.0.4 05/13/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ICMP_H
+#define _ICMP_H
+
+#include <linux/icmp.h>
+#include <linux/skbuff.h>
+
+#include <net/sock.h>
+#include <net/protocol.h>
+
+extern struct icmp_err icmp_err_convert[];
+extern struct icmp_mib icmp_statistics;
+
+extern void icmp_send(struct sk_buff *skb_in, int type, int code,
+ unsigned long info);
+extern int icmp_rcv(struct sk_buff *skb, unsigned short len);
+extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern void icmp_init(struct net_proto_family *ops);
+
+/* Move into dst.h ? */
+extern int xrlim_allow(struct dst_entry *dst, int timeout);
+
+/* CONFIG_IP_TRANSPARENT_PROXY */
+extern int icmp_chkaddr(struct sk_buff *skb);
+
+#endif /* _ICMP_H */
diff --git a/pfinet/linux-src/include/net/if_inet6.h b/pfinet/linux-src/include/net/if_inet6.h
new file mode 100644
index 00000000..4e9ed978
--- /dev/null
+++ b/pfinet/linux-src/include/net/if_inet6.h
@@ -0,0 +1,134 @@
+/*
+ * inet6 interface/address list definitions
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _NET_IF_INET6_H
+#define _NET_IF_INET6_H
+
+/* These flags match corresponding IFA_F_* flags but ADDR_INVALID,
+ which is invisible externally.
+ */
+
+#define ADDR_PERMANENT 0x80
+
+#define DAD_COMPLETE 0x00
+#define DAD_INCOMPLETE 0x40
+#define DAD_STATUS 0x40
+
+#define ADDR_STATUS 0x21
+#define ADDR_DEPRECATED 0x20
+#define ADDR_INVALID 0x01
+
+
+
+#define IF_RA_RCVD 0x20
+#define IF_RS_SENT 0x10
+
+#ifdef __KERNEL__
+
+struct inet6_ifaddr
+{
+ struct in6_addr addr;
+ __u32 prefix_len;
+
+ __u32 valid_lft;
+ __u32 prefered_lft;
+ unsigned long tstamp;
+
+ __u8 probes;
+ __u8 flags;
+
+ __u16 scope;
+
+ struct timer_list timer;
+
+ struct inet6_dev *idev;
+
+ struct inet6_ifaddr *lst_next; /* next addr in addr_lst */
+ struct inet6_ifaddr *if_next; /* next addr in inet6_dev */
+};
+
+
+struct ipv6_mc_socklist
+{
+ struct in6_addr addr;
+ int ifindex;
+ struct ipv6_mc_socklist *next;
+};
+
+#define MAF_TIMER_RUNNING 0x01
+#define MAF_LAST_REPORTER 0x02
+#define MAF_LOADED 0x04
+
+struct ifmcaddr6
+{
+ struct in6_addr mca_addr;
+ struct device *dev;
+ struct ifmcaddr6 *next;
+ struct ifmcaddr6 *if_next;
+ struct timer_list mca_timer;
+ unsigned mca_flags;
+ atomic_t mca_users;
+};
+
+#define IFA_HOST IPV6_ADDR_LOOPBACK
+#define IFA_LINK IPV6_ADDR_LINKLOCAL
+#define IFA_SITE IPV6_ADDR_SITELOCAL
+#define IFA_GLOBAL 0x0000U
+
+struct ipv6_devconf
+{
+ int forwarding;
+ int hop_limit;
+ int mtu6;
+ int accept_ra;
+ int accept_redirects;
+ int autoconf;
+ int dad_transmits;
+ int rtr_solicits;
+ int rtr_solicit_interval;
+ int rtr_solicit_delay;
+
+ void *sysctl;
+};
+
+struct inet6_dev
+{
+ struct device *dev;
+
+ struct inet6_ifaddr *addr_list;
+ struct ifmcaddr6 *mc_list;
+ __u32 if_flags;
+
+ struct neigh_parms *nd_parms;
+ struct inet6_dev *next;
+ struct ipv6_devconf cnf;
+};
+
+extern struct ipv6_devconf ipv6_devconf;
+
+extern __inline__ void ipv6_eth_mc_map(struct in6_addr *addr, char *buf)
+{
+ /*
+ * +-------+-------+-------+-------+-------+-------+
+ * | 33 | 33 | DST13 | DST14 | DST15 | DST16 |
+ * +-------+-------+-------+-------+-------+-------+
+ */
+
+ buf[0]= 0x33;
+ buf[1]= 0x33;
+
+ memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32));
+}
+#endif
+#endif
diff --git a/pfinet/linux-src/include/net/inet_common.h b/pfinet/linux-src/include/net/inet_common.h
new file mode 100644
index 00000000..9c7c8b94
--- /dev/null
+++ b/pfinet/linux-src/include/net/inet_common.h
@@ -0,0 +1,45 @@
+#ifndef _INET_COMMON_H
+#define _INET_COMMON_H
+
+extern struct proto_ops inet_stream_ops;
+extern struct proto_ops inet_dgram_ops;
+
+/*
+ * INET4 prototypes used by INET6
+ */
+
+extern void inet_remove_sock(struct sock *sk1);
+extern void inet_put_sock(unsigned short num,
+ struct sock *sk);
+extern int inet_release(struct socket *sock,
+ struct socket *peer);
+extern int inet_stream_connect(struct socket *sock,
+ struct sockaddr * uaddr,
+ int addr_len, int flags);
+extern int inet_dgram_connect(struct socket *sock,
+ struct sockaddr * uaddr,
+ int addr_len, int flags);
+extern int inet_accept(struct socket *sock,
+ struct socket *newsock, int flags);
+extern int inet_recvmsg(struct socket *sock,
+ struct msghdr *ubuf,
+ int size, int flags, struct scm_cookie *scm);
+extern int inet_sendmsg(struct socket *sock,
+ struct msghdr *msg,
+ int size, struct scm_cookie *scm);
+extern int inet_shutdown(struct socket *sock, int how);
+extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
+extern int inet_setsockopt(struct socket *sock, int level,
+ int optname, char *optval,
+ int optlen);
+extern int inet_getsockopt(struct socket *sock, int level,
+ int optname, char *optval,
+ int *optlen);
+extern int inet_fcntl(struct socket *sock,
+ unsigned int cmd,
+ unsigned long arg);
+extern int inet_listen(struct socket *sock, int backlog);
+
+#endif
+
+
diff --git a/pfinet/linux-src/include/net/ip.h b/pfinet/linux-src/include/net/ip.h
new file mode 100644
index 00000000..5e80fb43
--- /dev/null
+++ b/pfinet/linux-src/include/net/ip.h
@@ -0,0 +1,251 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the IP module.
+ *
+ * Version: @(#)ip.h 1.0.2 05/07/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *
+ * Changes:
+ * Mike McLagan : Routing by source
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _IP_H
+#define _IP_H
+
+
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/ip.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in_route.h>
+#include <net/route.h>
+#include <net/arp.h>
+
+#ifndef _SNMP_H
+#include <net/snmp.h>
+#endif
+
+#include <net/sock.h> /* struct sock */
+
+struct inet_skb_parm
+{
+ struct ip_options opt; /* Compiled IP options */
+ u16 redirport; /* Redirect port */
+ unsigned char flags;
+
+#define IPSKB_MASQUERADED 1
+#define IPSKB_TRANSLATED 2
+#define IPSKB_FORWARDED 4
+};
+
+struct ipcm_cookie
+{
+ u32 addr;
+ int oif;
+ struct ip_options *opt;
+};
+
+#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
+
+struct ip_ra_chain
+{
+ struct ip_ra_chain *next;
+ struct sock *sk;
+ void (*destructor)(struct sock *);
+};
+
+extern struct ip_ra_chain *ip_ra_chain;
+
+/* IP flags. */
+#define IP_CE 0x8000 /* Flag: "Congestion" */
+#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
+#define IP_MF 0x2000 /* Flag: "More Fragments" */
+#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
+
+#define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */
+
+extern void ip_mc_dropsocket(struct sock *);
+extern void ip_mc_dropdevice(struct device *dev);
+extern int ip_mc_procinfo(char *, char **, off_t, int, int);
+
+/*
+ * Functions provided by ip.c
+ */
+
+extern int ip_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern void ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
+ u32 saddr, u32 daddr,
+ struct ip_options *opt);
+extern int ip_rcv(struct sk_buff *skb, struct device *dev,
+ struct packet_type *pt);
+extern int ip_local_deliver(struct sk_buff *skb);
+extern int ip_mr_input(struct sk_buff *skb);
+extern int ip_output(struct sk_buff *skb);
+extern int ip_mc_output(struct sk_buff *skb);
+extern void ip_fragment(struct sk_buff *skb, int (*out)(struct sk_buff*));
+extern int ip_do_nat(struct sk_buff *skb);
+extern void ip_send_check(struct iphdr *ip);
+extern int ip_id_count;
+extern void ip_queue_xmit(struct sk_buff *skb);
+extern void ip_init(void);
+extern int ip_build_xmit(struct sock *sk,
+ int getfrag (const void *,
+ char *,
+ unsigned int,
+ unsigned int),
+ const void *frag,
+ unsigned length,
+ struct ipcm_cookie *ipc,
+ struct rtable *rt,
+ int flags);
+
+
+struct ip_reply_arg {
+ struct iovec iov[2];
+ int n_iov; /* redundant */
+ u32 csum;
+ int csumoffset; /* u16 offset of csum in iov[0].iov_base */
+ /* -1 if not needed */
+};
+
+void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
+ unsigned int len);
+
+extern int __ip_finish_output(struct sk_buff *skb);
+
+struct ipv4_config
+{
+ int log_martians;
+ int autoconfig;
+ int no_pmtu_disc;
+};
+
+extern struct ipv4_config ipv4_config;
+extern struct ip_mib ip_statistics;
+extern struct linux_mib net_statistics;
+
+extern int sysctl_local_port_range[2];
+
+extern __inline__ int ip_finish_output(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct device *dev = dst->dev;
+ struct hh_cache *hh = dst->hh;
+
+ skb->dev = dev;
+ skb->protocol = __constant_htons(ETH_P_IP);
+
+ if (hh) {
+ read_lock_irq(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_irq(&hh->hh_lock);
+ skb_push(skb, dev->hard_header_len);
+ return hh->hh_output(skb);
+ } else if (dst->neighbour)
+ return dst->neighbour->output(skb);
+
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+extern __inline__ void ip_send(struct sk_buff *skb)
+{
+ if (skb->len > skb->dst->pmtu)
+ ip_fragment(skb, __ip_finish_output);
+ else
+ ip_finish_output(skb);
+}
+
+extern __inline__
+int ip_decrease_ttl(struct iphdr *iph)
+{
+ u16 check = iph->check;
+ check = ntohs(check) + 0x0100;
+ if ((check & 0xFF00) == 0)
+ check++; /* carry overflow */
+ iph->check = htons(check);
+ return --iph->ttl;
+}
+
+extern __inline__
+int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
+{
+ return (sk->ip_pmtudisc == IP_PMTUDISC_DO ||
+ (sk->ip_pmtudisc == IP_PMTUDISC_WANT &&
+ !(dst->mxlock&(1<<RTAX_MTU))));
+}
+
+/*
+ * Map a multicast IP onto multicast MAC for type ethernet.
+ */
+
+extern __inline__ void ip_eth_mc_map(u32 addr, char *buf)
+{
+ addr=ntohl(addr);
+ buf[0]=0x01;
+ buf[1]=0x00;
+ buf[2]=0x5e;
+ buf[5]=addr&0xFF;
+ addr>>=8;
+ buf[4]=addr&0xFF;
+ addr>>=8;
+ buf[3]=addr&0x7F;
+}
+
+
+extern int ip_call_ra_chain(struct sk_buff *skb);
+
+/*
+ * Functions provided by ip_fragment.o
+ */
+
+struct sk_buff *ip_defrag(struct sk_buff *skb);
+
+/*
+ * Functions provided by ip_forward.c
+ */
+
+extern int ip_forward(struct sk_buff *skb);
+extern int ip_net_unreachable(struct sk_buff *skb);
+
+/*
+ * Functions provided by ip_options.c
+ */
+
+extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, u32 daddr, struct rtable *rt, int is_frag);
+extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
+extern void ip_options_fragment(struct sk_buff *skb);
+extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb);
+extern int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user);
+extern void ip_options_undo(struct ip_options * opt);
+extern void ip_forward_options(struct sk_buff *skb);
+extern int ip_options_rcv_srr(struct sk_buff *skb);
+
+/*
+ * Functions provided by ip_sockglue.c
+ */
+
+extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
+extern int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc);
+extern int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen);
+extern int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen);
+extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
+
+extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
+extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
+ u16 port, u32 info, u8 *payload);
+extern void ip_local_error(struct sock *sk, int err, u32 daddr, u16 dport,
+ u32 info);
+
+#endif /* _IP_H */
diff --git a/pfinet/linux-src/include/net/ip6_fib.h b/pfinet/linux-src/include/net/ip6_fib.h
new file mode 100644
index 00000000..efd652f2
--- /dev/null
+++ b/pfinet/linux-src/include/net/ip6_fib.h
@@ -0,0 +1,177 @@
+/*
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _IP6_FIB_H
+#define _IP6_FIB_H
+
+#ifdef __KERNEL__
+
+#include <linux/ipv6_route.h>
+
+#include <net/dst.h>
+#include <net/flow.h>
+#include <linux/rtnetlink.h>
+
+struct rt6_info;
+
+struct fib6_node
+{
+ struct fib6_node *parent;
+ struct fib6_node *left;
+ struct fib6_node *right;
+
+ struct fib6_node *subtree;
+
+ struct rt6_info *leaf;
+
+ __u16 fn_bit; /* bit key */
+ __u16 fn_flags;
+ __u32 fn_sernum;
+};
+
+
+/*
+ * routing information
+ *
+ */
+
+struct rt6key
+{
+ struct in6_addr addr;
+ int plen;
+};
+
+struct rt6_info
+{
+ union {
+ struct dst_entry dst;
+ struct rt6_info *next;
+ } u;
+
+#define rt6i_dev u.dst.dev
+#define rt6i_nexthop u.dst.neighbour
+#define rt6i_expires u.dst.expires
+
+ struct fib6_node *rt6i_node;
+
+ struct in6_addr rt6i_gateway;
+
+ u32 rt6i_flags;
+ u32 rt6i_metric;
+ u8 rt6i_hoplimit;
+ atomic_t rt6i_ref;
+
+ union {
+ struct flow_rule *rt6iu_flowr;
+ struct flow_filter *rt6iu_filter;
+ } flow_u;
+
+#define rt6i_flowr flow_u.rt6iu_flowr
+#define rt6i_filter flow_u.rt6iu_filter
+
+ struct rt6key rt6i_dst;
+ struct rt6key rt6i_src;
+};
+
+struct fib6_walker_t
+{
+ struct fib6_walker_t *prev, *next;
+ struct fib6_node *root, *node;
+ struct rt6_info *leaf;
+ unsigned char state;
+ unsigned char prune;
+ int (*func)(struct fib6_walker_t *);
+ void *args;
+};
+
+extern struct fib6_walker_t fib6_walker_list;
+
+extern __inline__ void fib6_walker_link(struct fib6_walker_t *w)
+{
+ w->next = fib6_walker_list.next;
+ w->prev = &fib6_walker_list;
+ w->next->prev = w;
+ w->prev->next = w;
+}
+
+extern __inline__ void fib6_walker_unlink(struct fib6_walker_t *w)
+{
+ w->next->prev = w->prev;
+ w->prev->next = w->next;
+ w->prev = w->next = w;
+}
+
+struct rt6_statistics {
+ __u32 fib_nodes;
+ __u32 fib_route_nodes;
+ __u32 fib_rt_alloc; /* permanet routes */
+ __u32 fib_rt_entries; /* rt entries in table */
+ __u32 fib_rt_cache; /* cache routes */
+};
+
+#define RTN_TL_ROOT 0x0001
+#define RTN_ROOT 0x0002 /* tree root node */
+#define RTN_RTINFO 0x0004 /* node with valid routing info */
+
+/*
+ * priority levels (or metrics)
+ *
+ */
+
+#define RTPRI_FIREWALL 8 /* Firewall control information */
+#define RTPRI_FLOW 16 /* Flow based forwarding rules */
+#define RTPRI_KERN_CTL 32 /* Kernel control routes */
+
+#define RTPRI_USER_MIN 256 /* Mimimum user priority */
+#define RTPRI_USER_MAX 1024 /* Maximum user priority */
+
+#define RTPRI_KERN_DFLT 4096 /* Kernel default routes */
+
+#define MAX_FLOW_BACKTRACE 32
+
+
+typedef void (*f_pnode)(struct fib6_node *fn, void *);
+
+extern struct fib6_node ip6_routing_table;
+
+/*
+ * exported functions
+ */
+
+extern struct fib6_node *fib6_lookup(struct fib6_node *root,
+ struct in6_addr *daddr,
+ struct in6_addr *saddr);
+
+struct fib6_node *fib6_locate(struct fib6_node *root,
+ struct in6_addr *daddr, int dst_len,
+ struct in6_addr *saddr, int src_len);
+
+extern void fib6_clean_tree(struct fib6_node *root,
+ int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg);
+
+extern int fib6_walk(struct fib6_walker_t *w);
+extern int fib6_walk_continue(struct fib6_walker_t *w);
+
+extern int fib6_add(struct fib6_node *root,
+ struct rt6_info *rt);
+
+extern int fib6_del(struct rt6_info *rt);
+
+extern void inet6_rt_notify(int event, struct rt6_info *rt);
+
+extern void fib6_run_gc(unsigned long dummy);
+
+extern void fib6_gc_cleanup(void);
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/net/ip6_fw.h b/pfinet/linux-src/include/net/ip6_fw.h
new file mode 100644
index 00000000..7866273d
--- /dev/null
+++ b/pfinet/linux-src/include/net/ip6_fw.h
@@ -0,0 +1,54 @@
+#ifndef __NET_IP6_FW_H
+#define __NET_IP6_FW_H
+
+#define IP6_FW_LISTHEAD 0x1000
+#define IP6_FW_ACCEPT 0x0001
+#define IP6_FW_REJECT 0x0002
+
+#define IP6_FW_DEBUG 2
+
+#define IP6_FW_MSG_ADD 1
+#define IP6_FW_MSG_DEL 2
+#define IP6_FW_MSG_REPORT 3
+
+
+/*
+ * Fast "hack" user interface
+ */
+struct ip6_fw_msg {
+ struct in6_addr dst;
+ struct in6_addr src;
+ int dst_len;
+ int src_len;
+ int action;
+ int policy;
+ int proto;
+ union {
+ struct {
+ __u16 sport;
+ __u16 dport;
+ } transp;
+
+ unsigned long data;
+
+ int icmp_type;
+ } u;
+
+ int msg_len;
+};
+
+#ifdef __KERNEL__
+
+#include <net/flow.h>
+
+struct ip6_fw_rule {
+ struct flow_rule flowr;
+ struct ip6_fw_rule *next;
+ struct ip6_fw_rule *prev;
+ struct flowi info;
+ unsigned long policy;
+};
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/net/ip6_route.h b/pfinet/linux-src/include/net/ip6_route.h
new file mode 100644
index 00000000..9311cc34
--- /dev/null
+++ b/pfinet/linux-src/include/net/ip6_route.h
@@ -0,0 +1,111 @@
+#ifndef _NET_IP6_ROUTE_H
+#define _NET_IP6_ROUTE_H
+
+#define IP6_RT_PRIO_FW 16
+#define IP6_RT_PRIO_USER 1024
+#define IP6_RT_PRIO_ADDRCONF 256
+#define IP6_RT_PRIO_KERN 512
+#define IP6_RT_FLOW_MASK 0x00ff
+
+#ifdef __KERNEL__
+
+#include <net/flow.h>
+#include <net/ip6_fib.h>
+
+struct pol_chain {
+ int type;
+ int priority;
+ struct fib6_node *rules;
+ struct pol_chain *next;
+};
+
+extern struct rt6_info ip6_null_entry;
+
+extern int ip6_rt_max_size;
+extern int ip6_rt_gc_min;
+extern int ip6_rt_gc_timeout;
+extern int ip6_rt_gc_interval;
+
+extern void ip6_route_input(struct sk_buff *skb);
+
+extern struct dst_entry * ip6_route_output(struct sock *sk,
+ struct flowi *fl);
+
+extern void ip6_route_init(void);
+extern void ip6_route_cleanup(void);
+
+extern int ipv6_route_ioctl(unsigned int cmd, void *arg);
+
+extern int ip6_route_add(struct in6_rtmsg *rtmsg);
+extern int ip6_del_rt(struct rt6_info *);
+
+extern int ip6_rt_addr_add(struct in6_addr *addr,
+ struct device *dev);
+
+extern int ip6_rt_addr_del(struct in6_addr *addr,
+ struct device *dev);
+
+extern void rt6_sndmsg(int type, struct in6_addr *dst,
+ struct in6_addr *src,
+ struct in6_addr *gw,
+ struct device *dev,
+ int dstlen, int srclen,
+ int metric, __u32 flags);
+
+extern struct rt6_info *rt6_lookup(struct in6_addr *daddr,
+ struct in6_addr *saddr,
+ int oif, int flags);
+
+/*
+ * support functions for ND
+ *
+ */
+extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr,
+ struct device *dev);
+extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr,
+ struct device *dev);
+
+extern void rt6_purge_dflt_routers(int lst_resort);
+
+extern void rt6_redirect(struct in6_addr *dest,
+ struct in6_addr *saddr,
+ struct neighbour *neigh,
+ int on_link);
+
+extern void rt6_pmtu_discovery(struct in6_addr *daddr,
+ struct in6_addr *saddr,
+ struct device *dev,
+ u32 pmtu);
+
+struct nlmsghdr;
+struct netlink_callback;
+extern int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb);
+extern int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
+extern int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
+extern int inet6_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
+
+extern void rt6_ifdown(struct device *dev);
+extern void rt6_mtu_change(struct device *dev, unsigned mtu);
+
+/*
+ * Store a destination cache entry in a socket
+ * For UDP/RAW sockets this is done on udp_connect.
+ */
+
+extern __inline__ void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
+ struct in6_addr *daddr)
+{
+ struct ipv6_pinfo *np;
+ struct rt6_info *rt;
+
+ np = &sk->net_pinfo.af_inet6;
+ dst_release(xchg(&sk->dst_cache,dst));
+
+ rt = (struct rt6_info *) dst;
+
+ np->daddr_cache = daddr;
+ np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
+}
+
+#endif
+#endif
diff --git a/pfinet/linux-src/include/net/ip_fib.h b/pfinet/linux-src/include/net/ip_fib.h
new file mode 100644
index 00000000..6e1fd869
--- /dev/null
+++ b/pfinet/linux-src/include/net/ip_fib.h
@@ -0,0 +1,257 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the Forwarding Information Base.
+ *
+ * Authors: A.N.Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _NET_IP_FIB_H
+#define _NET_IP_FIB_H
+
+#include <linux/config.h>
+
+struct kern_rta
+{
+ void *rta_dst;
+ void *rta_src;
+ int *rta_iif;
+ int *rta_oif;
+ void *rta_gw;
+ u32 *rta_priority;
+ void *rta_prefsrc;
+ struct rtattr *rta_mx;
+ struct rtattr *rta_mp;
+ unsigned char *rta_protoinfo;
+ unsigned char *rta_flow;
+ struct rta_cacheinfo *rta_ci;
+};
+
+struct fib_nh
+{
+ struct device *nh_dev;
+ unsigned nh_flags;
+ unsigned char nh_scope;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ int nh_weight;
+ int nh_power;
+#endif
+#ifdef CONFIG_NET_CLS_ROUTE
+ __u32 nh_tclassid;
+#endif
+ int nh_oif;
+ u32 nh_gw;
+};
+
+/*
+ * This structure contains data shared by many of routes.
+ */
+
+struct fib_info
+{
+ struct fib_info *fib_next;
+ struct fib_info *fib_prev;
+ int fib_refcnt;
+ unsigned fib_flags;
+ int fib_protocol;
+ u32 fib_prefsrc;
+ u32 fib_priority;
+#define FIB_MAX_METRICS RTAX_RTT
+ unsigned fib_metrics[FIB_MAX_METRICS];
+#define fib_mtu fib_metrics[RTAX_MTU-1]
+#define fib_window fib_metrics[RTAX_WINDOW-1]
+#define fib_rtt fib_metrics[RTAX_RTT-1]
+ int fib_nhs;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ int fib_power;
+#endif
+ struct fib_nh fib_nh[0];
+#define fib_dev fib_nh[0].nh_dev
+};
+
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+struct fib_rule;
+#endif
+
+struct fib_result
+{
+ u32 *prefix;
+ unsigned char prefixlen;
+ unsigned char nh_sel;
+ unsigned char type;
+ unsigned char scope;
+ struct fib_info *fi;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ struct fib_rule *r;
+#endif
+};
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+
+#define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
+#define FIB_RES_RESET(res) ((res).nh_sel = 0)
+
+#else /* CONFIG_IP_ROUTE_MULTIPATH */
+
+#define FIB_RES_NH(res) ((res).fi->fib_nh[0])
+#define FIB_RES_RESET(res)
+
+#endif /* CONFIG_IP_ROUTE_MULTIPATH */
+
+#define FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __fib_res_prefsrc(&res))
+#define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw)
+#define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
+#define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif)
+
+struct fib_table
+{
+ unsigned char tb_id;
+ unsigned tb_stamp;
+ int (*tb_lookup)(struct fib_table *tb, const struct rt_key *key, struct fib_result *res);
+ int (*tb_insert)(struct fib_table *table, struct rtmsg *r,
+ struct kern_rta *rta, struct nlmsghdr *n,
+ struct netlink_skb_parms *req);
+ int (*tb_delete)(struct fib_table *table, struct rtmsg *r,
+ struct kern_rta *rta, struct nlmsghdr *n,
+ struct netlink_skb_parms *req);
+ int (*tb_dump)(struct fib_table *table, struct sk_buff *skb,
+ struct netlink_callback *cb);
+ int (*tb_flush)(struct fib_table *table);
+ int (*tb_get_info)(struct fib_table *table, char *buf,
+ int first, int count);
+ void (*tb_select_default)(struct fib_table *table,
+ const struct rt_key *key, struct fib_result *res);
+
+ unsigned char tb_data[0];
+};
+
+#ifndef CONFIG_IP_MULTIPLE_TABLES
+
+extern struct fib_table *local_table;
+extern struct fib_table *main_table;
+
+extern __inline__ struct fib_table *fib_get_table(int id)
+{
+ if (id != RT_TABLE_LOCAL)
+ return main_table;
+ return local_table;
+}
+
+extern __inline__ struct fib_table *fib_new_table(int id)
+{
+ return fib_get_table(id);
+}
+
+extern __inline__ int fib_lookup(const struct rt_key *key, struct fib_result *res)
+{
+ if (local_table->tb_lookup(local_table, key, res) &&
+ main_table->tb_lookup(main_table, key, res))
+ return -ENETUNREACH;
+ return 0;
+}
+
+extern __inline__ void fib_select_default(const struct rt_key *key, struct fib_result *res)
+{
+ if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
+ main_table->tb_select_default(main_table, key, res);
+}
+
+#else /* CONFIG_IP_MULTIPLE_TABLES */
+#define local_table (fib_tables[RT_TABLE_LOCAL])
+#define main_table (fib_tables[RT_TABLE_MAIN])
+
+extern struct fib_table * fib_tables[RT_TABLE_MAX+1];
+extern int fib_lookup(const struct rt_key *key, struct fib_result *res);
+extern struct fib_table *__fib_new_table(int id);
+
+extern __inline__ struct fib_table *fib_get_table(int id)
+{
+ if (id == 0)
+ id = RT_TABLE_MAIN;
+
+ return fib_tables[id];
+}
+
+extern __inline__ struct fib_table *fib_new_table(int id)
+{
+ if (id == 0)
+ id = RT_TABLE_MAIN;
+
+ return fib_tables[id] ? : __fib_new_table(id);
+}
+
+extern void fib_select_default(const struct rt_key *key, struct fib_result *res);
+
+#endif /* CONFIG_IP_MULTIPLE_TABLES */
+
+/* Exported by fib_frontend.c */
+extern void ip_fib_init(void);
+extern void fib_flush(void);
+extern int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
+extern int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
+extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
+extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb);
+extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
+ struct device *dev, u32 *spec_dst, u32 *itag);
+extern void fib_select_multipath(const struct rt_key *key, struct fib_result *res);
+
+/* Exported by fib_semantics.c */
+extern int ip_fib_check_default(u32 gw, struct device *dev);
+extern void fib_release_info(struct fib_info *);
+extern int fib_semantic_match(int type, struct fib_info *,
+ const struct rt_key *, struct fib_result*);
+extern struct fib_info *fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
+ const struct nlmsghdr *, int *err);
+extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, struct kern_rta *rta, struct fib_info *fi);
+extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+ u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
+ struct fib_info *fi);
+extern int fib_sync_down(u32 local, struct device *dev, int force);
+extern int fib_sync_up(struct device *dev);
+extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
+ struct kern_rta *rta, struct rtentry *r);
+extern void fib_node_get_info(int type, int dead, struct fib_info *fi, u32 prefix, u32 mask, char *buffer);
+extern u32 __fib_res_prefsrc(struct fib_result *res);
+
+/* Exported by fib_hash.c */
+extern struct fib_table *fib_hash_init(int id);
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+/* Exported by fib_rules.c */
+
+extern int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
+extern int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
+extern int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb);
+extern u32 fib_rules_map_destination(u32 daddr, struct fib_result *res);
+#ifdef CONFIG_NET_CLS_ROUTE
+extern u32 fib_rules_tclass(struct fib_result *res);
+#endif
+extern u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags);
+extern void fib_rules_init(void);
+#endif
+
+extern __inline__ void fib_combine_itag(u32 *itag, struct fib_result *res)
+{
+#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ u32 rtag;
+#endif
+ *itag = FIB_RES_NH(*res).nh_tclassid<<16;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ rtag = fib_rules_tclass(res);
+ if (*itag == 0)
+ *itag = (rtag<<16);
+ *itag |= (rtag>>16);
+#endif
+#endif
+}
+
+#endif _NET_FIB_H
diff --git a/pfinet/linux-src/include/net/ip_masq.h b/pfinet/linux-src/include/net/ip_masq.h
new file mode 100644
index 00000000..1e050359
--- /dev/null
+++ b/pfinet/linux-src/include/net/ip_masq.h
@@ -0,0 +1,362 @@
+/*
+ * IP masquerading functionality definitions
+ */
+
+#include <linux/config.h> /* for CONFIG_IP_MASQ_DEBUG */
+#ifndef _IP_MASQ_H
+#define _IP_MASQ_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#endif /* __KERNEL__ */
+
+/*
+ * This define affects the number of ports that can be handled
+ * by each of the protocol helper modules.
+ */
+#define MAX_MASQ_APP_PORTS 12
+
+/*
+ * Linux ports don't normally get allocated above 32K.
+ * I used an extra 4K port-space
+ */
+
+#define PORT_MASQ_BEGIN 61000
+#define PORT_MASQ_END (PORT_MASQ_BEGIN+4096)
+
+#define MASQUERADE_EXPIRE_TCP 15*60*HZ
+#define MASQUERADE_EXPIRE_TCP_FIN 2*60*HZ
+#define MASQUERADE_EXPIRE_UDP 5*60*HZ
+/*
+ * ICMP can no longer be modified on the fly using an ioctl - this
+ * define is the only way to change the timeouts
+ */
+#define MASQUERADE_EXPIRE_ICMP 125*HZ
+
+#define IP_MASQ_MOD_CTL 0x00
+#define IP_MASQ_USER_CTL 0x01
+
+#ifdef __KERNEL__
+
+#define IP_MASQ_TAB_SIZE 256
+
+#define IP_MASQ_F_NO_DADDR 0x0001 /* no daddr yet */
+#define IP_MASQ_F_NO_DPORT 0x0002 /* no dport set yet */
+#define IP_MASQ_F_NO_SADDR 0x0004 /* no sport set yet */
+#define IP_MASQ_F_NO_SPORT 0x0008 /* no sport set yet */
+
+#define IP_MASQ_F_DLOOSE 0x0010 /* loose dest binding */
+#define IP_MASQ_F_NO_REPLY 0x0080 /* no reply yet from outside */
+
+#define IP_MASQ_F_HASHED 0x0100 /* hashed entry */
+#define IP_MASQ_F_OUT_SEQ 0x0200 /* must do output seq adjust */
+#define IP_MASQ_F_IN_SEQ 0x0400 /* must do input seq adjust */
+
+#define IP_MASQ_F_MPORT 0x1000 /* own mport specified */
+#define IP_MASQ_F_USER 0x2000 /* from uspace */
+#define IP_MASQ_F_SIMPLE_HASH 0x8000 /* prevent s+d and m+d hashing */
+
+/*
+ * Delta seq. info structure
+ * Each MASQ struct has 2 (output AND input seq. changes).
+ */
+
+struct ip_masq_seq {
+ __u32 init_seq; /* Add delta from this seq */
+ short delta; /* Delta in sequence numbers */
+ short previous_delta; /* Delta in sequence numbers before last resized pkt */
+};
+
+/*
+ * MASQ structure allocated for each masqueraded association
+ */
+struct ip_masq {
+ struct list_head m_list, s_list, d_list;
+ /* hashed d-linked list heads */
+ atomic_t refcnt; /* reference count */
+ struct timer_list timer; /* Expiration timer */
+ __u16 protocol; /* Which protocol are we talking? */
+ __u16 sport, dport, mport; /* src, dst & masq ports */
+ __u32 saddr, daddr, maddr; /* src, dst & masq addresses */
+ struct ip_masq_seq out_seq, in_seq;
+ struct ip_masq_app *app; /* bound ip_masq_app object */
+ void *app_data; /* Application private data */
+ struct ip_masq *control; /* Master control connection */
+ atomic_t n_control; /* Number of "controlled" masqs */
+ unsigned flags; /* status flags */
+ unsigned timeout; /* timeout */
+ unsigned state; /* state info */
+ struct ip_masq_timeout_table *timeout_table;
+};
+
+/*
+ * Timeout values
+ * ipchains holds a copy of this definition
+ */
+
+struct ip_fw_masq {
+ int tcp_timeout;
+ int tcp_fin_timeout;
+ int udp_timeout;
+};
+
+union ip_masq_tphdr {
+ unsigned char *raw;
+ struct udphdr *uh;
+ struct tcphdr *th;
+ struct icmphdr *icmph;
+ __u16 *portp;
+};
+/*
+ * [0]: UDP free_ports
+ * [1]: TCP free_ports
+ * [2]: ICMP free_ports
+ */
+
+extern atomic_t ip_masq_free_ports[3];
+
+/*
+ * ip_masq initializer (registers symbols and /proc/net entries)
+ */
+extern int ip_masq_init(void);
+
+/*
+ * functions called from ip layer
+ */
+extern int ip_fw_masquerade(struct sk_buff **, __u32 maddr);
+extern int ip_fw_masq_icmp(struct sk_buff **, __u32 maddr);
+extern int ip_fw_unmasq_icmp(struct sk_buff *);
+extern int ip_fw_demasquerade(struct sk_buff **);
+
+/*
+ * ip_masq obj creation/deletion functions.
+ */
+extern struct ip_masq *ip_masq_new(int proto, __u32 maddr, __u16 mport, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned flags);
+
+extern void ip_masq_control_add(struct ip_masq *ms, struct ip_masq* ctl_ms);
+extern void ip_masq_control_del(struct ip_masq *ms);
+extern struct ip_masq * ip_masq_control_get(struct ip_masq *ms);
+
+struct ip_masq_ctl;
+
+struct ip_masq_hook {
+ int (*ctl)(int, struct ip_masq_ctl *, int);
+ int (*info)(char *, char **, off_t, int, int);
+};
+
+extern struct list_head ip_masq_m_table[IP_MASQ_TAB_SIZE];
+extern struct list_head ip_masq_s_table[IP_MASQ_TAB_SIZE];
+extern struct list_head ip_masq_d_table[IP_MASQ_TAB_SIZE];
+extern const char * ip_masq_state_name(int state);
+extern struct ip_masq_hook *ip_masq_user_hook;
+extern u32 ip_masq_select_addr(struct device *dev, u32 dst, int scope);
+/*
+ *
+ * IP_MASQ_APP: IP application masquerading definitions
+ *
+ */
+
+struct ip_masq_app
+{
+ struct ip_masq_app *next;
+ char *name; /* name of application proxy */
+ unsigned type; /* type = proto<<16 | port (host byte order)*/
+ int n_attach;
+ int (*masq_init_1) /* ip_masq initializer */
+ (struct ip_masq_app *, struct ip_masq *);
+ int (*masq_done_1) /* ip_masq fin. */
+ (struct ip_masq_app *, struct ip_masq *);
+ int (*pkt_out) /* output (masquerading) hook */
+ (struct ip_masq_app *, struct ip_masq *, struct sk_buff **, __u32);
+ int (*pkt_in) /* input (demasq) hook */
+ (struct ip_masq_app *, struct ip_masq *, struct sk_buff **, __u32);
+};
+
+/*
+ * ip_masq_app initializer
+ */
+extern int ip_masq_app_init(void);
+
+/*
+ * ip_masq_app object registration functions (port: host byte order)
+ */
+extern int register_ip_masq_app(struct ip_masq_app *mapp, unsigned short proto, __u16 port);
+extern int unregister_ip_masq_app(struct ip_masq_app *mapp);
+
+/*
+ * get ip_masq_app obj by proto,port(net_byte_order)
+ */
+extern struct ip_masq_app * ip_masq_app_get(unsigned short proto, __u16 port);
+
+/*
+ * ip_masq TO ip_masq_app (un)binding functions.
+ */
+extern struct ip_masq_app * ip_masq_bind_app(struct ip_masq *ms);
+extern int ip_masq_unbind_app(struct ip_masq *ms);
+
+/*
+ * output and input app. masquerading hooks.
+ *
+ */
+extern int ip_masq_app_pkt_out(struct ip_masq *, struct sk_buff **skb_p, __u32 maddr);
+extern int ip_masq_app_pkt_in(struct ip_masq *, struct sk_buff **skb_p, __u32 maddr);
+
+/*
+ * service routine(s).
+ */
+
+extern struct ip_masq * ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+extern struct ip_masq * ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+
+extern int ip_masq_listen(struct ip_masq *);
+
+static __inline__ struct ip_masq * ip_masq_in_get_iph(const struct iphdr *iph)
+{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+ return ip_masq_in_get(iph->protocol,
+ iph->saddr, portp[0],
+ iph->daddr, portp[1]);
+}
+
+static __inline__ struct ip_masq * ip_masq_out_get_iph(const struct iphdr *iph)
+{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+ return ip_masq_out_get(iph->protocol,
+ iph->saddr, portp[0],
+ iph->daddr, portp[1]);
+}
+
+extern void ip_masq_put(struct ip_masq *ms);
+
+
+extern rwlock_t __ip_masq_lock;
+
+#ifdef __SMP__
+#define read_lock_bh(lock) do { start_bh_atomic(); read_lock(lock); \
+ } while (0)
+#define read_unlock_bh(lock) do { read_unlock(lock); end_bh_atomic(); \
+ } while (0)
+#define write_lock_bh(lock) do { start_bh_atomic(); write_lock(lock); \
+ } while (0)
+#define write_unlock_bh(lock) do { write_unlock(lock); end_bh_atomic(); \
+ } while (0)
+#else
+#define read_lock_bh(lock) start_bh_atomic()
+#define read_unlock_bh(lock) end_bh_atomic()
+#define write_lock_bh(lock) start_bh_atomic()
+#define write_unlock_bh(lock) end_bh_atomic()
+#endif
+/*
+ *
+ */
+
+/*
+ * Debugging stuff
+ */
+
+extern int ip_masq_get_debug_level(void);
+
+#ifdef CONFIG_IP_MASQ_DEBUG
+#define IP_MASQ_DEBUG(level, msg...) do { \
+ if (level <= ip_masq_get_debug_level()) \
+ printk(KERN_DEBUG "IP_MASQ:" ## msg); \
+ } while (0)
+#else /* NO DEBUGGING at ALL */
+#define IP_MASQ_DEBUG(level, msg...) do { } while (0)
+#endif
+
+#define IP_MASQ_INFO(msg...) \
+ printk(KERN_INFO "IP_MASQ:" ## msg)
+
+#define IP_MASQ_ERR(msg...) \
+ printk(KERN_ERR "IP_MASQ:" ## msg)
+
+#define IP_MASQ_WARNING(msg...) \
+ printk(KERN_WARNING "IP_MASQ:" ## msg)
+
+
+/*
+ * /proc/net entry
+ */
+extern int ip_masq_proc_register(struct proc_dir_entry *);
+extern void ip_masq_proc_unregister(struct proc_dir_entry *);
+extern int ip_masq_app_getinfo(char *buffer, char **start, off_t offset, int length, int dummy);
+
+/*
+ * skb_replace function used by "client" modules to replace
+ * a segment of skb.
+ */
+extern struct sk_buff * ip_masq_skb_replace(struct sk_buff *skb, int pri, char *o_buf, int o_len, char *n_buf, int n_len);
+
+/*
+ * masq_proto_num returns 0 for UDP, 1 for TCP, 2 for ICMP
+ */
+
+static __inline__ int masq_proto_num(unsigned proto)
+{
+ switch (proto)
+ {
+ case IPPROTO_UDP: return (0); break;
+ case IPPROTO_TCP: return (1); break;
+ case IPPROTO_ICMP: return (2); break;
+ default: return (-1); break;
+ }
+}
+
+static __inline__ const char *masq_proto_name(unsigned proto)
+{
+ static char buf[20];
+ static const char *strProt[] = {"UDP","TCP","ICMP"};
+ int msproto = masq_proto_num(proto);
+
+ if (msproto<0||msproto>2) {
+ sprintf(buf, "IP_%d", proto);
+ return buf;
+ }
+ return strProt[msproto];
+}
+
+enum {
+ IP_MASQ_S_NONE = 0,
+ IP_MASQ_S_ESTABLISHED,
+ IP_MASQ_S_SYN_SENT,
+ IP_MASQ_S_SYN_RECV,
+ IP_MASQ_S_FIN_WAIT,
+ IP_MASQ_S_TIME_WAIT,
+ IP_MASQ_S_CLOSE,
+ IP_MASQ_S_CLOSE_WAIT,
+ IP_MASQ_S_LAST_ACK,
+ IP_MASQ_S_LISTEN,
+ IP_MASQ_S_UDP,
+ IP_MASQ_S_ICMP,
+ IP_MASQ_S_LAST
+};
+
+struct ip_masq_timeout_table {
+ atomic_t refcnt;
+ int scale;
+ int timeout[IP_MASQ_S_LAST+1];
+};
+
+static __inline__ void ip_masq_timeout_attach(struct ip_masq *ms, struct ip_masq_timeout_table *mstim)
+{
+ atomic_inc (&mstim->refcnt);
+ ms->timeout_table=mstim;
+}
+
+static __inline__ void ip_masq_timeout_detach(struct ip_masq *ms)
+{
+ struct ip_masq_timeout_table *mstim = ms->timeout_table;
+
+ if (!mstim)
+ return;
+ atomic_dec(&mstim->refcnt);
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _IP_MASQ_H */
diff --git a/pfinet/linux-src/include/net/ip_masq_mod.h b/pfinet/linux-src/include/net/ip_masq_mod.h
new file mode 100644
index 00000000..a7a67d6f
--- /dev/null
+++ b/pfinet/linux-src/include/net/ip_masq_mod.h
@@ -0,0 +1,86 @@
+/*
+ * IP Masquerading Modules Support
+ *
+ * Version: @(#)ip_masq_mod.h 0.01 97/10/30
+ *
+ * Author: Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
+ *
+ */
+
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/ip_fw.h>
+#include <linux/proc_fs.h>
+#include <net/ip_masq.h>
+
+#define IP_MASQ_MOD_NOP 0
+#define IP_MASQ_MOD_ACCEPT 1
+#define IP_MASQ_MOD_REJECT -1
+
+struct ip_masq_mod {
+ struct ip_masq_mod *next; /* next mod for addrs. lookups */
+ struct ip_masq_mod *next_reg; /* next mod for configuration ctls */
+ char *mmod_name;
+ atomic_t refcnt;
+ atomic_t mmod_nent; /* number of entries */
+ struct proc_dir_entry *mmod_proc_ent;
+ int (*mmod_ctl) (int optname, struct ip_masq_ctl *, int optlen);
+ int (*mmod_init) (void);
+ int (*mmod_done) (void);
+ int (*mmod_in_rule) (const struct sk_buff *, const struct iphdr *);
+ int (*mmod_in_update) (const struct sk_buff *, const struct iphdr *,
+ struct ip_masq *);
+ struct ip_masq * (*mmod_in_create) (const struct sk_buff *, const struct iphdr *, __u32);
+ int (*mmod_out_rule) (const struct sk_buff *, const struct iphdr *);
+ int (*mmod_out_update) (const struct sk_buff *, const struct iphdr *,
+ struct ip_masq *);
+ struct ip_masq * (*mmod_out_create) (const struct sk_buff *, const struct iphdr *, __u32);
+};
+
+/*
+ * Service routines (called from ip_masq.c)
+ */
+
+int ip_masq_mod_out_rule(const struct sk_buff *, const struct iphdr *);
+int ip_masq_mod_out_update(const struct sk_buff *, const struct iphdr *, struct ip_masq *ms);
+struct ip_masq * ip_masq_mod_out_create(const struct sk_buff *, const struct iphdr *iph, __u32 maddr);
+
+int ip_masq_mod_in_rule(const struct sk_buff *, const struct iphdr *iph);
+int ip_masq_mod_in_update(const struct sk_buff *, const struct iphdr *iph, struct ip_masq *ms);
+struct ip_masq * ip_masq_mod_in_create(const struct sk_buff *, const struct iphdr *iph, __u32 maddr);
+
+extern int ip_masq_mod_ctl(int optname, struct ip_masq_ctl *, int len);
+
+/*
+ * ip_masq_mod registration functions
+ */
+extern int register_ip_masq_mod(struct ip_masq_mod *mmod);
+extern int unregister_ip_masq_mod(struct ip_masq_mod *mmod);
+extern int ip_masq_mod_lkp_unlink(struct ip_masq_mod *mmod);
+extern int ip_masq_mod_lkp_link(struct ip_masq_mod *mmod);
+
+/*
+ * init functions protos
+ */
+extern int ip_portfw_init(void);
+extern int ip_mfw_init(void);
+extern int ip_autofw_init(void);
+
+/*
+ * Utility ...
+ */
+static __inline__ void ip_masq_mod_dec_nent(struct ip_masq_mod *mmod)
+{
+ if (atomic_dec_and_test(&mmod->mmod_nent)) {
+ ip_masq_mod_lkp_unlink(mmod);
+ }
+}
+static __inline__ void ip_masq_mod_inc_nent(struct ip_masq_mod *mmod)
+{
+ atomic_inc(&mmod->mmod_nent);
+ if (atomic_read(&mmod->mmod_nent)==1)
+ ip_masq_mod_lkp_link(mmod);
+}
+
+#endif /* __KERNEL__ */
diff --git a/pfinet/linux-src/include/net/ipconfig.h b/pfinet/linux-src/include/net/ipconfig.h
new file mode 100644
index 00000000..f9356946
--- /dev/null
+++ b/pfinet/linux-src/include/net/ipconfig.h
@@ -0,0 +1,21 @@
+/*
+ * $Id: ipconfig.h,v 1.3 1999/01/04 20:13:29 davem Exp $
+ *
+ * Copyright (C) 1997 Martin Mares
+ *
+ * Automatic IP Layer Configuration
+ */
+
+extern __u32 root_server_addr;
+extern u8 root_server_path[];
+extern u32 ic_myaddr;
+extern u32 ic_servaddr;
+extern u32 ic_gateway;
+extern u32 ic_netmask;
+extern int ic_enable;
+extern int ic_host_name_set;
+extern int ic_set_manually;
+extern int ic_proto_enabled;
+
+#define IC_BOOTP 1
+#define IC_RARP 2
diff --git a/pfinet/linux-src/include/net/ipip.h b/pfinet/linux-src/include/net/ipip.h
new file mode 100644
index 00000000..22c464c3
--- /dev/null
+++ b/pfinet/linux-src/include/net/ipip.h
@@ -0,0 +1,33 @@
+#ifndef __NET_IPIP_H
+#define __NET_IPIP_H 1
+
+#include <linux/if_tunnel.h>
+
+/* Keep error state on tunnel for 30 sec */
+#define IPTUNNEL_ERR_TIMEO (30*HZ)
+
+struct ip_tunnel
+{
+ struct ip_tunnel *next;
+ struct device *dev;
+ struct net_device_stats stat;
+
+ int recursion; /* Depth of hard_start_xmit recursion */
+ int err_count; /* Number of arrived ICMP errors */
+ unsigned long err_time; /* Time when the last ICMP error arrived */
+
+ /* These four fields used only by GRE */
+ __u32 i_seqno; /* The last seen seqno */
+ __u32 o_seqno; /* The last output seqno */
+ int hlen; /* Precalculated GRE header length */
+ int mlink;
+
+ struct ip_tunnel_parm parms;
+};
+
+extern int ipip_init(void);
+extern int ipgre_init(void);
+extern int sit_init(void);
+extern void sit_cleanup(void);
+
+#endif
diff --git a/pfinet/linux-src/include/net/ipv6.h b/pfinet/linux-src/include/net/ipv6.h
new file mode 100644
index 00000000..50e2299f
--- /dev/null
+++ b/pfinet/linux-src/include/net/ipv6.h
@@ -0,0 +1,325 @@
+/*
+ * Linux INET6 implementation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ *
+ * $Id: ipv6.h,v 1.16 1999/04/22 10:07:27 davem Exp $
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _NET_IPV6_H
+#define _NET_IPV6_H
+
+#include <linux/ipv6.h>
+#include <asm/hardirq.h>
+#include <net/ndisc.h>
+#include <net/flow.h>
+
+/*
+ * NextHeader field of IPv6 header
+ */
+
+#define NEXTHDR_HOP 0 /* Hop-by-hop option header. */
+#define NEXTHDR_TCP 6 /* TCP segment. */
+#define NEXTHDR_UDP 17 /* UDP message. */
+#define NEXTHDR_IPV6 41 /* IPv6 in IPv6 */
+#define NEXTHDR_ROUTING 43 /* Routing header. */
+#define NEXTHDR_FRAGMENT 44 /* Fragmentation/reassembly header. */
+#define NEXTHDR_ESP 50 /* Encapsulating security payload. */
+#define NEXTHDR_AUTH 51 /* Authentication header. */
+#define NEXTHDR_ICMP 58 /* ICMP for IPv6. */
+#define NEXTHDR_NONE 59 /* No next header */
+#define NEXTHDR_DEST 60 /* Destination options header. */
+
+#define NEXTHDR_MAX 255
+
+
+
+#define IPV6_DEFAULT_HOPLIMIT 64
+#define IPV6_DEFAULT_MCASTHOPS 1
+
+/*
+ * Addr type
+ *
+ * type - unicast | multicast | anycast
+ * scope - local | site | global
+ * v4 - compat
+ * v4mapped
+ * any
+ * loopback
+ */
+
+#define IPV6_ADDR_ANY 0x0000U
+
+#define IPV6_ADDR_UNICAST 0x0001U
+#define IPV6_ADDR_MULTICAST 0x0002U
+#define IPV6_ADDR_ANYCAST 0x0004U
+
+#define IPV6_ADDR_LOOPBACK 0x0010U
+#define IPV6_ADDR_LINKLOCAL 0x0020U
+#define IPV6_ADDR_SITELOCAL 0x0040U
+
+#define IPV6_ADDR_COMPATv4 0x0080U
+
+#define IPV6_ADDR_SCOPE_MASK 0x00f0U
+
+#define IPV6_ADDR_MAPPED 0x1000U
+#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
+
+/*
+ * fragmentation header
+ */
+
+struct frag_hdr {
+ unsigned char nexthdr;
+ unsigned char reserved;
+ unsigned short frag_off;
+ __u32 identification;
+};
+
+#ifdef __KERNEL__
+
+#include <net/sock.h>
+
+extern struct ipv6_mib ipv6_statistics;
+extern struct icmpv6_mib icmpv6_statistics;
+extern struct udp_mib udp_stats_in6;
+
+struct ip6_ra_chain
+{
+ struct ip6_ra_chain *next;
+ struct sock *sk;
+ int sel;
+ void (*destructor)(struct sock *);
+};
+
+extern struct ip6_ra_chain *ip6_ra_chain;
+
+/*
+ This structure is prepared by protocol, when parsing
+ ancillary data and passed to IPv6.
+ */
+
+struct ipv6_txoptions
+{
+ /* Length of this structure */
+ int tot_len;
+
+ /* length of extension headers */
+
+ __u16 opt_flen; /* after fragment hdr */
+ __u16 opt_nflen; /* before fragment hdr */
+
+ struct ipv6_opt_hdr *hopopt;
+ struct ipv6_opt_hdr *dst0opt;
+ struct ipv6_rt_hdr *srcrt; /* Routing Header */
+ struct ipv6_opt_hdr *auth;
+ struct ipv6_opt_hdr *dst1opt;
+
+ /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
+};
+
+struct ip6_flowlabel
+{
+ struct ip6_flowlabel *next;
+ u32 label;
+ struct in6_addr dst;
+ struct ipv6_txoptions *opt;
+ atomic_t users;
+ u32 linger;
+ u8 share;
+ u32 owner;
+ unsigned long lastuse;
+ unsigned long expires;
+};
+
+#define IPV6_FLOWINFO_MASK __constant_htonl(0x0FFFFFFF)
+#define IPV6_FLOWLABEL_MASK __constant_htonl(0x000FFFFF)
+
+struct ipv6_fl_socklist
+{
+ struct ipv6_fl_socklist *next;
+ struct ip6_flowlabel *fl;
+};
+
+extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, u32 label);
+extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
+ struct ip6_flowlabel * fl,
+ struct ipv6_txoptions * fopt);
+extern void fl6_free_socklist(struct sock *sk);
+extern int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen);
+extern void ip6_flowlabel_init(void);
+extern void ip6_flowlabel_cleanup(void);
+
+extern __inline__ void fl6_sock_release(struct ip6_flowlabel *fl)
+{
+ if (fl)
+ atomic_dec(&fl->users);
+}
+
+extern int ip6_ra_control(struct sock *sk, int sel,
+ void (*destructor)(struct sock *));
+
+
+extern int ip6_call_ra_chain(struct sk_buff *skb, int sel);
+
+extern u8 * ipv6_reassembly(struct sk_buff **skb, u8 *nhptr);
+
+extern u8 * ipv6_parse_hopopts(struct sk_buff *skb, u8 *nhptr);
+
+extern u8 * ipv6_parse_exthdrs(struct sk_buff **skb, u8 *nhptr);
+
+extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
+
+#define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */
+
+/*
+ * Function prototype for build_xmit
+ */
+
+typedef int (*inet_getfrag_t) (const void *data,
+ struct in6_addr *addr,
+ char *,
+ unsigned int, unsigned int);
+
+
+extern int ipv6_addr_type(struct in6_addr *addr);
+
+extern __inline__ int ipv6_addr_scope(struct in6_addr *addr)
+{
+ return ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK;
+}
+
+extern __inline__ int ipv6_addr_cmp(struct in6_addr *a1, struct in6_addr *a2)
+{
+ return memcmp((void *) a1, (void *) a2, sizeof(struct in6_addr));
+}
+
+extern __inline__ void ipv6_addr_copy(struct in6_addr *a1, struct in6_addr *a2)
+{
+ memcpy((void *) a1, (void *) a2, sizeof(struct in6_addr));
+}
+
+#ifndef __HAVE_ARCH_ADDR_SET
+extern __inline__ void ipv6_addr_set(struct in6_addr *addr,
+ __u32 w1, __u32 w2,
+ __u32 w3, __u32 w4)
+{
+ addr->s6_addr32[0] = w1;
+ addr->s6_addr32[1] = w2;
+ addr->s6_addr32[2] = w3;
+ addr->s6_addr32[3] = w4;
+}
+#endif
+
+extern __inline__ int ipv6_addr_any(struct in6_addr *a)
+{
+ return ((a->s6_addr32[0] | a->s6_addr32[1] |
+ a->s6_addr32[2] | a->s6_addr32[3] ) == 0);
+}
+
+/*
+ * Prototypes exported by ipv6
+ */
+
+/*
+ * rcv function (called from netdevice level)
+ */
+
+extern int ipv6_rcv(struct sk_buff *skb,
+ struct device *dev,
+ struct packet_type *pt);
+
+/*
+ * upper-layer output functions
+ */
+extern int ip6_xmit(struct sock *sk,
+ struct sk_buff *skb,
+ struct flowi *fl,
+ struct ipv6_txoptions *opt);
+
+extern int ip6_nd_hdr(struct sock *sk,
+ struct sk_buff *skb,
+ struct device *dev,
+ struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ int proto, int len);
+
+extern int ip6_build_xmit(struct sock *sk,
+ inet_getfrag_t getfrag,
+ const void *data,
+ struct flowi *fl,
+ unsigned length,
+ struct ipv6_txoptions *opt,
+ int hlimit, int flags);
+
+/*
+ * skb processing functions
+ */
+
+extern int ip6_output(struct sk_buff *skb);
+extern int ip6_forward(struct sk_buff *skb);
+extern int ip6_input(struct sk_buff *skb);
+extern int ip6_mc_input(struct sk_buff *skb);
+
+/*
+ * Extension header (options) processing
+ */
+
+extern u8 * ipv6_build_nfrag_opts(struct sk_buff *skb,
+ u8 *prev_hdr,
+ struct ipv6_txoptions *opt,
+ struct in6_addr *daddr,
+ u32 jumbolen);
+extern u8 * ipv6_build_frag_opts(struct sk_buff *skb,
+ u8 *prev_hdr,
+ struct ipv6_txoptions *opt);
+extern void ipv6_push_nfrag_opts(struct sk_buff *skb,
+ struct ipv6_txoptions *opt,
+ u8 *proto,
+ struct in6_addr **daddr_p);
+extern void ipv6_push_frag_opts(struct sk_buff *skb,
+ struct ipv6_txoptions *opt,
+ u8 *proto);
+
+extern u8 * ipv6_skip_exthdr(struct ipv6_opt_hdr *hdr,
+ u8 *nexthdrp, int len);
+
+extern struct ipv6_txoptions * ipv6_invert_rthdr(struct sock *sk,
+ struct ipv6_rt_hdr *hdr);
+
+
+/*
+ * socket options (ipv6_sockglue.c)
+ */
+
+extern int ipv6_setsockopt(struct sock *sk, int level,
+ int optname, char *optval,
+ int optlen);
+extern int ipv6_getsockopt(struct sock *sk, int level,
+ int optname, char *optval,
+ int *optlen);
+
+extern void ipv6_packet_init(void);
+
+extern void ipv6_netdev_notif_init(void);
+
+extern void ipv6_packet_cleanup(void);
+
+extern void ipv6_netdev_notif_cleanup(void);
+
+extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
+extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, u16 port,
+ u32 info, u8 *payload);
+extern void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info);
+
+#endif /* __KERNEL__ */
+#endif /* _NET_IPV6_H */
+
+
+
diff --git a/pfinet/linux-src/include/net/ipx.h b/pfinet/linux-src/include/net/ipx.h
new file mode 100644
index 00000000..2152e388
--- /dev/null
+++ b/pfinet/linux-src/include/net/ipx.h
@@ -0,0 +1,82 @@
+/*
+ * The following information is in its entirety obtained from:
+ *
+ * Novell 'IPX Router Specification' Version 1.10
+ * Part No. 107-000029-001
+ *
+ * Which is available from ftp.novell.com
+ */
+
+#ifndef _NET_INET_IPX_H_
+#define _NET_INET_IPX_H_
+
+#include <linux/netdevice.h>
+#include <net/datalink.h>
+#include <linux/ipx.h>
+
+typedef struct
+{
+ __u32 net;
+ __u8 node[IPX_NODE_LEN];
+ __u16 sock;
+} ipx_address;
+
+#define ipx_broadcast_node "\377\377\377\377\377\377"
+#define ipx_this_node "\0\0\0\0\0\0"
+
+struct ipxhdr
+{
+ __u16 ipx_checksum __attribute__ ((packed));
+#define IPX_NO_CHECKSUM 0xFFFF
+ __u16 ipx_pktsize __attribute__ ((packed));
+ __u8 ipx_tctrl;
+ __u8 ipx_type;
+#define IPX_TYPE_UNKNOWN 0x00
+#define IPX_TYPE_RIP 0x01 /* may also be 0 */
+#define IPX_TYPE_SAP 0x04 /* may also be 0 */
+#define IPX_TYPE_SPX 0x05 /* SPX protocol */
+#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
+#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
+ ipx_address ipx_dest __attribute__ ((packed));
+ ipx_address ipx_source __attribute__ ((packed));
+};
+
+#include <net/ipxcall.h>
+
+typedef struct ipx_interface {
+ /* IPX address */
+ __u32 if_netnum;
+ unsigned char if_node[IPX_NODE_LEN];
+
+ /* physical device info */
+ struct device *if_dev;
+ struct datalink_proto *if_dlink;
+ unsigned short if_dlink_type;
+
+ /* socket support */
+ unsigned short if_sknum;
+ struct sock *if_sklist;
+
+ /* administrative overhead */
+ int if_ipx_offset;
+ unsigned char if_internal;
+ unsigned char if_primary;
+
+ struct ipx_interface *if_next;
+} ipx_interface;
+
+typedef struct ipx_route {
+ __u32 ir_net;
+ ipx_interface *ir_intrfc;
+ unsigned char ir_routed;
+ unsigned char ir_router_node[IPX_NODE_LEN];
+ struct ipx_route *ir_next;
+} ipx_route;
+
+#define IPX_MIN_EPHEMERAL_SOCKET 0x4000
+#define IPX_MAX_EPHEMERAL_SOCKET 0x7fff
+
+extern int ipx_register_spx(struct proto_ops **, struct net_proto_family *);
+extern int ipx_unregister_spx(void);
+
+#endif /* def _NET_INET_IPX_H_ */
diff --git a/pfinet/linux-src/include/net/ipxcall.h b/pfinet/linux-src/include/net/ipxcall.h
new file mode 100644
index 00000000..eb5bd2bd
--- /dev/null
+++ b/pfinet/linux-src/include/net/ipxcall.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void ipx_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/include/net/lapb.h b/pfinet/linux-src/include/net/lapb.h
new file mode 100644
index 00000000..7cc9b345
--- /dev/null
+++ b/pfinet/linux-src/include/net/lapb.h
@@ -0,0 +1,150 @@
+#ifndef _LAPB_H
+#define _LAPB_H
+#include <linux/lapb.h>
+
+#define LAPB_HEADER_LEN 20 /* LAPB over Ethernet + a bit more */
+
+#define LAPB_ACK_PENDING_CONDITION 0x01
+#define LAPB_REJECT_CONDITION 0x02
+#define LAPB_PEER_RX_BUSY_CONDITION 0x04
+
+/* Control field templates */
+#define LAPB_I 0x00 /* Information frames */
+#define LAPB_S 0x01 /* Supervisory frames */
+#define LAPB_U 0x03 /* Unnumbered frames */
+
+#define LAPB_RR 0x01 /* Receiver ready */
+#define LAPB_RNR 0x05 /* Receiver not ready */
+#define LAPB_REJ 0x09 /* Reject */
+
+#define LAPB_SABM 0x2F /* Set Asynchronous Balanced Mode */
+#define LAPB_SABME 0x6F /* Set Asynchronous Balanced Mode Extended */
+#define LAPB_DISC 0x43 /* Disconnect */
+#define LAPB_DM 0x0F /* Disconnected mode */
+#define LAPB_UA 0x63 /* Unnumbered acknowledge */
+#define LAPB_FRMR 0x87 /* Frame reject */
+
+#define LAPB_ILLEGAL 0x100 /* Impossible to be a real frame type */
+
+#define LAPB_SPF 0x10 /* Poll/final bit for standard LAPB */
+#define LAPB_EPF 0x01 /* Poll/final bit for extended LAPB */
+
+#define LAPB_FRMR_W 0x01 /* Control field invalid */
+#define LAPB_FRMR_X 0x02 /* I field invalid */
+#define LAPB_FRMR_Y 0x04 /* I field too long */
+#define LAPB_FRMR_Z 0x08 /* Invalid N(R) */
+
+#define LAPB_POLLOFF 0
+#define LAPB_POLLON 1
+
+/* LAPB C-bit */
+#define LAPB_COMMAND 1
+#define LAPB_RESPONSE 2
+
+#define LAPB_ADDR_A 0x03
+#define LAPB_ADDR_B 0x01
+#define LAPB_ADDR_C 0x0F
+#define LAPB_ADDR_D 0x07
+
+/* Define Link State constants. */
+enum {
+ LAPB_STATE_0, /* Disconnected State */
+ LAPB_STATE_1, /* Awaiting Connection State */
+ LAPB_STATE_2, /* Awaiting Disconnection State */
+ LAPB_STATE_3, /* Data Transfer State */
+ LAPB_STATE_4 /* Frame Reject State */
+};
+
+#define LAPB_DEFAULT_MODE (LAPB_STANDARD | LAPB_SLP | LAPB_DTE)
+#define LAPB_DEFAULT_WINDOW 7 /* Window=7 */
+#define LAPB_DEFAULT_T1 (5 * HZ) /* T1=5s */
+#define LAPB_DEFAULT_T2 (1 * HZ) /* T2=1s */
+#define LAPB_DEFAULT_N2 20 /* N2=20 */
+
+#define LAPB_SMODULUS 8
+#define LAPB_EMODULUS 128
+
+/*
+ * Information about the current frame.
+ */
+struct lapb_frame {
+ unsigned short type; /* Parsed type */
+ unsigned short nr, ns; /* N(R), N(S) */
+ unsigned char cr; /* Command/Response */
+ unsigned char pf; /* Poll/Final */
+ unsigned char control[2]; /* Original control data*/
+};
+
+/*
+ * The per LAPB connection control structure.
+ */
+typedef struct lapb_cb {
+ struct lapb_cb *next;
+ void *token;
+
+ /* Link status fields */
+ unsigned int mode;
+ unsigned char state;
+ unsigned short vs, vr, va;
+ unsigned char condition;
+ unsigned short n2, n2count;
+ unsigned short t1, t2;
+ struct timer_list t1timer, t2timer;
+
+ /* Internal control information */
+ struct sk_buff_head write_queue;
+ struct sk_buff_head ack_queue;
+ unsigned char window;
+ struct lapb_register_struct callbacks;
+
+ /* FRMR control information */
+ struct lapb_frame frmr_data;
+ unsigned char frmr_type;
+} lapb_cb;
+
+/* lapb_iface.c */
+extern void lapb_connect_confirmation(lapb_cb *, int);
+extern void lapb_connect_indication(lapb_cb *, int);
+extern void lapb_disconnect_confirmation(lapb_cb *, int);
+extern void lapb_disconnect_indication(lapb_cb *, int);
+extern int lapb_data_indication(lapb_cb *, struct sk_buff *);
+extern int lapb_data_transmit(lapb_cb *, struct sk_buff *);
+
+/* lapb_in.c */
+extern void lapb_data_input(lapb_cb *, struct sk_buff *);
+
+/* lapb_out.c */
+extern void lapb_kick(lapb_cb *);
+extern void lapb_transmit_buffer(lapb_cb *, struct sk_buff *, int);
+extern void lapb_establish_data_link(lapb_cb *);
+extern void lapb_enquiry_response(lapb_cb *);
+extern void lapb_timeout_response(lapb_cb *);
+extern void lapb_check_iframes_acked(lapb_cb *, unsigned short);
+extern void lapb_check_need_response(lapb_cb *, int, int);
+
+/* lapb_subr.c */
+extern void lapb_clear_queues(lapb_cb *);
+extern void lapb_frames_acked(lapb_cb *, unsigned short);
+extern void lapb_requeue_frames(lapb_cb *);
+extern int lapb_validate_nr(lapb_cb *, unsigned short);
+extern void lapb_decode(lapb_cb *, struct sk_buff *, struct lapb_frame *);
+extern void lapb_send_control(lapb_cb *, int, int, int);
+extern void lapb_transmit_frmr(lapb_cb *);
+
+/* lapb_timer.c */
+extern void lapb_start_t1timer(lapb_cb *);
+extern void lapb_start_t2timer(lapb_cb *);
+extern void lapb_stop_t1timer(lapb_cb *);
+extern void lapb_stop_t2timer(lapb_cb *);
+extern int lapb_t1timer_running(lapb_cb *);
+
+/*
+ * Debug levels.
+ * 0 = Off
+ * 1 = State Changes
+ * 2 = Packets I/O and State Changes
+ * 3 = Hex dumps, Packets I/O and State Changes.
+ */
+#define LAPB_DEBUG 0
+
+#endif
diff --git a/pfinet/linux-src/include/net/lapbcall.h b/pfinet/linux-src/include/net/lapbcall.h
new file mode 100644
index 00000000..825e7f2c
--- /dev/null
+++ b/pfinet/linux-src/include/net/lapbcall.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void lapb_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/include/net/llc.h b/pfinet/linux-src/include/net/llc.h
new file mode 100644
index 00000000..654a658d
--- /dev/null
+++ b/pfinet/linux-src/include/net/llc.h
@@ -0,0 +1,135 @@
+#include <linux/skbuff.h>
+
+#define LLC_MODULE
+
+typedef struct llc_struct llc;
+typedef struct llc_struct *llcptr;
+
+/*
+ * LLC private data area structure.
+ */
+
+struct llc_struct
+{
+ char eye[4]; /* To recognize llc area in dump */
+ int retry_count; /* LLC link state variables */
+ unsigned char name[9]; /* name of this llc instance */
+ unsigned char s_flag;
+ unsigned char p_flag;
+ unsigned char f_flag;
+ unsigned char data_flag;
+ unsigned char cause_flag;
+ unsigned char vs; /* Send state variable */
+ unsigned char vr; /* Receive state variable */
+ unsigned char remote_busy;
+ unsigned char state; /* Current state of type2 llc procedure */
+ int n1; /* Maximum number of bytes in I pdu 7.8.2 */
+ int n2; /* Naximum number of retransmissions 7.8.2 */
+ unsigned char k; /* Transmit window size 7.8.4, tw in IBM doc*/
+ unsigned char rw; /* Receive window size */
+ struct
+ {
+ /*
+ * FRMR_RSP info field structure: 5.4.2.3.5 p55
+ */
+
+ unsigned char cntl1;
+ unsigned char cntl2;
+ unsigned char vs;
+ unsigned char vr_cr;
+ unsigned char xxyz;
+ } frmr_info_fld;
+
+ /*
+ * Timers in 7.8.1 page 78
+ */
+
+#define P_TIMER 0
+#define REJ_TIMER 1
+#define ACK_TIMER 2
+#define BUSY_TIMER 3
+ unsigned long timer_expire_time[4];
+ unsigned char timer_state[4]; /* The state of each timer */
+#define TIMER_IDLE 0
+#define TIMER_RUNNING 1
+#define TIMER_EXPIRED 2
+ unsigned long timer_interval[4];
+ struct timer_list tl[4];
+
+ /*
+ * Client entry point, called by the LLC.
+ */
+
+ void (*llc_event)(struct llc_struct *);
+
+ /*
+ * Mux and Demux variables
+ */
+
+ char * client_data; /* Pointer to clients context */
+ unsigned char local_sap;
+ unsigned char remote_sap ;
+ char remote_mac[MAX_ADDR_LEN]; /* MAC address of remote session partner */
+ struct device *dev; /* Device we are attached to */
+
+ unsigned char llc_mode; /* See doc 7.1 on p70 */
+#define MODE_ADM 1
+#define MODE_ABM 2
+
+ int llc_callbacks; /* Pending callbacks */
+#define LLC_CONN_INDICATION 1 /* We have to ensure the names don't */
+#define LLC_CONN_CONFIRM 2 /* mix up with the 802 state table */
+#define LLC_DATA_INDIC 4
+#define LLC_DISC_INDICATION 8
+#define LLC_RESET_INDIC_LOC 16
+#define LLC_RESET_INDIC_REM 32
+#define LLC_RST_CONFIRM 64
+#define LLC_FRMR_RECV 128
+#define LLC_FRMR_SENT 256
+#define LLC_REMOTE_BUSY 512
+#define LLC_REMOTE_NOTBUSY 1024
+#define LLC_TEST_INDICATION 2048
+#define LLC_XID_INDICATION 4096
+#define LLC_UI_DATA 8192
+
+ struct sk_buff *inc_skb; /* Saved data buffer for indications */
+
+ struct sk_buff_head rtq; /* Retransmit queue */
+ struct sk_buff_head atq; /* Await transit queue */
+
+ unsigned char xid_count;
+
+ struct llc_struct *nextllc; /* ptr to next llc struct in proto chain */
+};
+
+#define ADD_TO_RTQ(skb) skb_queue_tail(&lp->rtq,skb)
+#define ADD_TO_ATQ(skb) skb_queue_tail(&lp->atq,skb)
+
+void llc_cancel_timers(llcptr lp);
+int llc_decode_frametype(frameptr fr);
+llcptr llc_find(void);
+int llc_free_acknowledged_skbs(llcptr lp, unsigned char ack);
+void llc_handle_xid_indication( char *chsp, short int ll, char *xid_data);
+void llc_interpret_pseudo_code(llcptr lp, int pc_label, struct sk_buff *skb, char type);
+void llc_add_to_queue(struct sk_buff *skb, struct sk_buff **f, struct sk_buff **b);
+void llc_process_otype2_frame(llcptr lp, struct sk_buff *skb, char type);
+struct sk_buff *llc_pull_from_atq(llcptr lp);
+int llc_resend_ipdu(llcptr lp, unsigned char ack_nr, unsigned char type, char p);
+void llc_sendpdu(llcptr lp, char type, char pf, int data_len, char *pdu_data);
+void llc_sendipdu(llcptr lp, char type, char pf, struct sk_buff *skb);
+void llc_start_timer(llcptr lp, int t);
+void llc_stop_timer(llcptr lp, int t);
+void llc_timer_expired(llcptr lp, int t);
+int llc_validate_seq_nos(llcptr lp, frameptr fr);
+
+int llc_data_request(llcptr lp, struct sk_buff *skb);
+void llc_unit_data_request(llcptr lp, int ll, char * data);
+void llc_disconnect_request(llcptr lp);
+void llc_connect_request(llcptr lp);
+void llc_xid_request(llcptr lp, char opt, int data_len, char *pdu_data);
+void llc_test_request(llcptr lp, int data_len, char *pdu_data);
+
+int register_cl2llc_client(llcptr llc, const char *device, void (*ops)(llcptr), u8 *rmac, u8 ssap, u8 dsap);
+void unregister_cl2llc_client(llcptr lp);
+int llc_mac_data_indicate(llcptr lp, struct sk_buff *skb );
+
diff --git a/pfinet/linux-src/include/net/llc_frame.h b/pfinet/linux-src/include/net/llc_frame.h
new file mode 100644
index 00000000..e8fb198d
--- /dev/null
+++ b/pfinet/linux-src/include/net/llc_frame.h
@@ -0,0 +1,98 @@
+/* if_ether.h needed for definition of ETH_DATA_LEN and ETH_ALEN
+ */
+#include "linux/if_ether.h"
+
+/* frame layout based on par3.2 "LLC PDU format"
+ */
+typedef union { /* pdu layout from pages 40 & 44 */
+ struct { /* general header, all pdu types */
+ unsigned dsap : 8; /* dest service access point */
+ unsigned ssap : 8; /* source service access point */
+ unsigned f1 : 1; /* I- U- or S- format id bits */
+ unsigned f2 : 1;
+ unsigned : 6;
+ unsigned : 8;
+ } pdu_hdr;
+ struct {
+ char dummy1[2]; /* dsap + ssap */
+ char byte1;
+ char byte2;
+ } pdu_cntl; /* unformatted control bytes */
+ struct { /* header of an Information pdu */
+ unsigned char dummy2[2];
+ unsigned : 1;
+ unsigned ns : 7;
+ unsigned i_pflag : 1; /* poll/final bit */
+ unsigned nr : 7; /* N(R) */
+ unsigned char is_info[ ETH_DATA_LEN ];
+ } i_hdr;
+ struct { /* header of a Supervisory pdu */
+ unsigned char dummy3[2];
+ unsigned : 2;
+ unsigned ss : 2; /* supervisory function bits */
+ unsigned : 4;
+ unsigned s_pflag : 1; /* poll/final bit */
+ unsigned nr : 7; /* N(R) */
+ } s_hdr;
+
+/* when accessing the P/F bit or the N(R) field there's no need to distinguish
+ I pdus from S pdus i_pflag and s_pflag / i_nr and s_nr map to the same
+ physical location.
+ */
+ struct { /* header of an Unnumbered pdu */
+ unsigned char dummy4[2];
+ unsigned : 2;
+ unsigned mm1 : 2; /* modifier function part1 */
+ unsigned u_pflag : 1; /* P/F for U- pdus */
+ unsigned mm2 : 3; /* modifier function part2 */
+ unsigned char u_info[ ETH_DATA_LEN-1];
+ } u_hdr;
+ struct { /* mm field in an Unnumbered pdu */
+ unsigned char dummy5[2];
+ unsigned : 2;
+ unsigned mm : 6; /* must be masked to get ridd of P/F ! */
+ } u_mm;
+
+} frame_type, *frameptr;
+
+/* frame format test macros: */
+
+#define IS_UFRAME( fr ) ( ( (fr)->pdu_hdr.f1) & ( (fr)->pdu_hdr.f2) )
+
+#define IS_IFRAME( fr ) ( !( (fr)->pdu_hdr.f1) )
+
+#define IS_SFRAME( fr ) ( ( (fr)->pdu_hdr.f1) & !( (fr)->pdu_hdr.f2) )
+
+#define IS_RSP( fr ) ( fr->pdu_hdr.ssap & 0x01 )
+
+
+/* The transition table, the _encode tables and some tests in the
+ source code depend on the numeric order of these values.
+ Think twice before changing.
+ */
+
+/* frame names for TYPE 2 operation: */
+#define I_CMD 0
+#define RR_CMD 1
+#define RNR_CMD 2
+#define REJ_CMD 3
+#define DISC_CMD 4
+#define SABME_CMD 5
+#define I_RSP 6
+#define RR_RSP 7
+#define RNR_RSP 8
+#define REJ_RSP 9
+#define UA_RSP 10
+#define DM_RSP 11
+#define FRMR_RSP 12
+
+/* junk frame name: */
+#define BAD_FRAME 13
+#define NO_FRAME 13
+
+/* frame names for TYPE 1 operation: */
+#define UI_CMD 14
+#define XID_CMD 15
+#define TEST_CMD 16
+#define XID_RSP 17
+#define TEST_RSP 18
diff --git a/pfinet/linux-src/include/net/llc_name.h b/pfinet/linux-src/include/net/llc_name.h
new file mode 100644
index 00000000..72128719
--- /dev/null
+++ b/pfinet/linux-src/include/net/llc_name.h
@@ -0,0 +1,7 @@
+char *frame_names[] =
+ {"I_CMD","RR_CMD","RNR_CMD","REJ_CMD","DISC_CMD",
+ "SABME_CMD","I_RSP","RR_RSP","RNR_RSP","REJ_RSP",
+ "UA_RSP","DM_RSP","FRMR_RSP","BAD_FRAME","UI_CMD",
+ "XID_CMD","TEST_CMD","XID_RSP","TEST_RSP"
+};
+
diff --git a/pfinet/linux-src/include/net/llc_state.h b/pfinet/linux-src/include/net/llc_state.h
new file mode 100644
index 00000000..bb18e9bd
--- /dev/null
+++ b/pfinet/linux-src/include/net/llc_state.h
@@ -0,0 +1,4 @@
+char *state_names[] = {
+ "ADM","CONN","RESET_WAIT","RESET_CHECK","SETUP",
+ "RESET","D_CONN","ERROR","NORMAL"
+};
diff --git a/pfinet/linux-src/include/net/llccall.h b/pfinet/linux-src/include/net/llccall.h
new file mode 100644
index 00000000..07013ba3
--- /dev/null
+++ b/pfinet/linux-src/include/net/llccall.h
@@ -0,0 +1,3 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void llc_init(struct net_proto *pro);
+
diff --git a/pfinet/linux-src/include/net/ndisc.h b/pfinet/linux-src/include/net/ndisc.h
new file mode 100644
index 00000000..7a51f367
--- /dev/null
+++ b/pfinet/linux-src/include/net/ndisc.h
@@ -0,0 +1,123 @@
+#ifndef _NDISC_H
+#define _NDISC_H
+
+/*
+ * ICMP codes for neighbour discovery messages
+ */
+
+#define NDISC_ROUTER_SOLICITATION 133
+#define NDISC_ROUTER_ADVERTISEMENT 134
+#define NDISC_NEIGHBOUR_SOLICITATION 135
+#define NDISC_NEIGHBOUR_ADVERTISEMENT 136
+#define NDISC_REDIRECT 137
+
+/*
+ * ndisc options
+ */
+
+#define ND_OPT_SOURCE_LL_ADDR 1
+#define ND_OPT_TARGET_LL_ADDR 2
+#define ND_OPT_PREFIX_INFO 3
+#define ND_OPT_REDIRECT_HDR 4
+#define ND_OPT_MTU 5
+
+#define MAX_RTR_SOLICITATION_DELAY HZ
+
+#define ND_REACHABLE_TIME (30*HZ)
+#define ND_RETRANS_TIMER HZ
+
+#define ND_MIN_RANDOM_FACTOR (1/2)
+#define ND_MAX_RANDOM_FACTOR (3/2)
+
+#ifdef __KERNEL__
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/icmpv6.h>
+#include <net/neighbour.h>
+#include <asm/atomic.h>
+
+extern struct neigh_table nd_tbl;
+
+struct nd_msg {
+ struct icmp6hdr icmph;
+ struct in6_addr target;
+ struct {
+ __u8 opt_type;
+ __u8 opt_len;
+ __u8 link_addr[MAX_ADDR_LEN];
+ } opt;
+};
+
+struct ra_msg {
+ struct icmp6hdr icmph;
+ __u32 reachable_time;
+ __u32 retrans_timer;
+};
+
+
+extern int ndisc_init(struct net_proto_family *ops);
+
+extern void ndisc_cleanup(void);
+
+extern int ndisc_rcv(struct sk_buff *skb, unsigned long len);
+
+extern void ndisc_send_ns(struct device *dev,
+ struct neighbour *neigh,
+ struct in6_addr *solicit,
+ struct in6_addr *daddr,
+ struct in6_addr *saddr);
+
+extern void ndisc_send_rs(struct device *dev,
+ struct in6_addr *saddr,
+ struct in6_addr *daddr);
+
+extern void ndisc_forwarding_on(void);
+extern void ndisc_forwarding_off(void);
+
+extern void ndisc_send_redirect(struct sk_buff *skb,
+ struct neighbour *neigh,
+ struct in6_addr *target);
+
+extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct device *dev, int dir);
+
+
+struct rt6_info * dflt_rt_lookup(void);
+
+/*
+ * IGMP
+ */
+extern int igmp6_init(struct net_proto_family *ops);
+
+extern void igmp6_cleanup(void);
+
+extern int igmp6_event_query(struct sk_buff *skb,
+ struct icmp6hdr *hdr,
+ int len);
+
+extern int igmp6_event_report(struct sk_buff *skb,
+ struct icmp6hdr *hdr,
+ int len);
+
+extern void igmp6_cleanup(void);
+
+extern __inline__ struct neighbour * ndisc_get_neigh(struct device *dev, struct in6_addr *addr)
+{
+
+ if (dev) {
+ struct neighbour *neigh;
+
+ start_bh_atomic();
+ neigh = __neigh_lookup(&nd_tbl, addr, dev, 1);
+ end_bh_atomic();
+
+ return neigh;
+ }
+ return NULL;
+}
+
+
+#endif /* __KERNEL__ */
+
+
+#endif
diff --git a/pfinet/linux-src/include/net/neighbour.h b/pfinet/linux-src/include/net/neighbour.h
new file mode 100644
index 00000000..5c5d90bb
--- /dev/null
+++ b/pfinet/linux-src/include/net/neighbour.h
@@ -0,0 +1,272 @@
+#ifndef _NET_NEIGHBOUR_H
+#define _NET_NEIGHBOUR_H
+
+/*
+ * Generic neighbour manipulation
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+ */
+
+/* The following flags & states are exported to user space,
+ so that they should be moved to include/linux/ directory.
+ */
+
+/*
+ * Neighbor Cache Entry Flags
+ */
+
+#define NTF_PROXY 0x08 /* == ATF_PUBL */
+#define NTF_ROUTER 0x80
+
+/*
+ * Neighbor Cache Entry States.
+ */
+
+#define NUD_INCOMPLETE 0x01
+#define NUD_REACHABLE 0x02
+#define NUD_STALE 0x04
+#define NUD_DELAY 0x08
+#define NUD_PROBE 0x10
+#define NUD_FAILED 0x20
+
+/* Dummy states */
+#define NUD_NOARP 0x40
+#define NUD_PERMANENT 0x80
+#define NUD_NONE 0x00
+
+/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
+ and make no address resolution or NUD.
+ NUD_PERMANENT is also cannot be deleted by garbage collectors.
+ */
+
+#ifdef __KERNEL__
+
+#include <asm/atomic.h>
+#include <linux/skbuff.h>
+
+#define NUD_IN_TIMER (NUD_INCOMPLETE|NUD_DELAY|NUD_PROBE)
+#define NUD_VALID (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
+#define NUD_CONNECTED (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
+
+struct neigh_parms
+{
+ struct neigh_parms *next;
+ int (*neigh_setup)(struct neighbour *);
+ struct neigh_table *tbl;
+ int entries;
+ void *priv;
+
+ void *sysctl_table;
+
+ int base_reachable_time;
+ int retrans_time;
+ int gc_staletime;
+ int reachable_time;
+ int delay_probe_time;
+
+ int queue_len;
+ int ucast_probes;
+ int app_probes;
+ int mcast_probes;
+ int anycast_delay;
+ int proxy_delay;
+ int proxy_qlen;
+ int locktime;
+};
+
+struct neigh_statistics
+{
+ unsigned long allocs;
+ unsigned long res_failed;
+ unsigned long rcv_probes_mcast;
+ unsigned long rcv_probes_ucast;
+};
+
+struct neighbour
+{
+ struct neighbour *next;
+ struct neigh_table *tbl;
+ struct neigh_parms *parms;
+ struct device *dev;
+ unsigned long used;
+ unsigned long confirmed;
+ unsigned long updated;
+ __u8 flags;
+ __u8 nud_state;
+ __u8 type;
+ __u8 probes;
+ unsigned char ha[MAX_ADDR_LEN];
+ struct hh_cache *hh;
+ atomic_t refcnt;
+ int (*output)(struct sk_buff *skb);
+ struct sk_buff_head arp_queue;
+ struct timer_list timer;
+ struct neigh_ops *ops;
+ u8 primary_key[0];
+};
+
+struct neigh_ops
+{
+ int family;
+ void (*destructor)(struct neighbour *);
+ void (*solicit)(struct neighbour *, struct sk_buff*);
+ void (*error_report)(struct neighbour *, struct sk_buff*);
+ int (*output)(struct sk_buff*);
+ int (*connected_output)(struct sk_buff*);
+ int (*hh_output)(struct sk_buff*);
+ int (*queue_xmit)(struct sk_buff*);
+};
+
+struct pneigh_entry
+{
+ struct pneigh_entry *next;
+ struct device *dev;
+ u8 key[0];
+};
+
+#define NEIGH_HASHMASK 0x1F
+#define PNEIGH_HASHMASK 0xF
+
+/*
+ * neighbour table manipulation
+ */
+
+
+struct neigh_table
+{
+ struct neigh_table *next;
+ int family;
+ int entry_size;
+ int key_len;
+ int (*constructor)(struct neighbour *);
+ int (*pconstructor)(struct pneigh_entry *);
+ void (*pdestructor)(struct pneigh_entry *);
+ void (*proxy_redo)(struct sk_buff *skb);
+ struct neigh_parms parms;
+ /* HACK. gc_* shoul follow parms without a gap! */
+ int gc_interval;
+ int gc_thresh1;
+ int gc_thresh2;
+ int gc_thresh3;
+ unsigned long last_flush;
+ struct timer_list gc_timer;
+ struct timer_list proxy_timer;
+ struct sk_buff_head proxy_queue;
+ int entries;
+ atomic_t lock;
+ unsigned long last_rand;
+ struct neigh_parms *parms_list;
+ struct neigh_statistics stats;
+ struct neighbour *hash_buckets[NEIGH_HASHMASK+1];
+ struct pneigh_entry *phash_buckets[PNEIGH_HASHMASK+1];
+};
+
+extern void neigh_table_init(struct neigh_table *tbl);
+extern int neigh_table_clear(struct neigh_table *tbl);
+extern struct neighbour *__neigh_lookup(struct neigh_table *tbl,
+ const void *pkey, struct device *dev,
+ int creat);
+extern void neigh_destroy(struct neighbour *neigh);
+extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
+extern int neigh_update(struct neighbour *neigh, u8 *lladdr, u8 new, int override, int arp);
+extern int neigh_ifdown(struct neigh_table *tbl, struct device *dev);
+extern int neigh_resolve_output(struct sk_buff *skb);
+extern int neigh_connected_output(struct sk_buff *skb);
+extern int neigh_compat_output(struct sk_buff *skb);
+extern struct neighbour *neigh_event_ns(struct neigh_table *tbl,
+ u8 *lladdr, void *saddr,
+ struct device *dev);
+
+extern struct neigh_parms *neigh_parms_alloc(struct device *dev, struct neigh_table *tbl);
+extern void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
+extern unsigned long neigh_rand_reach_time(unsigned long base);
+
+extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+ struct sk_buff *skb);
+extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, const void *key, struct device *dev, int creat);
+extern int pneigh_delete(struct neigh_table *tbl, const void *key, struct device *dev);
+
+struct netlink_callback;
+struct nlmsghdr;
+extern int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb);
+extern int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+extern void neigh_app_ns(struct neighbour *n);
+
+extern int neigh_sysctl_register(struct device *dev, struct neigh_parms *p,
+ int p_id, int pdev_id, char *p_name);
+extern void neigh_sysctl_unregister(struct neigh_parms *p);
+
+/*
+ * Neighbour references
+ *
+ * When neighbour pointers are passed to "client" code the
+ * reference count is increased. The count is 0 if the node
+ * is only referenced by the corresponding table.
+ */
+
+extern __inline__ void neigh_release(struct neighbour *neigh)
+{
+ if (atomic_dec_and_test(&neigh->refcnt) && neigh->tbl == NULL)
+ neigh_destroy(neigh);
+}
+
+extern __inline__ struct neighbour * neigh_clone(struct neighbour *neigh)
+{
+ if (neigh)
+ atomic_inc(&neigh->refcnt);
+ return neigh;
+}
+
+extern __inline__ void neigh_confirm(struct neighbour *neigh)
+{
+ if (neigh)
+ neigh->confirmed = jiffies;
+}
+
+extern __inline__ struct neighbour *
+neigh_lookup(struct neigh_table *tbl, const void *pkey, struct device *dev)
+{
+ struct neighbour *neigh;
+ start_bh_atomic();
+ neigh = __neigh_lookup(tbl, pkey, dev, 0);
+ end_bh_atomic();
+ return neigh;
+}
+
+extern __inline__ int neigh_is_connected(struct neighbour *neigh)
+{
+ return neigh->nud_state&NUD_CONNECTED;
+}
+
+extern __inline__ int neigh_is_valid(struct neighbour *neigh)
+{
+ return neigh->nud_state&NUD_VALID;
+}
+
+extern __inline__ int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+{
+ neigh->used = jiffies;
+ if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE)))
+ return __neigh_event_send(neigh, skb);
+ return 0;
+}
+
+extern __inline__ void neigh_table_lock(struct neigh_table *tbl)
+{
+ atomic_inc(&tbl->lock);
+ synchronize_bh();
+}
+
+extern __inline__ void neigh_table_unlock(struct neigh_table *tbl)
+{
+ atomic_dec(&tbl->lock);
+}
+
+
+#endif
+#endif
+
+
diff --git a/pfinet/linux-src/include/net/netbeuicall.h b/pfinet/linux-src/include/net/netbeuicall.h
new file mode 100644
index 00000000..5176f82b
--- /dev/null
+++ b/pfinet/linux-src/include/net/netbeuicall.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void netbeui_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/include/net/netrom.h b/pfinet/linux-src/include/net/netrom.h
new file mode 100644
index 00000000..356a7d27
--- /dev/null
+++ b/pfinet/linux-src/include/net/netrom.h
@@ -0,0 +1,181 @@
+/*
+ * Declarations of NET/ROM type objects.
+ *
+ * Jonathan Naylor G4KLX 9/4/95
+ */
+
+#ifndef _NETROM_H
+#define _NETROM_H
+#include <linux/netrom.h>
+
+#define NR_NETWORK_LEN 15
+#define NR_TRANSPORT_LEN 5
+
+#define NR_PROTO_IP 0x0C
+
+#define NR_PROTOEXT 0x00
+#define NR_CONNREQ 0x01
+#define NR_CONNACK 0x02
+#define NR_DISCREQ 0x03
+#define NR_DISCACK 0x04
+#define NR_INFO 0x05
+#define NR_INFOACK 0x06
+
+#define NR_CHOKE_FLAG 0x80
+#define NR_NAK_FLAG 0x40
+#define NR_MORE_FLAG 0x20
+
+/* Define Link State constants. */
+enum {
+ NR_STATE_0,
+ NR_STATE_1,
+ NR_STATE_2,
+ NR_STATE_3
+};
+
+#define NR_COND_ACK_PENDING 0x01
+#define NR_COND_REJECT 0x02
+#define NR_COND_PEER_RX_BUSY 0x04
+#define NR_COND_OWN_RX_BUSY 0x08
+
+#define NR_DEFAULT_T1 (120 * HZ) /* Outstanding frames - 120 seconds */
+#define NR_DEFAULT_T2 (5 * HZ) /* Response delay - 5 seconds */
+#define NR_DEFAULT_N2 3 /* Number of Retries - 3 */
+#define NR_DEFAULT_T4 (180 * HZ) /* Busy Delay - 180 seconds */
+#define NR_DEFAULT_IDLE (0 * 60 * HZ) /* No Activity Timeout - none */
+#define NR_DEFAULT_WINDOW 4 /* Default Window Size - 4 */
+#define NR_DEFAULT_OBS 6 /* Default Obsolescence Count - 6 */
+#define NR_DEFAULT_QUAL 10 /* Default Neighbour Quality - 10 */
+#define NR_DEFAULT_TTL 16 /* Default Time To Live - 16 */
+#define NR_DEFAULT_ROUTING 1 /* Is routing enabled ? */
+#define NR_DEFAULT_FAILS 2 /* Link fails until route fails */
+
+#define NR_MODULUS 256
+#define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */
+#define NR_MAX_PACKET_SIZE 236 /* Maximum Packet Length - 236 */
+
+typedef struct {
+ ax25_address user_addr, source_addr, dest_addr;
+ struct device *device;
+ unsigned char my_index, my_id;
+ unsigned char your_index, your_id;
+ unsigned char state, condition, bpqext, window;
+ unsigned short vs, vr, va, vl;
+ unsigned char n2, n2count;
+ unsigned long t1, t2, t4, idle;
+ unsigned short fraglen;
+ struct timer_list t1timer;
+ struct timer_list t2timer;
+ struct timer_list t4timer;
+ struct timer_list idletimer;
+ struct sk_buff_head ack_queue;
+ struct sk_buff_head reseq_queue;
+ struct sk_buff_head frag_queue;
+ struct sock *sk; /* Backlink to socket */
+} nr_cb;
+
+struct nr_neigh {
+ struct nr_neigh *next;
+ ax25_address callsign;
+ ax25_digi *digipeat;
+ ax25_cb *ax25;
+ struct device *dev;
+ unsigned char quality;
+ unsigned char locked;
+ unsigned short count;
+ unsigned int number;
+ unsigned char failed;
+};
+
+struct nr_route {
+ unsigned char quality;
+ unsigned char obs_count;
+ struct nr_neigh *neighbour;
+};
+
+struct nr_node {
+ struct nr_node *next;
+ ax25_address callsign;
+ char mnemonic[7];
+ unsigned char which;
+ unsigned char count;
+ struct nr_route routes[3];
+};
+
+/* af_netrom.c */
+extern int sysctl_netrom_default_path_quality;
+extern int sysctl_netrom_obsolescence_count_initialiser;
+extern int sysctl_netrom_network_ttl_initialiser;
+extern int sysctl_netrom_transport_timeout;
+extern int sysctl_netrom_transport_maximum_tries;
+extern int sysctl_netrom_transport_acknowledge_delay;
+extern int sysctl_netrom_transport_busy_delay;
+extern int sysctl_netrom_transport_requested_window_size;
+extern int sysctl_netrom_transport_no_activity_timeout;
+extern int sysctl_netrom_routing_control;
+extern int sysctl_netrom_link_fails_count;
+extern int nr_rx_frame(struct sk_buff *, struct device *);
+extern void nr_destroy_socket(struct sock *);
+
+/* nr_dev.c */
+extern int nr_rx_ip(struct sk_buff *, struct device *);
+extern int nr_init(struct device *);
+
+#include <net/nrcall.h>
+
+/* nr_in.c */
+extern int nr_process_rx_frame(struct sock *, struct sk_buff *);
+
+/* nr_loopback.c */
+extern void nr_loopback_init(void);
+extern void nr_loopback_clear(void);
+extern int nr_loopback_queue(struct sk_buff *);
+
+/* nr_out.c */
+extern void nr_output(struct sock *, struct sk_buff *);
+extern void nr_send_nak_frame(struct sock *);
+extern void nr_kick(struct sock *);
+extern void nr_transmit_buffer(struct sock *, struct sk_buff *);
+extern void nr_establish_data_link(struct sock *);
+extern void nr_enquiry_response(struct sock *);
+extern void nr_check_iframes_acked(struct sock *, unsigned short);
+
+/* nr_route.c */
+extern void nr_rt_device_down(struct device *);
+extern struct device *nr_dev_first(void);
+extern struct device *nr_dev_get(ax25_address *);
+extern int nr_rt_ioctl(unsigned int, void *);
+extern void nr_link_failed(ax25_cb *, int);
+extern int nr_route_frame(struct sk_buff *, ax25_cb *);
+extern int nr_nodes_get_info(char *, char **, off_t, int, int);
+extern int nr_neigh_get_info(char *, char **, off_t, int, int);
+extern void nr_rt_free(void);
+
+/* nr_subr.c */
+extern void nr_clear_queues(struct sock *);
+extern void nr_frames_acked(struct sock *, unsigned short);
+extern void nr_requeue_frames(struct sock *);
+extern int nr_validate_nr(struct sock *, unsigned short);
+extern int nr_in_rx_window(struct sock *, unsigned short);
+extern void nr_write_internal(struct sock *, int);
+extern void nr_transmit_refusal(struct sk_buff *, int);
+extern void nr_disconnect(struct sock *, int);
+
+/* nr_timer.c */
+extern void nr_start_heartbeat(struct sock *);
+extern void nr_start_t1timer(struct sock *);
+extern void nr_start_t2timer(struct sock *);
+extern void nr_start_t4timer(struct sock *);
+extern void nr_start_idletimer(struct sock *);
+extern void nr_stop_heartbeat(struct sock *);
+extern void nr_stop_t1timer(struct sock *);
+extern void nr_stop_t2timer(struct sock *);
+extern void nr_stop_t4timer(struct sock *);
+extern void nr_stop_idletimer(struct sock *);
+extern int nr_t1timer_running(struct sock *);
+
+/* sysctl_net_netrom.c */
+extern void nr_register_sysctl(void);
+extern void nr_unregister_sysctl(void);
+
+#endif
diff --git a/pfinet/linux-src/include/net/nrcall.h b/pfinet/linux-src/include/net/nrcall.h
new file mode 100644
index 00000000..09ee699d
--- /dev/null
+++ b/pfinet/linux-src/include/net/nrcall.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void nr_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/include/net/p8022.h b/pfinet/linux-src/include/net/p8022.h
new file mode 100644
index 00000000..03d7c3d6
--- /dev/null
+++ b/pfinet/linux-src/include/net/p8022.h
@@ -0,0 +1,7 @@
+#ifndef _NET_P8022_H
+#define _NET_P8022_H
+
+extern struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *));
+extern void unregister_8022_client(unsigned char type);
+
+#endif
diff --git a/pfinet/linux-src/include/net/p8022call.h b/pfinet/linux-src/include/net/p8022call.h
new file mode 100644
index 00000000..14f0c2ce
--- /dev/null
+++ b/pfinet/linux-src/include/net/p8022call.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of Space.c simpler */
+extern void p8022_proto_init(struct net_proto *);
diff --git a/pfinet/linux-src/include/net/pkt_cls.h b/pfinet/linux-src/include/net/pkt_cls.h
new file mode 100644
index 00000000..b8547e60
--- /dev/null
+++ b/pfinet/linux-src/include/net/pkt_cls.h
@@ -0,0 +1,93 @@
+#ifndef __NET_PKT_CLS_H
+#define __NET_PKT_CLS_H
+
+
+#include <linux/pkt_cls.h>
+
+struct rtattr;
+struct tcmsg;
+
+/* Basic packet classifier frontend definitions. */
+
+struct tcf_result
+{
+ unsigned long class;
+ u32 classid;
+};
+
+struct tcf_proto
+{
+ /* Fast access part */
+ struct tcf_proto *next;
+ void *root;
+ int (*classify)(struct sk_buff*, struct tcf_proto*, struct tcf_result *);
+ u32 protocol;
+
+ /* All the rest */
+ u32 prio;
+ u32 classid;
+ struct Qdisc *q;
+ void *data;
+ struct tcf_proto_ops *ops;
+};
+
+struct tcf_walker
+{
+ int stop;
+ int skip;
+ int count;
+ int (*fn)(struct tcf_proto *, unsigned long node, struct tcf_walker *);
+};
+
+struct tcf_proto_ops
+{
+ struct tcf_proto_ops *next;
+ char kind[IFNAMSIZ];
+
+ int (*classify)(struct sk_buff*, struct tcf_proto*, struct tcf_result *);
+ int (*init)(struct tcf_proto*);
+ void (*destroy)(struct tcf_proto*);
+
+ unsigned long (*get)(struct tcf_proto*, u32 handle);
+ void (*put)(struct tcf_proto*, unsigned long);
+ int (*change)(struct tcf_proto*, unsigned long, u32 handle, struct rtattr **, unsigned long *);
+ int (*delete)(struct tcf_proto*, unsigned long);
+ void (*walk)(struct tcf_proto*, struct tcf_walker *arg);
+
+ /* rtnetlink specific */
+ int (*dump)(struct tcf_proto*, unsigned long, struct sk_buff *skb, struct tcmsg*);
+};
+
+/* Main classifier routine: scans classifier chain attached
+ to this qdisc, (optionally) tests for protocol and asks
+ specific classifiers.
+ */
+
+extern __inline__ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res)
+{
+ int err = 0;
+ u32 protocol = skb->protocol;
+
+ for ( ; tp; tp = tp->next) {
+ if ((tp->protocol == protocol ||
+ tp->protocol == __constant_htons(ETH_P_ALL)) &&
+ (err = tp->classify(skb, tp, res)) >= 0)
+ return err;
+ }
+ return -1;
+}
+
+extern __inline__ unsigned long cls_set_class(unsigned long *clp, unsigned long cl)
+{
+ unsigned long old_cl;
+
+ old_cl = *clp;
+ *clp = cl;
+ synchronize_bh();
+ return old_cl;
+}
+
+extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
+extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
+
+#endif
diff --git a/pfinet/linux-src/include/net/pkt_sched.h b/pfinet/linux-src/include/net/pkt_sched.h
new file mode 100644
index 00000000..9911464f
--- /dev/null
+++ b/pfinet/linux-src/include/net/pkt_sched.h
@@ -0,0 +1,407 @@
+#ifndef __NET_PKT_SCHED_H
+#define __NET_PKT_SCHED_H
+
+#define PSCHED_GETTIMEOFDAY 1
+#define PSCHED_JIFFIES 2
+#define PSCHED_CPU 3
+
+#define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES
+
+#include <linux/pkt_sched.h>
+#include <net/pkt_cls.h>
+
+struct rtattr;
+struct Qdisc;
+
+struct qdisc_walker
+{
+ int stop;
+ int skip;
+ int count;
+ int (*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *);
+};
+
+struct Qdisc_class_ops
+{
+ /* Child qdisc manipulation */
+ int (*graft)(struct Qdisc *, unsigned long cl, struct Qdisc *, struct Qdisc **);
+ struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl);
+
+ /* Class manipulation routines */
+ unsigned long (*get)(struct Qdisc *, u32 classid);
+ void (*put)(struct Qdisc *, unsigned long);
+ int (*change)(struct Qdisc *, u32, u32, struct rtattr **, unsigned long *);
+ int (*delete)(struct Qdisc *, unsigned long);
+ void (*walk)(struct Qdisc *, struct qdisc_walker * arg);
+
+ /* Filter manipulation */
+ struct tcf_proto ** (*tcf_chain)(struct Qdisc *, unsigned long);
+ unsigned long (*bind_tcf)(struct Qdisc *, unsigned long, u32 classid);
+ void (*unbind_tcf)(struct Qdisc *, unsigned long);
+
+ /* rtnetlink specific */
+ int (*dump)(struct Qdisc *, unsigned long, struct sk_buff *skb, struct tcmsg*);
+};
+
+struct Qdisc_ops
+{
+ struct Qdisc_ops *next;
+ struct Qdisc_class_ops *cl_ops;
+ char id[IFNAMSIZ];
+ int priv_size;
+
+ int (*enqueue)(struct sk_buff *, struct Qdisc *);
+ struct sk_buff * (*dequeue)(struct Qdisc *);
+ int (*requeue)(struct sk_buff *, struct Qdisc *);
+ int (*drop)(struct Qdisc *);
+
+ int (*init)(struct Qdisc *, struct rtattr *arg);
+ void (*reset)(struct Qdisc *);
+ void (*destroy)(struct Qdisc *);
+ int (*change)(struct Qdisc *, struct rtattr *arg);
+
+ int (*dump)(struct Qdisc *, struct sk_buff *);
+};
+
+struct Qdisc_head
+{
+ struct Qdisc_head *forw;
+};
+
+extern struct Qdisc_head qdisc_head;
+
+struct Qdisc
+{
+ struct Qdisc_head h;
+ int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
+ struct sk_buff * (*dequeue)(struct Qdisc *dev);
+ unsigned flags;
+#define TCQ_F_BUILTIN 1
+#define TCQ_F_THROTTLED 2
+ struct Qdisc_ops *ops;
+ struct Qdisc *next;
+ u32 handle;
+ atomic_t refcnt;
+ struct sk_buff_head q;
+ struct device *dev;
+
+ struct tc_stats stats;
+ unsigned long tx_timeo;
+ unsigned long tx_last;
+ int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
+
+ /* This field is deprecated, but it is still used by CBQ
+ * and it will live until better solution will be invented.
+ */
+ struct Qdisc *__parent;
+
+ char data[0];
+};
+
+struct qdisc_rate_table
+{
+ struct tc_ratespec rate;
+ u32 data[256];
+ struct qdisc_rate_table *next;
+ int refcnt;
+};
+
+
+/*
+ Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
+
+ Normal IP packet size ~ 512byte, hence:
+
+ 0.5Kbyte/1Mbyte/sec = 0.5msec, so that we need 50usec timer for
+ 10Mbit ethernet.
+
+ 10msec resolution -> <50Kbit/sec.
+
+ The result: [34]86 is not good choice for QoS router :-(
+
+ The things are not so bad, because we may use artifical
+ clock evaluated by integration of network data flow
+ in the most critical places.
+
+ Note: we do not use fastgettimeofday.
+ The reason is that, when it is not the same thing as
+ gettimeofday, it returns invalid timestamp, which is
+ not updated, when net_bh is active.
+
+ So, use PSCHED_CLOCK_SOURCE = PSCHED_CPU on alpha and pentiums
+ with rtdsc. And PSCHED_JIFFIES on all other architectures, including [34]86
+ and pentiums without rtdsc.
+ You can use PSCHED_GETTIMEOFDAY on another architectures,
+ which have fast and precise clock source, but it is too expensive.
+ */
+
+/* General note about internal clock.
+
+ Any clock source returns time intervals, measured in units
+ close to 1usec. With source PSCHED_GETTIMEOFDAY it is precisely
+ microseconds, otherwise something close but different chosen to minimize
+ arithmetic cost. Ratio usec/internal untis in form nominator/denominator
+ may be read from /proc/net/psched.
+ */
+
+
+#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
+
+typedef struct timeval psched_time_t;
+typedef long psched_tdiff_t;
+
+#define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp))
+#define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
+
+#define PSCHED_EXPORTLIST EXPORT_SYMBOL(psched_tod_diff);
+
+#else /* PSCHED_CLOCK_SOURCE != PSCHED_GETTIMEOFDAY */
+
+#define PSCHED_EXPORTLIST PSCHED_EXPORTLIST_1 PSCHED_EXPORTLIST_2
+
+typedef u64 psched_time_t;
+typedef long psched_tdiff_t;
+
+extern psched_time_t psched_time_base;
+
+#if PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES
+
+#if HZ == 100
+#define PSCHED_JSCALE 13
+#elif HZ == 1024
+#define PSCHED_JSCALE 10
+#else
+#define PSCHED_JSCALE 0
+#endif
+
+#define PSCHED_EXPORTLIST_2
+
+#if ~0UL == 0xFFFFFFFF
+
+#define PSCHED_WATCHER unsigned long
+
+extern PSCHED_WATCHER psched_time_mark;
+
+#define PSCHED_GET_TIME(stamp) ((stamp) = psched_time_base + (((unsigned long)(jiffies-psched_time_mark))<<PSCHED_JSCALE))
+
+#define PSCHED_EXPORTLIST_1 EXPORT_SYMBOL(psched_time_base); \
+ EXPORT_SYMBOL(psched_time_mark);
+
+#else
+
+#define PSCHED_GET_TIME(stamp) ((stamp) = (jiffies<<PSCHED_JSCALE))
+
+#define PSCHED_EXPORTLIST_1
+
+#endif
+
+#define PSCHED_US2JIFFIE(delay) (((delay)+(1<<PSCHED_JSCALE)-1)>>PSCHED_JSCALE)
+
+#elif PSCHED_CLOCK_SOURCE == PSCHED_CPU
+
+extern psched_tdiff_t psched_clock_per_hz;
+extern int psched_clock_scale;
+
+#define PSCHED_EXPORTLIST_2 EXPORT_SYMBOL(psched_clock_per_hz); \
+ EXPORT_SYMBOL(psched_clock_scale);
+
+#define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
+
+#if CPU == 586 || CPU == 686
+
+#define PSCHED_GET_TIME(stamp) \
+({ u64 __cur; \
+ __asm__ __volatile__ (".byte 0x0f,0x31" :"=A" (__cur)); \
+ (stamp) = __cur>>psched_clock_scale; \
+})
+
+#define PSCHED_EXPORTLIST_1
+
+#elif defined (__alpha__)
+
+#define PSCHED_WATCHER u32
+
+extern PSCHED_WATCHER psched_time_mark;
+
+#define PSCHED_GET_TIME(stamp) \
+({ u32 __res; \
+ __asm__ __volatile__ ("rpcc %0" : "r="(__res)); \
+ if (__res <= psched_time_mark) psched_time_base += 0x100000000UL; \
+ psched_time_mark = __res; \
+ (stamp) = (psched_time_base + __res)>>psched_clock_scale; \
+})
+
+#define PSCHED_EXPORTLIST_1 EXPORT_SYMBOL(psched_time_base); \
+ EXPORT_SYMBOL(psched_time_mark);
+
+#else
+
+#error PSCHED_CLOCK_SOURCE=PSCHED_CPU is not supported on this arch.
+
+#endif /* ARCH */
+
+#endif /* PSCHED_CLOCK_SOURCE == PSCHED_JIFFIES */
+
+#endif /* PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY */
+
+#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY
+#define PSCHED_TDIFF(tv1, tv2) \
+({ \
+ int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
+ int __delta = (tv1).tv_usec - (tv2).tv_usec; \
+ if (__delta_sec) { \
+ switch (__delta_sec) { \
+ default: \
+ __delta = 0; \
+ case 2: \
+ __delta += 1000000; \
+ case 1: \
+ __delta += 1000000; \
+ } \
+ } \
+ __delta; \
+})
+
+extern int psched_tod_diff(int delta_sec, int bound);
+
+#define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
+({ \
+ int __delta_sec = (tv1).tv_sec - (tv2).tv_sec; \
+ int __delta = (tv1).tv_usec - (tv2).tv_usec; \
+ switch (__delta_sec) { \
+ default: \
+ __delta = psched_tod_diff(__delta_sec, bound); guard; break; \
+ case 2: \
+ __delta += 1000000; \
+ case 1: \
+ __delta += 1000000; \
+ case 0: ; \
+ } \
+ __delta; \
+})
+
+#define PSCHED_TLESS(tv1, tv2) (((tv1).tv_usec < (tv2).tv_usec && \
+ (tv1).tv_sec <= (tv2).tv_sec) || \
+ (tv1).tv_sec < (tv2).tv_sec)
+
+#define PSCHED_TADD2(tv, delta, tv_res) \
+({ \
+ int __delta = (tv).tv_usec + (delta); \
+ (tv_res).tv_sec = (tv).tv_sec; \
+ if (__delta > 1000000) { (tv_res).tv_sec++; __delta -= 1000000; } \
+ (tv_res).tv_usec = __delta; \
+})
+
+#define PSCHED_TADD(tv, delta) \
+({ \
+ (tv).tv_usec += (delta); \
+ if ((tv).tv_usec > 1000000) { (tv).tv_sec++; \
+ (tv).tv_usec -= 1000000; } \
+})
+
+/* Set/check that time is in the "past perfect";
+ it depends on concrete representation of system time
+ */
+
+#define PSCHED_SET_PASTPERFECT(t) ((t).tv_sec = 0)
+#define PSCHED_IS_PASTPERFECT(t) ((t).tv_sec == 0)
+
+#define PSCHED_AUDIT_TDIFF(t) ({ if ((t) > 2000000) (t) = 2000000; })
+
+#else
+
+#define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2))
+#define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
+({ \
+ long __delta = (tv1) - (tv2); \
+ if ( __delta > (bound)) { __delta = (bound); guard; } \
+ __delta; \
+})
+
+
+#define PSCHED_TLESS(tv1, tv2) ((tv1) < (tv2))
+#define PSCHED_TADD2(tv, delta, tv_res) ((tv_res) = (tv) + (delta))
+#define PSCHED_TADD(tv, delta) ((tv) += (delta))
+#define PSCHED_SET_PASTPERFECT(t) ((t) = 0)
+#define PSCHED_IS_PASTPERFECT(t) ((t) == 0)
+#define PSCHED_AUDIT_TDIFF(t)
+
+#endif
+
+struct tcf_police
+{
+ struct tcf_police *next;
+ int refcnt;
+ u32 index;
+
+ int action;
+ int result;
+ u32 ewma_rate;
+ u32 burst;
+ u32 mtu;
+
+ u32 toks;
+ u32 ptoks;
+ psched_time_t t_c;
+ struct qdisc_rate_table *R_tab;
+ struct qdisc_rate_table *P_tab;
+
+ struct tc_stats stats;
+};
+
+extern void tcf_police_destroy(struct tcf_police *p);
+extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
+extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
+extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
+
+extern __inline__ void tcf_police_release(struct tcf_police *p)
+{
+ if (p && --p->refcnt == 0)
+ tcf_police_destroy(p);
+}
+
+extern struct Qdisc noop_qdisc;
+extern struct Qdisc_ops noop_qdisc_ops;
+extern struct Qdisc_ops pfifo_qdisc_ops;
+extern struct Qdisc_ops bfifo_qdisc_ops;
+
+int register_qdisc(struct Qdisc_ops *qops);
+int unregister_qdisc(struct Qdisc_ops *qops);
+struct Qdisc *qdisc_lookup(struct device *dev, u32 handle);
+struct Qdisc *qdisc_lookup_class(struct device *dev, u32 handle);
+void dev_init_scheduler(struct device *dev);
+void dev_shutdown(struct device *dev);
+void dev_activate(struct device *dev);
+void dev_deactivate(struct device *dev);
+void qdisc_reset(struct Qdisc *qdisc);
+void qdisc_destroy(struct Qdisc *qdisc);
+struct Qdisc * qdisc_create_dflt(struct device *dev, struct Qdisc_ops *ops);
+int qdisc_new_estimator(struct tc_stats *stats, struct rtattr *opt);
+void qdisc_kill_estimator(struct tc_stats *stats);
+struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab);
+void qdisc_put_rtab(struct qdisc_rate_table *tab);
+int teql_init(void);
+int tc_filter_init(void);
+int pktsched_init(void);
+
+void qdisc_run_queues(void);
+int qdisc_restart(struct device *dev);
+
+extern __inline__ void qdisc_wakeup(struct device *dev)
+{
+ if (!dev->tbusy) {
+ struct Qdisc *q = dev->qdisc;
+ if (qdisc_restart(dev) && q->h.forw == NULL) {
+ q->h.forw = qdisc_head.forw;
+ qdisc_head.forw = &q->h;
+ }
+ }
+}
+
+extern __inline__ unsigned psched_mtu(struct device *dev)
+{
+ unsigned mtu = dev->mtu;
+ return dev->hard_header ? mtu + dev->hard_header_len : mtu;
+}
+
+#endif
diff --git a/pfinet/linux-src/include/net/profile.h b/pfinet/linux-src/include/net/profile.h
new file mode 100644
index 00000000..82fad0a3
--- /dev/null
+++ b/pfinet/linux-src/include/net/profile.h
@@ -0,0 +1,311 @@
+#include <linux/config.h> /* for CONFIG_NET_PROFILE */
+#ifndef _NET_PROFILE_H_
+#define _NET_PROFILE_H_ 1
+
+#ifdef CONFIG_NET_PROFILE
+
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
+
+struct net_profile_slot
+{
+ char id[16];
+ struct net_profile_slot *next;
+ struct timeval entered;
+ struct timeval accumulator;
+ struct timeval irq;
+ int hits;
+ int active;
+ int underflow;
+};
+
+extern atomic_t net_profile_active;
+extern struct timeval net_profile_adjust;
+extern void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved);
+
+#if CPU == 586 || CPU == 686
+
+
+extern __inline__ void net_profile_stamp(struct timeval *pstamp)
+{
+ __asm__ __volatile__ (".byte 0x0f,0x31"
+ :"=a" (pstamp->tv_usec),
+ "=d" (pstamp->tv_sec));
+}
+
+extern __inline__ void net_profile_accumulate(struct timeval *entered,
+ struct timeval *leaved,
+ struct timeval *acc)
+{
+ __asm__ __volatile__ ("subl %2,%0\n\t"
+ "sbbl %3,%1\n\t"
+ "addl %4,%0\n\t"
+ "adcl %5,%1\n\t"
+ "subl " SYMBOL_NAME_STR(net_profile_adjust) "+4,%0\n\t"
+ "sbbl $0,%1\n\t"
+ : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
+ : "g" (entered->tv_usec), "g" (entered->tv_sec),
+ "g" (leaved->tv_usec), "g" (leaved->tv_sec),
+ "0" (acc->tv_usec), "1" (acc->tv_sec));
+}
+
+extern __inline__ void net_profile_sub(struct timeval *sub,
+ struct timeval *acc)
+{
+ __asm__ __volatile__ ("subl %2,%0\n\t"
+ "sbbl %3,%1\n\t"
+ : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
+ : "g" (sub->tv_usec), "g" (sub->tv_sec),
+ "0" (acc->tv_usec), "1" (acc->tv_sec));
+}
+
+extern __inline__ void net_profile_add(struct timeval *add,
+ struct timeval *acc)
+{
+ __asm__ __volatile__ ("addl %2,%0\n\t"
+ "adcl %3,%1\n\t"
+ : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
+ : "g" (add->tv_usec), "g" (add->tv_sec),
+ "0" (acc->tv_usec), "1" (acc->tv_sec));
+}
+
+
+#elif defined (__alpha__)
+
+extern __u32 alpha_lo;
+extern long alpha_hi;
+
+/* On alpha cycle counter has only 32 bits :-( :-( */
+
+extern __inline__ void net_profile_stamp(struct timeval *pstamp)
+{
+ __u32 result;
+ __asm__ __volatile__ ("rpcc %0" : "r="(result));
+ if (result <= alpha_lo)
+ alpha_hi++;
+ alpha_lo = result;
+ pstamp->tv_sec = alpha_hi;
+ pstamp->tv_usec = alpha_lo;
+}
+
+extern __inline__ void net_profile_accumulate(struct timeval *entered,
+ struct timeval *leaved,
+ struct timeval *acc)
+{
+ time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec
+ - net_profile_adjust.tv_usec;
+ time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec;
+
+ if (usecs >= 0x100000000L) {
+ usecs -= 0x100000000L;
+ secs++;
+ } else if (usecs < -0x100000000L) {
+ usecs += 0x200000000L;
+ secs -= 2;
+ } else if (usecs < 0) {
+ usecs += 0x100000000L;
+ secs--;
+ }
+ acc->tv_sec = secs;
+ acc->tv_usec = usecs;
+}
+
+extern __inline__ void net_profile_sub(struct timeval *entered,
+ struct timeval *leaved)
+{
+ time_t usecs = leaved->tv_usec - entered->tv_usec;
+ time_t secs = leaved->tv_sec - entered->tv_sec;
+
+ if (usecs < 0) {
+ usecs += 0x100000000L;
+ secs--;
+ }
+ leaved->tv_sec = secs;
+ leaved->tv_usec = usecs;
+}
+
+extern __inline__ void net_profile_add(struct timeval *entered, struct timeval *leaved)
+{
+ time_t usecs = leaved->tv_usec + entered->tv_usec;
+ time_t secs = leaved->tv_sec + entered->tv_sec;
+
+ if (usecs >= 0x100000000L) {
+ usecs -= 0x100000000L;
+ secs++;
+ }
+ leaved->tv_sec = secs;
+ leaved->tv_usec = usecs;
+}
+
+
+#else
+
+extern __inline__ void net_profile_stamp(struct timeval *pstamp)
+{
+ /* Not "fast" counterpart! On architectures without
+ cpu clock "fast" routine is absolutely useless in this
+ situation. do_gettimeofday still says something on slow-slow-slow
+ boxes, though it eats more cpu time than the sobject of
+ investigation :-) :-)
+ */
+ do_gettimeofday(pstamp);
+}
+
+extern __inline__ void net_profile_accumulate(struct timeval *entered,
+ struct timeval *leaved,
+ struct timeval *acc)
+{
+ time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec
+ - net_profile_adjust.tv_usec;
+ time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec;
+
+ if (usecs >= 1000000) {
+ usecs -= 1000000;
+ secs++;
+ } else if (usecs < -1000000) {
+ usecs += 2000000;
+ secs -= 2;
+ } else if (usecs < 0) {
+ usecs += 1000000;
+ secs--;
+ }
+ acc->tv_sec = secs;
+ acc->tv_usec = usecs;
+}
+
+extern __inline__ void net_profile_sub(struct timeval *entered,
+ struct timeval *leaved)
+{
+ time_t usecs = leaved->tv_usec - entered->tv_usec;
+ time_t secs = leaved->tv_sec - entered->tv_sec;
+
+ if (usecs < 0) {
+ usecs += 1000000;
+ secs--;
+ }
+ leaved->tv_sec = secs;
+ leaved->tv_usec = usecs;
+}
+
+extern __inline__ void net_profile_add(struct timeval *entered, struct timeval *leaved)
+{
+ time_t usecs = leaved->tv_usec + entered->tv_usec;
+ time_t secs = leaved->tv_sec + entered->tv_sec;
+
+ if (usecs >= 1000000) {
+ usecs -= 1000000;
+ secs++;
+ }
+ leaved->tv_sec = secs;
+ leaved->tv_usec = usecs;
+}
+
+
+
+#endif
+
+extern __inline__ void net_profile_enter(struct net_profile_slot *s)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ if (s->active++ == 0) {
+ net_profile_stamp(&s->entered);
+ atomic_inc(&net_profile_active);
+ }
+ restore_flags(flags);
+}
+
+extern __inline__ void net_profile_leave_irq(struct net_profile_slot *s)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ if (--s->active <= 0) {
+ if (s->active == 0) {
+ struct timeval curr_pstamp;
+ net_profile_stamp(&curr_pstamp);
+ net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator);
+ if (!atomic_dec_and_test(&net_profile_active))
+ net_profile_irq_adjust(&s->entered, &curr_pstamp);
+ } else {
+ s->underflow++;
+ }
+ }
+ s->hits++;
+ restore_flags(flags);
+}
+
+extern __inline__ void net_profile_leave(struct net_profile_slot *s)
+{
+ unsigned long flags;
+ save_flags(flags);
+ cli();
+ if (--s->active <= 0) {
+ if (s->active == 0) {
+ struct timeval curr_pstamp;
+ net_profile_stamp(&curr_pstamp);
+ net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator);
+ atomic_dec(&net_profile_active);
+ } else {
+ s->underflow++;
+ }
+ }
+ s->hits++;
+ restore_flags(flags);
+}
+
+
+#define NET_PROFILE_ENTER(slot) net_profile_enter(&net_prof_##slot)
+#define NET_PROFILE_LEAVE(slot) net_profile_leave(&net_prof_##slot)
+#define NET_PROFILE_LEAVE_IRQ(slot) net_profile_leave_irq(&net_prof_##slot)
+
+#define NET_PROFILE_SKB_CLEAR(skb) ({ \
+ skb->pstamp.tv_usec = 0; \
+})
+
+#define NET_PROFILE_SKB_INIT(skb) ({ \
+ net_profile_stamp(&skb->pstamp); \
+})
+
+#define NET_PROFILE_SKB_PASSED(skb, slot) ({ \
+ if (skb->pstamp.tv_usec) { \
+ struct timeval cur_pstamp = skb->pstamp; \
+ net_profile_stamp(&skb->pstamp); \
+ net_profile_accumulate(&cur_pstamp, &skb->pstamp, &net_prof_##slot.accumulator); \
+ net_prof_##slot.hits++; \
+ }})
+
+#define NET_PROFILE_DECL(slot) \
+ extern struct net_profile_slot net_prof_##slot;
+
+#define NET_PROFILE_DEFINE(slot) \
+ struct net_profile_slot net_prof_##slot = { #slot, };
+
+#define NET_PROFILE_REGISTER(slot) net_profile_register(&net_prof_##slot)
+#define NET_PROFILE_UNREGISTER(slot) net_profile_unregister(&net_prof_##slot)
+
+extern int net_profile_init(void);
+extern int net_profile_register(struct net_profile_slot *);
+extern int net_profile_unregister(struct net_profile_slot *);
+
+#else
+
+#define NET_PROFILE_ENTER(slot) do { /* nothing */ } while(0)
+#define NET_PROFILE_LEAVE(slot) do { /* nothing */ } while(0)
+#define NET_PROFILE_LEAVE_IRQ(slot) do { /* nothing */ } while(0)
+#define NET_PROFILE_SKB_CLEAR(skb) do { /* nothing */ } while(0)
+#define NET_PROFILE_SKB_INIT(skb) do { /* nothing */ } while(0)
+#define NET_PROFILE_SKB_PASSED(skb, slot) do { /* nothing */ } while(0)
+#define NET_PROFILE_DECL(slot)
+#define NET_PROFILE_DEFINE(slot)
+#define NET_PROFILE_REGISTER(slot) do { /* nothing */ } while(0)
+#define NET_PROFILE_UNREGISTER(slot) do { /* nothing */ } while(0)
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/net/protocol.h b/pfinet/linux-src/include/net/protocol.h
new file mode 100644
index 00000000..f6e947b1
--- /dev/null
+++ b/pfinet/linux-src/include/net/protocol.h
@@ -0,0 +1,82 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the protocol dispatcher.
+ *
+ * Version: @(#)protocol.h 1.0.2 05/07/93
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Changes:
+ * Alan Cox : Added a name field and a frag handler
+ * field for later.
+ * Alan Cox : Cleaned up, and sorted types.
+ * Pedro Roque : inet6 protocols
+ */
+
+#ifndef _PROTOCOL_H
+#define _PROTOCOL_H
+
+#include <linux/config.h>
+#include <linux/in6.h>
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#include <linux/ipv6.h>
+#endif
+
+#define MAX_INET_PROTOS 32 /* Must be a power of 2 */
+
+
+/* This is used to register protocols. */
+struct inet_protocol
+{
+ int (*handler)(struct sk_buff *skb, unsigned short len);
+ void (*err_handler)(struct sk_buff *skb, unsigned char *dp, int len);
+ struct inet_protocol *next;
+ unsigned char protocol;
+ unsigned char copy:1;
+ void *data;
+ const char *name;
+};
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+struct inet6_protocol
+{
+ int (*handler)(struct sk_buff *skb,
+ unsigned long len);
+
+ void (*err_handler)(struct sk_buff *skb, struct ipv6hdr *hdr,
+ struct inet6_skb_parm *opt,
+ int type, int code, unsigned char *buff,
+ __u32 info);
+ struct inet6_protocol *next;
+ unsigned char protocol;
+ unsigned char copy:1;
+ void *data;
+ const char *name;
+};
+#endif
+
+extern struct inet_protocol *inet_protocol_base;
+extern struct inet_protocol *inet_protos[MAX_INET_PROTOS];
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+extern struct inet6_protocol *inet6_protocol_base;
+extern struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
+#endif
+
+extern void inet_add_protocol(struct inet_protocol *prot);
+extern int inet_del_protocol(struct inet_protocol *prot);
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+extern void inet6_add_protocol(struct inet6_protocol *prot);
+extern int inet6_del_protocol(struct inet6_protocol *prot);
+#endif
+
+#endif /* _PROTOCOL_H */
diff --git a/pfinet/linux-src/include/net/psnap.h b/pfinet/linux-src/include/net/psnap.h
new file mode 100644
index 00000000..49a68f7e
--- /dev/null
+++ b/pfinet/linux-src/include/net/psnap.h
@@ -0,0 +1,7 @@
+#ifndef _NET_PSNAP_H
+#define _NET_PSNAP_H
+
+extern struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *));
+extern void unregister_snap_client(unsigned char *desc);
+
+#endif
diff --git a/pfinet/linux-src/include/net/psnapcall.h b/pfinet/linux-src/include/net/psnapcall.h
new file mode 100644
index 00000000..9da5763c
--- /dev/null
+++ b/pfinet/linux-src/include/net/psnapcall.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of Space.c simpler */
+extern void snap_proto_init(struct net_proto *);
diff --git a/pfinet/linux-src/include/net/rarp.h b/pfinet/linux-src/include/net/rarp.h
new file mode 100644
index 00000000..7bfb08ef
--- /dev/null
+++ b/pfinet/linux-src/include/net/rarp.h
@@ -0,0 +1,12 @@
+/* linux/net/inet/rarp.h */
+#ifndef _RARP_H
+#define _RARP_H
+
+extern int rarp_ioctl(unsigned int cmd, void *arg);
+extern int rarp_get_info(char *buffer,
+ char **start,
+ off_t offset,
+ int length,
+ int dummy);
+#endif /* _RARP_H */
+
diff --git a/pfinet/linux-src/include/net/raw.h b/pfinet/linux-src/include/net/raw.h
new file mode 100644
index 00000000..4d2e6e98
--- /dev/null
+++ b/pfinet/linux-src/include/net/raw.h
@@ -0,0 +1,38 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the RAW-IP module.
+ *
+ * Version: @(#)raw.h 1.0.2 05/07/93
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _RAW_H
+#define _RAW_H
+
+
+extern struct proto raw_prot;
+
+
+extern void raw_err(struct sock *, struct sk_buff *);
+extern int raw_rcv(struct sock *, struct sk_buff *);
+
+/* Note: v4 ICMP wants to get at this stuff, if you change the
+ * hashing mechanism, make sure you update icmp.c as well.
+ */
+#define RAWV4_HTABLE_SIZE MAX_INET_PROTOS
+extern struct sock *raw_v4_htable[RAWV4_HTABLE_SIZE];
+
+
+extern struct sock *raw_v4_lookup(struct sock *sk, unsigned short num,
+ unsigned long raddr, unsigned long laddr,
+ int dif);
+
+#endif /* _RAW_H */
diff --git a/pfinet/linux-src/include/net/rawv6.h b/pfinet/linux-src/include/net/rawv6.h
new file mode 100644
index 00000000..d54572d1
--- /dev/null
+++ b/pfinet/linux-src/include/net/rawv6.h
@@ -0,0 +1,27 @@
+#ifndef _NET_RAWV6_H
+#define _NET_RAWV6_H
+
+#ifdef __KERNEL__
+
+#define RAWV6_HTABLE_SIZE MAX_INET_PROTOS
+extern struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE];
+
+
+extern struct sock *raw_v6_lookup(struct sock *sk, unsigned short num,
+ struct in6_addr *loc_addr, struct in6_addr *rmt_addr);
+
+extern int rawv6_rcv(struct sock *sk,
+ struct sk_buff *skb,
+ unsigned long len);
+
+
+extern void rawv6_err(struct sock *sk,
+ struct sk_buff *skb,
+ struct ipv6hdr *hdr,
+ struct inet6_skb_parm *opt,
+ int type, int code,
+ unsigned char *buff, u32 info);
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/net/rose.h b/pfinet/linux-src/include/net/rose.h
new file mode 100644
index 00000000..1c8684d2
--- /dev/null
+++ b/pfinet/linux-src/include/net/rose.h
@@ -0,0 +1,241 @@
+/*
+ * Declarations of Rose type objects.
+ *
+ * Jonathan Naylor G4KLX 25/8/96
+ */
+
+#ifndef _ROSE_H
+#define _ROSE_H
+#include <linux/rose.h>
+
+#define ROSE_ADDR_LEN 5
+
+#define ROSE_MIN_LEN 3
+
+#define ROSE_GFI 0x10
+#define ROSE_Q_BIT 0x80
+#define ROSE_D_BIT 0x40
+#define ROSE_M_BIT 0x10
+
+#define ROSE_CALL_REQUEST 0x0B
+#define ROSE_CALL_ACCEPTED 0x0F
+#define ROSE_CLEAR_REQUEST 0x13
+#define ROSE_CLEAR_CONFIRMATION 0x17
+#define ROSE_DATA 0x00
+#define ROSE_INTERRUPT 0x23
+#define ROSE_INTERRUPT_CONFIRMATION 0x27
+#define ROSE_RR 0x01
+#define ROSE_RNR 0x05
+#define ROSE_REJ 0x09
+#define ROSE_RESET_REQUEST 0x1B
+#define ROSE_RESET_CONFIRMATION 0x1F
+#define ROSE_REGISTRATION_REQUEST 0xF3
+#define ROSE_REGISTRATION_CONFIRMATION 0xF7
+#define ROSE_RESTART_REQUEST 0xFB
+#define ROSE_RESTART_CONFIRMATION 0xFF
+#define ROSE_DIAGNOSTIC 0xF1
+#define ROSE_ILLEGAL 0xFD
+
+/* Define Link State constants. */
+
+enum {
+ ROSE_STATE_0, /* Ready */
+ ROSE_STATE_1, /* Awaiting Call Accepted */
+ ROSE_STATE_2, /* Awaiting Clear Confirmation */
+ ROSE_STATE_3, /* Data Transfer */
+ ROSE_STATE_4, /* Awaiting Reset Confirmation */
+ ROSE_STATE_5 /* Deferred Call Acceptance */
+};
+
+#define ROSE_DEFAULT_T0 (180 * HZ) /* Default T10 T20 value */
+#define ROSE_DEFAULT_T1 (200 * HZ) /* Default T11 T21 value */
+#define ROSE_DEFAULT_T2 (180 * HZ) /* Default T12 T22 value */
+#define ROSE_DEFAULT_T3 (180 * HZ) /* Default T13 T23 value */
+#define ROSE_DEFAULT_HB (5 * HZ) /* Default Holdback value */
+#define ROSE_DEFAULT_IDLE (0 * 60 * HZ) /* No Activity Timeout - none */
+#define ROSE_DEFAULT_ROUTING 1 /* Default routing flag */
+#define ROSE_DEFAULT_FAIL_TIMEOUT (120 * HZ) /* Time until link considered usable */
+#define ROSE_DEFAULT_MAXVC 50 /* Maximum number of VCs per neighbour */
+#define ROSE_DEFAULT_WINDOW_SIZE 7 /* Default window size */
+
+#define ROSE_MODULUS 8
+#define ROSE_MAX_PACKET_SIZE 251 /* Maximum packet size */
+
+#define ROSE_COND_ACK_PENDING 0x01
+#define ROSE_COND_PEER_RX_BUSY 0x02
+#define ROSE_COND_OWN_RX_BUSY 0x04
+
+#define FAC_NATIONAL 0x00
+#define FAC_CCITT 0x0F
+
+#define FAC_NATIONAL_RAND 0x7F
+#define FAC_NATIONAL_FLAGS 0x3F
+#define FAC_NATIONAL_DEST_DIGI 0xE9
+#define FAC_NATIONAL_SRC_DIGI 0xEB
+#define FAC_NATIONAL_FAIL_CALL 0xED
+#define FAC_NATIONAL_FAIL_ADD 0xEE
+#define FAC_NATIONAL_DIGIS 0xEF
+
+#define FAC_CCITT_DEST_NSAP 0xC9
+#define FAC_CCITT_SRC_NSAP 0xCB
+
+struct rose_neigh {
+ struct rose_neigh *next;
+ ax25_address callsign;
+ ax25_digi *digipeat;
+ ax25_cb *ax25;
+ struct device *dev;
+ unsigned short count;
+ unsigned short use;
+ unsigned int number;
+ char restarted;
+ char dce_mode;
+ char loopback;
+ struct sk_buff_head queue;
+ struct timer_list t0timer;
+ struct timer_list ftimer;
+};
+
+struct rose_node {
+ struct rose_node *next;
+ rose_address address;
+ unsigned short mask;
+ unsigned char count;
+ char loopback;
+ struct rose_neigh *neighbour[3];
+};
+
+struct rose_route {
+ struct rose_route *next;
+ unsigned int lci1, lci2;
+ rose_address src_addr, dest_addr;
+ ax25_address src_call, dest_call;
+ struct rose_neigh *neigh1, *neigh2;
+ unsigned int rand;
+};
+
+typedef struct {
+ rose_address source_addr, dest_addr;
+ ax25_address source_call, dest_call;
+ unsigned char source_ndigis, dest_ndigis;
+ ax25_address source_digis[ROSE_MAX_DIGIS];
+ ax25_address dest_digis[ROSE_MAX_DIGIS];
+ struct rose_neigh *neighbour;
+ struct device *device;
+ unsigned int lci, rand;
+ unsigned char state, condition, qbitincl, defer;
+ unsigned char cause, diagnostic;
+ unsigned short vs, vr, va, vl;
+ unsigned long t1, t2, t3, hb, idle;
+#ifdef M_BIT
+ unsigned short fraglen;
+ struct sk_buff_head frag_queue;
+#endif
+ struct sk_buff_head ack_queue;
+ struct rose_facilities_struct facilities;
+ struct timer_list timer;
+ struct timer_list idletimer;
+ struct sock *sk; /* Backlink to socket */
+} rose_cb;
+
+/* af_rose.c */
+extern ax25_address rose_callsign;
+extern int sysctl_rose_restart_request_timeout;
+extern int sysctl_rose_call_request_timeout;
+extern int sysctl_rose_reset_request_timeout;
+extern int sysctl_rose_clear_request_timeout;
+extern int sysctl_rose_no_activity_timeout;
+extern int sysctl_rose_ack_hold_back_timeout;
+extern int sysctl_rose_routing_control;
+extern int sysctl_rose_link_fail_timeout;
+extern int sysctl_rose_maximum_vcs;
+extern int sysctl_rose_window_size;
+extern int rosecmp(rose_address *, rose_address *);
+extern int rosecmpm(rose_address *, rose_address *, unsigned short);
+extern char *rose2asc(rose_address *);
+extern struct sock *rose_find_socket(unsigned int, struct rose_neigh *);
+extern void rose_kill_by_neigh(struct rose_neigh *);
+extern unsigned int rose_new_lci(struct rose_neigh *);
+extern int rose_rx_call_request(struct sk_buff *, struct device *, struct rose_neigh *, unsigned int);
+extern void rose_destroy_socket(struct sock *);
+
+/* rose_dev.c */
+extern int rose_rx_ip(struct sk_buff *, struct device *);
+extern int rose_init(struct device *);
+
+#include <net/rosecall.h>
+
+/* rose_in.c */
+extern int rose_process_rx_frame(struct sock *, struct sk_buff *);
+
+/* rose_link.c */
+extern void rose_start_ftimer(struct rose_neigh *);
+extern void rose_start_t0timer(struct rose_neigh *);
+extern void rose_stop_ftimer(struct rose_neigh *);
+extern void rose_stop_t0timer(struct rose_neigh *);
+extern int rose_ftimer_running(struct rose_neigh *);
+extern int rose_t0timer_running(struct rose_neigh *);
+extern void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *, unsigned short);
+extern void rose_transmit_restart_request(struct rose_neigh *);
+extern void rose_transmit_restart_confirmation(struct rose_neigh *);
+extern void rose_transmit_diagnostic(struct rose_neigh *, unsigned char);
+extern void rose_transmit_clear_request(struct rose_neigh *, unsigned int, unsigned char, unsigned char);
+extern void rose_transmit_link(struct sk_buff *, struct rose_neigh *);
+
+/* rose_loopback.c */
+extern void rose_loopback_init(void);
+extern void rose_loopback_clear(void);
+extern int rose_loopback_queue(struct sk_buff *, struct rose_neigh *);
+
+/* rose_out.c */
+extern void rose_kick(struct sock *);
+extern void rose_enquiry_response(struct sock *);
+
+/* rose_route.c */
+extern struct rose_neigh *rose_loopback_neigh;
+
+extern int rose_add_loopback_neigh(void);
+extern int rose_add_loopback_node(rose_address *);
+extern void rose_del_loopback_node(rose_address *);
+extern void rose_rt_device_down(struct device *);
+extern void rose_link_device_down(struct device *);
+extern struct device *rose_dev_first(void);
+extern struct device *rose_dev_get(rose_address *);
+extern struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *);
+extern struct device *rose_ax25_dev_get(char *);
+extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsigned char *);
+extern int rose_rt_ioctl(unsigned int, void *);
+extern void rose_link_failed(ax25_cb *, int);
+extern int rose_route_frame(struct sk_buff *, ax25_cb *);
+extern int rose_nodes_get_info(char *, char **, off_t, int, int);
+extern int rose_neigh_get_info(char *, char **, off_t, int, int);
+extern int rose_routes_get_info(char *, char **, off_t, int, int);
+extern void rose_rt_free(void);
+
+/* rose_subr.c */
+extern void rose_clear_queues(struct sock *);
+extern void rose_frames_acked(struct sock *, unsigned short);
+extern void rose_requeue_frames(struct sock *);
+extern int rose_validate_nr(struct sock *, unsigned short);
+extern void rose_write_internal(struct sock *, int);
+extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *);
+extern int rose_parse_facilities(unsigned char *, struct rose_facilities_struct *);
+extern int rose_create_facilities(unsigned char *, rose_cb *);
+extern void rose_disconnect(struct sock *, int, int, int);
+
+/* rose_timer.c */
+extern void rose_start_heartbeat(struct sock *);
+extern void rose_start_t1timer(struct sock *);
+extern void rose_start_t2timer(struct sock *);
+extern void rose_start_t3timer(struct sock *);
+extern void rose_start_hbtimer(struct sock *);
+extern void rose_start_idletimer(struct sock *);
+extern void rose_stop_heartbeat(struct sock *);
+extern void rose_stop_timer(struct sock *);
+extern void rose_stop_idletimer(struct sock *);
+
+/* sysctl_net_rose.c */
+extern void rose_register_sysctl(void);
+extern void rose_unregister_sysctl(void);
+
+#endif
diff --git a/pfinet/linux-src/include/net/rosecall.h b/pfinet/linux-src/include/net/rosecall.h
new file mode 100644
index 00000000..5bbe69cc
--- /dev/null
+++ b/pfinet/linux-src/include/net/rosecall.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void rose_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/include/net/route.h b/pfinet/linux-src/include/net/route.h
new file mode 100644
index 00000000..66df4712
--- /dev/null
+++ b/pfinet/linux-src/include/net/route.h
@@ -0,0 +1,153 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the IP router.
+ *
+ * Version: @(#)route.h 1.0.4 05/27/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Fixes:
+ * Alan Cox : Reformatted. Added ip_rt_local()
+ * Alan Cox : Support for TCP parameters.
+ * Alexey Kuznetsov: Major changes for new routing code.
+ * Mike McLagan : Routing by source
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ROUTE_H
+#define _ROUTE_H
+
+#include <linux/config.h>
+#include <net/dst.h>
+#include <linux/in_route.h>
+#include <linux/rtnetlink.h>
+#include <linux/route.h>
+
+#ifndef __KERNEL__
+#warning This file is not supposed to be used outside of kernel.
+#endif
+
+#define RT_HASH_DIVISOR 256
+
+/*
+ * Prevents LRU trashing, entries considered equivalent,
+ * if the difference between last use times is less then this number.
+ */
+#define RT_CACHE_BUBBLE_THRESHOLD (5*HZ)
+
+
+#define RTO_ONLINK 0x01
+#define RTO_TPROXY 0x80000000
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+#define RTO_CONN RTO_TPROXY
+#else
+#define RTO_CONN 0
+#endif
+
+struct rt_key
+{
+ __u32 dst;
+ __u32 src;
+ int iif;
+ int oif;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ __u32 fwmark;
+#endif
+ __u8 tos;
+ __u8 scope;
+};
+
+struct rtable
+{
+ union
+ {
+ struct dst_entry dst;
+ struct rtable *rt_next;
+ } u;
+
+ unsigned rt_flags;
+ unsigned rt_type;
+
+ __u32 rt_dst; /* Path destination */
+ __u32 rt_src; /* Path source */
+ int rt_iif;
+
+ /* Info on neighbour */
+ __u32 rt_gateway;
+
+ /* Cache lookup keys */
+ struct rt_key key;
+
+ /* Miscellaneous cached information */
+ __u32 rt_spec_dst; /* RFC1122 specific destination */
+
+#ifdef CONFIG_IP_ROUTE_NAT
+ __u32 rt_src_map;
+ __u32 rt_dst_map;
+#endif
+};
+
+extern struct rtable *rt_hash_table[RT_HASH_DIVISOR];
+
+struct ip_rt_acct
+{
+ __u32 o_bytes;
+ __u32 o_packets;
+ __u32 i_bytes;
+ __u32 i_packets;
+};
+
+extern struct ip_rt_acct ip_rt_acct[256];
+
+extern void ip_rt_init(void);
+extern void ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw,
+ u32 src, u8 tos, struct device *dev);
+extern void ip_rt_advice(struct rtable **rp, int advice);
+extern void rt_cache_flush(int how);
+extern int ip_route_output(struct rtable **, u32 dst, u32 src, u32 tos, int oif);
+extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct device *devin);
+extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
+extern void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu);
+extern void ip_rt_send_redirect(struct sk_buff *skb);
+
+extern unsigned inet_addr_type(u32 addr);
+extern void ip_rt_multicast_event(struct in_device *);
+extern int ip_rt_ioctl(unsigned int cmd, void *arg);
+extern void ip_rt_get_source(u8 *src, struct rtable *rt);
+extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
+
+extern __inline__ void ip_rt_put(struct rtable * rt)
+{
+ if (rt)
+ dst_release(&rt->u.dst);
+}
+
+extern __u8 ip_tos2prio[16];
+
+extern __inline__ char rt_tos2priority(u8 tos)
+{
+ return ip_tos2prio[IPTOS_TOS(tos)>>1];
+}
+
+extern __inline__ int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif)
+{
+ int err;
+ err = ip_route_output(rp, dst, src, tos, oif);
+ if (err || (dst && src))
+ return err;
+ dst = (*rp)->rt_dst;
+ src = (*rp)->rt_src;
+ ip_rt_put(*rp);
+ *rp = NULL;
+ return ip_route_output(rp, dst, src, tos, oif);
+}
+
+#endif /* _ROUTE_H */
diff --git a/pfinet/linux-src/include/net/scm.h b/pfinet/linux-src/include/net/scm.h
new file mode 100644
index 00000000..98c2dc91
--- /dev/null
+++ b/pfinet/linux-src/include/net/scm.h
@@ -0,0 +1,67 @@
+#ifndef __LINUX_NET_SCM_H
+#define __LINUX_NET_SCM_H
+
+/* Well, we should have at least one descriptor open
+ * to accept passed FDs 8)
+ */
+#define SCM_MAX_FD (OPEN_MAX-1)
+
+struct scm_fp_list
+{
+ int count;
+ struct file *fp[SCM_MAX_FD];
+};
+
+struct scm_cookie
+{
+ struct ucred creds; /* Skb credentials */
+ struct scm_fp_list *fp; /* Passed files */
+ unsigned long seq; /* Connection seqno */
+};
+
+extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
+extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
+extern void __scm_destroy(struct scm_cookie *scm);
+extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
+
+static __inline__ void scm_destroy(struct scm_cookie *scm)
+{
+ if (scm && scm->fp)
+ __scm_destroy(scm);
+}
+
+static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
+ struct scm_cookie *scm)
+{
+ memset(scm, 0, sizeof(*scm));
+ scm->creds.uid = current->uid;
+ scm->creds.gid = current->gid;
+ scm->creds.pid = current->pid;
+ if (msg->msg_controllen <= 0)
+ return 0;
+ return __scm_send(sock, msg, scm);
+}
+
+static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
+ struct scm_cookie *scm, int flags)
+{
+ if (!msg->msg_control)
+ {
+ if (sock->passcred || scm->fp)
+ msg->msg_flags |= MSG_CTRUNC;
+ scm_destroy(scm);
+ return;
+ }
+
+ if (sock->passcred)
+ put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
+
+ if (!scm->fp)
+ return;
+
+ scm_detach_fds(msg, scm);
+}
+
+
+#endif __LINUX_NET_SCM_H
+
diff --git a/pfinet/linux-src/include/net/slhc.h b/pfinet/linux-src/include/net/slhc.h
new file mode 100644
index 00000000..c7b39db5
--- /dev/null
+++ b/pfinet/linux-src/include/net/slhc.h
@@ -0,0 +1,6 @@
+#ifndef __NET_SLHC_H
+#define __NET_SLHC_H
+
+extern void slhc_install(void);
+
+#endif
diff --git a/pfinet/linux-src/include/net/slhc_vj.h b/pfinet/linux-src/include/net/slhc_vj.h
new file mode 100644
index 00000000..04387d8a
--- /dev/null
+++ b/pfinet/linux-src/include/net/slhc_vj.h
@@ -0,0 +1,187 @@
+#ifndef _SLHC_H
+#define _SLHC_H
+/*
+ * Definitions for tcp compression routines.
+ *
+ * $Header: slcompress.h,v 1.10 89/12/31 08:53:02 van Exp $
+ *
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ * - Initial distribution.
+ *
+ *
+ * modified for KA9Q Internet Software Package by
+ * Katie Stevens (dkstevens@ucdavis.edu)
+ * University of California, Davis
+ * Computing Services
+ * - 01-31-90 initial adaptation
+ *
+ * - Feb 1991 Bill_Simpson@um.cc.umich.edu
+ * variable number of conversation slots
+ * allow zero or one slots
+ * separate routines
+ * status display
+ */
+
+/*
+ * Compressed packet format:
+ *
+ * The first octet contains the packet type (top 3 bits), TCP
+ * 'push' bit, and flags that indicate which of the 4 TCP sequence
+ * numbers have changed (bottom 5 bits). The next octet is a
+ * conversation number that associates a saved IP/TCP header with
+ * the compressed packet. The next two octets are the TCP checksum
+ * from the original datagram. The next 0 to 15 octets are
+ * sequence number changes, one change per bit set in the header
+ * (there may be no changes and there are two special cases where
+ * the receiver implicitly knows what changed -- see below).
+ *
+ * There are 5 numbers which can change (they are always inserted
+ * in the following order): TCP urgent pointer, window,
+ * acknowledgment, sequence number and IP ID. (The urgent pointer
+ * is different from the others in that its value is sent, not the
+ * change in value.) Since typical use of SLIP links is biased
+ * toward small packets (see comments on MTU/MSS below), changes
+ * use a variable length coding with one octet for numbers in the
+ * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
+ * range 256 - 65535 or 0. (If the change in sequence number or
+ * ack is more than 65535, an uncompressed packet is sent.)
+ */
+
+/*
+ * Packet types (must not conflict with IP protocol version)
+ *
+ * The top nibble of the first octet is the packet type. There are
+ * three possible types: IP (not proto TCP or tcp with one of the
+ * control flags set); uncompressed TCP (a normal IP/TCP packet but
+ * with the 8-bit protocol field replaced by an 8-bit connection id --
+ * this type of packet syncs the sender & receiver); and compressed
+ * TCP (described above).
+ *
+ * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
+ * is logically part of the 4-bit "changes" field that follows. Top
+ * three bits are actual packet type. For backward compatibility
+ * and in the interest of conserving bits, numbers are chosen so the
+ * IP protocol version number (4) which normally appears in this nibble
+ * means "IP packet".
+ */
+
+/* SLIP compression masks for len/vers byte */
+#define SL_TYPE_IP 0x40
+#define SL_TYPE_UNCOMPRESSED_TCP 0x70
+#define SL_TYPE_COMPRESSED_TCP 0x80
+#define SL_TYPE_ERROR 0x00
+
+/* Bits in first octet of compressed packet */
+#define NEW_C 0x40 /* flag bits for what changed in a packet */
+#define NEW_I 0x20
+#define NEW_S 0x08
+#define NEW_A 0x04
+#define NEW_W 0x02
+#define NEW_U 0x01
+
+/* reserved, special-case values of above */
+#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
+#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
+#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
+
+#define TCP_PUSH_BIT 0x10
+
+/*
+ * data type and sizes conversion assumptions:
+ *
+ * VJ code KA9Q style generic
+ * u_char byte_t unsigned char 8 bits
+ * u_short int16 unsigned short 16 bits
+ * u_int int16 unsigned short 16 bits
+ * u_long unsigned long unsigned long 32 bits
+ * int int32 long 32 bits
+ */
+
+typedef __u8 byte_t;
+typedef __u32 int32;
+
+/*
+ * "state" data for each active tcp conversation on the wire. This is
+ * basically a copy of the entire IP/TCP header from the last packet
+ * we saw from the conversation together with a small identifier
+ * the transmit & receive ends of the line use to locate saved header.
+ */
+struct cstate {
+ byte_t cs_this; /* connection id number (xmit) */
+ struct cstate *next; /* next in ring (xmit) */
+ struct iphdr cs_ip; /* ip/tcp hdr from most recent packet */
+ struct tcphdr cs_tcp;
+ unsigned char cs_ipopt[64];
+ unsigned char cs_tcpopt[64];
+ int cs_hsize;
+};
+#define NULLSLSTATE (struct cstate *)0
+
+/*
+ * all the state data for one serial line (we need one of these per line).
+ */
+struct slcompress {
+ struct cstate *tstate; /* transmit connection states (array)*/
+ struct cstate *rstate; /* receive connection states (array)*/
+
+ byte_t tslot_limit; /* highest transmit slot id (0-l)*/
+ byte_t rslot_limit; /* highest receive slot id (0-l)*/
+
+ byte_t xmit_oldest; /* oldest xmit in ring */
+ byte_t xmit_current; /* most recent xmit id */
+ byte_t recv_current; /* most recent rcvd id */
+
+ byte_t flags;
+#define SLF_TOSS 0x01 /* tossing rcvd frames until id received */
+
+ int32 sls_o_nontcp; /* outbound non-TCP packets */
+ int32 sls_o_tcp; /* outbound TCP packets */
+ int32 sls_o_uncompressed; /* outbound uncompressed packets */
+ int32 sls_o_compressed; /* outbound compressed packets */
+ int32 sls_o_searches; /* searches for connection state */
+ int32 sls_o_misses; /* times couldn't find conn. state */
+
+ int32 sls_i_uncompressed; /* inbound uncompressed packets */
+ int32 sls_i_compressed; /* inbound compressed packets */
+ int32 sls_i_error; /* inbound error packets */
+ int32 sls_i_tossed; /* inbound packets tossed because of error */
+
+ int32 sls_i_runt;
+ int32 sls_i_badcheck;
+};
+#define NULLSLCOMPR (struct slcompress *)0
+
+#define __ARGS(x) x
+
+/* In slhc.c: */
+struct slcompress *slhc_init __ARGS((int rslots, int tslots));
+void slhc_free __ARGS((struct slcompress *comp));
+
+int slhc_compress __ARGS((struct slcompress *comp, unsigned char *icp,
+ int isize, unsigned char *ocp, unsigned char **cpp,
+ int compress_cid));
+int slhc_uncompress __ARGS((struct slcompress *comp, unsigned char *icp,
+ int isize));
+int slhc_remember __ARGS((struct slcompress *comp, unsigned char *icp,
+ int isize));
+int slhc_toss __ARGS((struct slcompress *comp));
+
+void slhc_i_status __ARGS((struct slcompress *comp));
+void slhc_o_status __ARGS((struct slcompress *comp));
+
+#endif /* _SLHC_H */
diff --git a/pfinet/linux-src/include/net/snmp.h b/pfinet/linux-src/include/net/snmp.h
new file mode 100644
index 00000000..cc8354b6
--- /dev/null
+++ b/pfinet/linux-src/include/net/snmp.h
@@ -0,0 +1,183 @@
+/*
+ *
+ * SNMP MIB entries for the IP subsystem.
+ *
+ * Alan Cox <gw4pts@gw4pts.ampr.org>
+ *
+ * We don't chose to implement SNMP in the kernel (this would
+ * be silly as SNMP is a pain in the backside in places). We do
+ * however need to collect the MIB statistics and export them
+ * out of /proc (eventually)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef _SNMP_H
+#define _SNMP_H
+
+/*
+ * We use all unsigned longs. Linux will soon be so reliable that even these
+ * will rapidly get too small 8-). Seriously consider the IpInReceives count
+ * on the 20Gb/s + networks people expect in a few years time!
+ */
+
+struct ip_mib
+{
+ unsigned long IpForwarding;
+ unsigned long IpDefaultTTL;
+ unsigned long IpInReceives;
+ unsigned long IpInHdrErrors;
+ unsigned long IpInAddrErrors;
+ unsigned long IpForwDatagrams;
+ unsigned long IpInUnknownProtos;
+ unsigned long IpInDiscards;
+ unsigned long IpInDelivers;
+ unsigned long IpOutRequests;
+ unsigned long IpOutDiscards;
+ unsigned long IpOutNoRoutes;
+ unsigned long IpReasmTimeout;
+ unsigned long IpReasmReqds;
+ unsigned long IpReasmOKs;
+ unsigned long IpReasmFails;
+ unsigned long IpFragOKs;
+ unsigned long IpFragFails;
+ unsigned long IpFragCreates;
+};
+
+struct ipv6_mib
+{
+ unsigned long Ip6InReceives;
+ unsigned long Ip6InHdrErrors;
+ unsigned long Ip6InTooBigErrors;
+ unsigned long Ip6InNoRoutes;
+ unsigned long Ip6InAddrErrors;
+ unsigned long Ip6InUnknownProtos;
+ unsigned long Ip6InTruncatedPkts;
+ unsigned long Ip6InDiscards;
+ unsigned long Ip6InDelivers;
+ unsigned long Ip6OutForwDatagrams;
+ unsigned long Ip6OutRequests;
+ unsigned long Ip6OutDiscards;
+ unsigned long Ip6OutNoRoutes;
+ unsigned long Ip6ReasmTimeout;
+ unsigned long Ip6ReasmReqds;
+ unsigned long Ip6ReasmOKs;
+ unsigned long Ip6ReasmFails;
+ unsigned long Ip6FragOKs;
+ unsigned long Ip6FragFails;
+ unsigned long Ip6FragCreates;
+ unsigned long Ip6InMcastPkts;
+ unsigned long Ip6OutMcastPkts;
+};
+
+struct icmp_mib
+{
+ unsigned long IcmpInMsgs;
+ unsigned long IcmpInErrors;
+ unsigned long IcmpInDestUnreachs;
+ unsigned long IcmpInTimeExcds;
+ unsigned long IcmpInParmProbs;
+ unsigned long IcmpInSrcQuenchs;
+ unsigned long IcmpInRedirects;
+ unsigned long IcmpInEchos;
+ unsigned long IcmpInEchoReps;
+ unsigned long IcmpInTimestamps;
+ unsigned long IcmpInTimestampReps;
+ unsigned long IcmpInAddrMasks;
+ unsigned long IcmpInAddrMaskReps;
+ unsigned long IcmpOutMsgs;
+ unsigned long IcmpOutErrors;
+ unsigned long IcmpOutDestUnreachs;
+ unsigned long IcmpOutTimeExcds;
+ unsigned long IcmpOutParmProbs;
+ unsigned long IcmpOutSrcQuenchs;
+ unsigned long IcmpOutRedirects;
+ unsigned long IcmpOutEchos;
+ unsigned long IcmpOutEchoReps;
+ unsigned long IcmpOutTimestamps;
+ unsigned long IcmpOutTimestampReps;
+ unsigned long IcmpOutAddrMasks;
+ unsigned long IcmpOutAddrMaskReps;
+};
+
+struct icmpv6_mib
+{
+ unsigned long Icmp6InMsgs;
+ unsigned long Icmp6InErrors;
+
+ unsigned long Icmp6InDestUnreachs;
+ unsigned long Icmp6InPktTooBigs;
+ unsigned long Icmp6InTimeExcds;
+ unsigned long Icmp6InParmProblems;
+
+ unsigned long Icmp6InEchos;
+ unsigned long Icmp6InEchoReplies;
+ unsigned long Icmp6InGroupMembQueries;
+ unsigned long Icmp6InGroupMembResponses;
+ unsigned long Icmp6InGroupMembReductions;
+ unsigned long Icmp6InRouterSolicits;
+ unsigned long Icmp6InRouterAdvertisements;
+ unsigned long Icmp6InNeighborSolicits;
+ unsigned long Icmp6InNeighborAdvertisements;
+ unsigned long Icmp6InRedirects;
+
+ unsigned long Icmp6OutMsgs;
+
+ unsigned long Icmp6OutDestUnreachs;
+ unsigned long Icmp6OutPktTooBigs;
+ unsigned long Icmp6OutTimeExcds;
+ unsigned long Icmp6OutParmProblems;
+
+ unsigned long Icmp6OutEchoReplies;
+ unsigned long Icmp6OutRouterSolicits;
+ unsigned long Icmp6OutNeighborSolicits;
+ unsigned long Icmp6OutNeighborAdvertisements;
+ unsigned long Icmp6OutRedirects;
+ unsigned long Icmp6OutGroupMembResponses;
+ unsigned long Icmp6OutGroupMembReductions;
+};
+
+struct tcp_mib
+{
+ unsigned long TcpRtoAlgorithm;
+ unsigned long TcpRtoMin;
+ unsigned long TcpRtoMax;
+ unsigned long TcpMaxConn;
+ unsigned long TcpActiveOpens;
+ unsigned long TcpPassiveOpens;
+ unsigned long TcpAttemptFails;
+ unsigned long TcpEstabResets;
+ unsigned long TcpCurrEstab;
+ unsigned long TcpInSegs;
+ unsigned long TcpOutSegs;
+ unsigned long TcpRetransSegs;
+ unsigned long TcpInErrs;
+ unsigned long TcpOutRsts;
+};
+
+struct udp_mib
+{
+ unsigned long UdpInDatagrams;
+ unsigned long UdpNoPorts;
+ unsigned long UdpInErrors;
+ unsigned long UdpOutDatagrams;
+};
+
+struct linux_mib
+{
+ unsigned long SyncookiesSent;
+ unsigned long SyncookiesRecv;
+ unsigned long SyncookiesFailed;
+ unsigned long EmbryonicRsts;
+ unsigned long PruneCalled;
+ unsigned long RcvPruned;
+ unsigned long OfoPruned;
+ unsigned long OutOfWindowIcmps;
+ unsigned long LockDroppedIcmps;
+};
+
+#endif
diff --git a/pfinet/linux-src/include/net/sock.h b/pfinet/linux-src/include/net/sock.h
new file mode 100644
index 00000000..28cf919e
--- /dev/null
+++ b/pfinet/linux-src/include/net/sock.h
@@ -0,0 +1,950 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the AF_INET socket handler.
+ *
+ * Version: @(#)sock.h 1.0.4 05/13/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche <flla@stud.uni-sb.de>
+ *
+ * Fixes:
+ * Alan Cox : Volatiles in skbuff pointers. See
+ * skbuff comments. May be overdone,
+ * better to prove they can be removed
+ * than the reverse.
+ * Alan Cox : Added a zapped field for tcp to note
+ * a socket is reset and must stay shut up
+ * Alan Cox : New fields for options
+ * Pauline Middelink : identd support
+ * Alan Cox : Eliminate low level recv/recvfrom
+ * David S. Miller : New socket lookup architecture.
+ * Steve Whitehouse: Default routines for sock_ops
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _SOCK_H
+#define _SOCK_H
+
+#include <linux/config.h>
+#include <linux/timer.h>
+#include <linux/in.h> /* struct sockaddr_in */
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#include <linux/in6.h> /* struct sockaddr_in6 */
+#include <linux/ipv6.h> /* dest_cache, inet6_options */
+#include <linux/icmpv6.h>
+#include <net/if_inet6.h> /* struct ipv6_mc_socklist */
+#endif
+
+#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE)
+#include <linux/icmp.h>
+#endif
+#include <linux/tcp.h> /* struct tcphdr */
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h> /* struct sk_buff */
+#include <net/protocol.h> /* struct inet_protocol */
+#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
+#include <net/x25.h>
+#endif
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+#include <net/ax25.h>
+#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+#include <net/netrom.h>
+#endif
+#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
+#include <net/rose.h>
+#endif
+#endif
+
+#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
+#if defined(CONFIG_SPX) || defined(CONFIG_SPX_MODULE)
+#include <net/spx.h>
+#else
+#include <net/ipx.h>
+#endif /* CONFIG_SPX */
+#endif /* CONFIG_IPX */
+
+#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
+#include <linux/atalk.h>
+#endif
+
+#if defined(CONFIG_DECNET) || defined(CONFIG_DECNET_MODULE)
+#include <net/dn.h>
+#endif
+
+#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
+#include <net/irda/irda.h>
+#endif
+
+#ifdef CONFIG_FILTER
+#include <linux/filter.h>
+#endif
+
+#include <asm/atomic.h>
+
+#define MIN_WRITE_SPACE 2048
+
+/* The AF_UNIX specific socket options */
+struct unix_opt {
+ int family;
+ char * name;
+ int locks;
+ struct unix_address *addr;
+ struct dentry * dentry;
+ struct semaphore readsem;
+ struct sock * other;
+ struct sock ** list;
+ struct sock * gc_tree;
+ int inflight;
+};
+
+#ifdef CONFIG_NETLINK
+struct netlink_callback;
+
+struct netlink_opt {
+ pid_t pid;
+ unsigned groups;
+ pid_t dst_pid;
+ unsigned dst_groups;
+ int (*handler)(int unit, struct sk_buff *skb);
+ atomic_t locks;
+ struct netlink_callback *cb;
+};
+#endif
+
+/* Once the IPX ncpd patches are in these are going into protinfo. */
+#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
+struct ipx_opt {
+ ipx_address dest_addr;
+ ipx_interface *intrfc;
+ unsigned short port;
+#ifdef CONFIG_IPX_INTERN
+ unsigned char node[IPX_NODE_LEN];
+#endif
+ unsigned short type;
+/*
+ * To handle special ncp connection-handling sockets for mars_nwe,
+ * the connection number must be stored in the socket.
+ */
+ unsigned short ipx_ncp_conn;
+};
+#endif
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+struct ipv6_pinfo {
+ struct in6_addr saddr;
+ struct in6_addr rcv_saddr;
+ struct in6_addr daddr;
+ struct in6_addr *daddr_cache;
+
+ __u32 flow_label;
+ __u32 frag_size;
+ int hop_limit;
+ int mcast_hops;
+ int mcast_oif;
+
+ /* pktoption flags */
+ union {
+ struct {
+ __u8 srcrt:2,
+ rxinfo:1,
+ rxhlim:1,
+ hopopts:1,
+ dstopts:1,
+ authhdr:1,
+ rxflow:1;
+ } bits;
+ __u8 all;
+ } rxopt;
+
+ /* sockopt flags */
+ __u8 mc_loop:1,
+ recverr:1,
+ sndflow:1,
+ pmtudisc:2;
+
+ struct ipv6_mc_socklist *ipv6_mc_list;
+ struct ipv6_fl_socklist *ipv6_fl_list;
+ __u32 dst_cookie;
+
+ struct ipv6_txoptions *opt;
+ struct sk_buff *pktoptions;
+};
+
+struct raw6_opt {
+ __u32 checksum; /* perform checksum */
+ __u32 offset; /* checksum offset */
+
+ struct icmp6_filter filter;
+};
+
+#endif /* IPV6 */
+
+#if defined(CONFIG_INET) || defined(CONFIG_INET_MODULE)
+struct raw_opt {
+ struct icmp_filter filter;
+};
+#endif
+
+/* This defines a selective acknowledgement block. */
+struct tcp_sack_block {
+ __u32 start_seq;
+ __u32 end_seq;
+};
+
+struct tcp_opt {
+ int tcp_header_len; /* Bytes of tcp header to send */
+
+/*
+ * Header prediction flags
+ * 0x5?10 << 16 + snd_wnd in net byte order
+ */
+ __u32 pred_flags;
+
+/*
+ * RFC793 variables by their proper names. This means you can
+ * read the code and the spec side by side (and laugh ...)
+ * See RFC793 and RFC1122. The RFC writes these in capitals.
+ */
+ __u32 rcv_nxt; /* What we want to receive next */
+ __u32 snd_nxt; /* Next sequence we send */
+
+ __u32 snd_una; /* First byte we want an ack for */
+ __u32 rcv_tstamp; /* timestamp of last received packet */
+ __u32 lrcvtime; /* timestamp of last received data packet*/
+ __u32 srtt; /* smothed round trip time << 3 */
+
+ __u32 ato; /* delayed ack timeout */
+ __u32 snd_wl1; /* Sequence for window update */
+
+ __u32 snd_wl2; /* Ack sequence for update */
+ __u32 snd_wnd; /* The window we expect to receive */
+ __u32 max_window;
+ __u32 pmtu_cookie; /* Last pmtu seen by socket */
+ __u16 mss_cache; /* Cached effective mss, not including SACKS */
+ __u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
+ __u16 ext_header_len; /* Dave, do you allow mw to use this hole? 8) --ANK */
+ __u8 pending; /* pending events */
+ __u8 retransmits;
+ __u32 last_ack_sent; /* last ack we sent */
+
+ __u32 backoff; /* backoff */
+ __u32 mdev; /* medium deviation */
+ __u32 snd_cwnd; /* Sending congestion window */
+ __u32 rto; /* retransmit timeout */
+
+ __u32 packets_out; /* Packets which are "in flight" */
+ __u32 fackets_out; /* Non-retrans SACK'd packets */
+ __u32 retrans_out; /* Fast-retransmitted packets out */
+ __u32 high_seq; /* snd_nxt at onset of congestion */
+/*
+ * Slow start and congestion control (see also Nagle, and Karn & Partridge)
+ */
+ __u32 snd_ssthresh; /* Slow start size threshold */
+ __u16 snd_cwnd_cnt; /* Linear increase counter */
+ __u8 dup_acks; /* Consequetive duplicate acks seen from other end */
+ __u8 delayed_acks;
+ __u16 user_mss; /* mss requested by user in ioctl */
+
+ /* Two commonly used timers in both sender and receiver paths. */
+ struct timer_list retransmit_timer; /* Resend (no ack) */
+ struct timer_list delack_timer; /* Ack delay */
+
+ struct sk_buff_head out_of_order_queue; /* Out of order segments go here */
+
+ struct tcp_func *af_specific; /* Operations which are AF_INET{4,6} specific */
+ struct sk_buff *send_head; /* Front of stuff to transmit */
+ struct sk_buff *retrans_head; /* retrans head can be
+ * different to the head of
+ * write queue if we are doing
+ * fast retransmit
+ */
+
+ __u32 rcv_wnd; /* Current receiver window */
+ __u32 rcv_wup; /* rcv_nxt on last window update sent */
+ __u32 write_seq;
+ __u32 copied_seq;
+/*
+ * Options received (usually on last packet, some only on SYN packets).
+ */
+ char tstamp_ok, /* TIMESTAMP seen on SYN packet */
+ wscale_ok, /* Wscale seen on SYN packet */
+ sack_ok; /* SACK seen on SYN packet */
+ char saw_tstamp; /* Saw TIMESTAMP on last packet */
+ __u8 snd_wscale; /* Window scaling received from sender */
+ __u8 rcv_wscale; /* Window scaling to send to receiver */
+ __u8 rexmt_done; /* Retransmitted up to send head? */
+ __u32 rcv_tsval; /* Time stamp value */
+ __u32 rcv_tsecr; /* Time stamp echo reply */
+ __u32 ts_recent; /* Time stamp to echo next */
+ __u32 ts_recent_stamp;/* Time we stored ts_recent (for aging) */
+ int num_sacks; /* Number of SACK blocks */
+ struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
+
+ struct timer_list probe_timer; /* Probes */
+ __u32 window_clamp; /* XXX Document this... -DaveM */
+ __u32 probes_out; /* unanswered 0 window probes */
+ __u32 syn_seq;
+ __u32 fin_seq;
+ __u32 urg_seq;
+ __u32 urg_data;
+
+ __u32 last_seg_size; /* Size of last incoming segment */
+ __u32 rcv_mss; /* MSS used for delayed ACK decisions */
+ __u32 partial_writers; /* # of clients wanting at the head packet */
+
+ struct open_request *syn_wait_queue;
+ struct open_request **syn_wait_last;
+
+ int syn_backlog; /* Backlog of received SYNs */
+};
+
+
+/*
+ * This structure really needs to be cleaned up.
+ * Most of it is for TCP, and not used by any of
+ * the other protocols.
+ */
+
+/*
+ * The idea is to start moving to a newer struct gradualy
+ *
+ * IMHO the newer struct should have the following format:
+ *
+ * struct sock {
+ * sockmem [mem, proto, callbacks]
+ *
+ * union or struct {
+ * ax25;
+ * } ll_pinfo;
+ *
+ * union {
+ * ipv4;
+ * ipv6;
+ * ipx;
+ * netrom;
+ * rose;
+ * x25;
+ * } net_pinfo;
+ *
+ * union {
+ * tcp;
+ * udp;
+ * spx;
+ * netrom;
+ * } tp_pinfo;
+ *
+ * }
+ */
+
+/* Define this to get the sk->debug debugging facility. */
+#define SOCK_DEBUGGING
+#ifdef SOCK_DEBUGGING
+#define SOCK_DEBUG(sk, msg...) do { if((sk) && ((sk)->debug)) printk(KERN_DEBUG ## msg); } while (0)
+#else
+#define SOCK_DEBUG(sk, msg...) do { } while (0)
+#endif
+
+struct sock {
+ /* This must be first. */
+ struct sock *sklist_next;
+ struct sock *sklist_prev;
+
+ /* Local port binding hash linkage. */
+ struct sock *bind_next;
+ struct sock **bind_pprev;
+
+ /* Socket demultiplex comparisons on incoming packets. */
+ __u32 daddr; /* Foreign IPv4 addr */
+ __u32 rcv_saddr; /* Bound local IPv4 addr */
+ __u16 dport; /* Destination port */
+ unsigned short num; /* Local port */
+ int bound_dev_if; /* Bound device index if != 0 */
+
+ /* Main hash linkage for various protocol lookup tables. */
+ struct sock *next;
+ struct sock **pprev;
+
+ volatile unsigned char state, /* Connection state */
+ zapped; /* In ax25 & ipx means not linked */
+ __u16 sport; /* Source port */
+
+ unsigned short family; /* Address family */
+ unsigned char reuse, /* SO_REUSEADDR setting */
+ nonagle; /* Disable Nagle algorithm? */
+
+ atomic_t sock_readers; /* User count */
+ int rcvbuf; /* Size of receive buffer in bytes */
+
+ struct wait_queue **sleep; /* Sock wait queue */
+ struct dst_entry *dst_cache; /* Destination cache */
+ atomic_t rmem_alloc; /* Receive queue bytes committed */
+ struct sk_buff_head receive_queue; /* Incoming packets */
+ atomic_t wmem_alloc; /* Transmit queue bytes committed */
+ struct sk_buff_head write_queue; /* Packet sending queue */
+ atomic_t omem_alloc; /* "o" is "option" or "other" */
+ __u32 saddr; /* Sending source */
+ unsigned int allocation; /* Allocation mode */
+ int sndbuf; /* Size of send buffer in bytes */
+ struct sock *prev;
+
+ /* Not all are volatile, but some are, so we might as well say they all are.
+ * XXX Make this a flag word -DaveM
+ */
+ volatile char dead,
+ done,
+ urginline,
+ keepopen,
+ linger,
+ destroy,
+ no_check,
+ broadcast,
+ bsdism;
+ unsigned char debug;
+ int proc;
+ unsigned long lingertime;
+
+ int hashent;
+ struct sock *pair;
+
+ /* Error and backlog packet queues, rarely used. */
+ struct sk_buff_head back_log,
+ error_queue;
+
+ struct proto *prot;
+
+ unsigned short shutdown;
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ union {
+ struct ipv6_pinfo af_inet6;
+ } net_pinfo;
+#endif
+
+ union {
+ struct tcp_opt af_tcp;
+#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE)
+ struct raw_opt tp_raw4;
+#endif
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct raw6_opt tp_raw;
+#endif /* CONFIG_IPV6 */
+#if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE)
+ struct spx_opt af_spx;
+#endif /* CONFIG_SPX */
+
+ } tp_pinfo;
+
+ int err, err_soft; /* Soft holds errors that don't
+ cause failure but are the cause
+ of a persistent failure not just
+ 'timed out' */
+ unsigned short ack_backlog;
+ unsigned short max_ack_backlog;
+ __u32 priority;
+ unsigned short type;
+ unsigned char localroute; /* Route locally only */
+ unsigned char protocol;
+ struct ucred peercred;
+
+#ifdef CONFIG_FILTER
+ /* Socket Filtering Instructions */
+ struct sk_filter *filter;
+#endif /* CONFIG_FILTER */
+
+ /* This is where all the private (optional) areas that don't
+ * overlap will eventually live.
+ */
+ union {
+ void *destruct_hook;
+ struct unix_opt af_unix;
+#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
+ struct atalk_sock af_at;
+#endif
+#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
+ struct ipx_opt af_ipx;
+#endif
+#if defined (CONFIG_DECNET) || defined(CONFIG_DECNET_MODULE)
+ struct dn_scp dn;
+#endif
+#if defined (CONFIG_PACKET) || defined(CONFIG_PACKET_MODULE)
+ struct packet_opt *af_packet;
+#endif
+#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
+ x25_cb *x25;
+#endif
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ ax25_cb *ax25;
+#endif
+#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+ nr_cb *nr;
+#endif
+#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
+ rose_cb *rose;
+#endif
+#ifdef CONFIG_NETLINK
+ struct netlink_opt af_netlink;
+#endif
+#if defined(CONFIG_ECONET) || defined(CONFIG_ECONET_MODULE)
+ struct econet_opt *af_econet;
+#endif
+#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
+ struct irda_sock *irda;
+#endif
+ } protinfo;
+
+ /* IP 'private area' or will be eventually. */
+ int ip_ttl; /* TTL setting */
+ int ip_tos; /* TOS */
+ unsigned ip_cmsg_flags;
+ struct ip_options *opt;
+ unsigned char ip_hdrincl; /* Include headers ? */
+ __u8 ip_mc_ttl; /* Multicasting TTL */
+ __u8 ip_mc_loop; /* Loopback */
+ __u8 ip_recverr;
+ __u8 ip_pmtudisc;
+ int ip_mc_index; /* Multicast device index */
+ __u32 ip_mc_addr;
+ struct ip_mc_socklist *ip_mc_list; /* Group array */
+
+ /* This part is used for the timeout functions (timer.c). */
+ int timeout; /* What are we waiting for? */
+ struct timer_list timer; /* This is the sock cleanup timer. */
+ struct timeval stamp;
+
+ /* Identd */
+ struct socket *socket;
+
+ /* RPC layer private data */
+ void *user_data;
+
+ /* Callbacks */
+ void (*state_change)(struct sock *sk);
+ void (*data_ready)(struct sock *sk,int bytes);
+ void (*write_space)(struct sock *sk);
+ void (*error_report)(struct sock *sk);
+
+ int (*backlog_rcv) (struct sock *sk,
+ struct sk_buff *skb);
+ void (*destruct)(struct sock *sk);
+};
+
+/* IP protocol blocks we attach to sockets.
+ * socket layer -> transport layer interface
+ * transport -> network interface is defined by struct inet_proto
+ */
+struct proto {
+ /* These must be first. */
+ struct sock *sklist_next;
+ struct sock *sklist_prev;
+
+ void (*close)(struct sock *sk,
+ long timeout);
+ int (*connect)(struct sock *sk,
+ struct sockaddr *uaddr,
+ int addr_len);
+
+ struct sock * (*accept) (struct sock *sk, int flags);
+ void (*retransmit)(struct sock *sk, int all);
+ void (*write_wakeup)(struct sock *sk);
+ void (*read_wakeup)(struct sock *sk);
+
+ unsigned int (*poll)(struct file * file, struct socket *sock,
+ struct poll_table_struct *wait);
+
+ int (*ioctl)(struct sock *sk, int cmd,
+ unsigned long arg);
+ int (*init)(struct sock *sk);
+ int (*destroy)(struct sock *sk);
+ void (*shutdown)(struct sock *sk, int how);
+ int (*setsockopt)(struct sock *sk, int level,
+ int optname, char *optval, int optlen);
+ int (*getsockopt)(struct sock *sk, int level,
+ int optname, char *optval,
+ int *option);
+ int (*sendmsg)(struct sock *sk, struct msghdr *msg,
+ int len);
+ int (*recvmsg)(struct sock *sk, struct msghdr *msg,
+ int len, int noblock, int flags,
+ int *addr_len);
+ int (*bind)(struct sock *sk,
+ struct sockaddr *uaddr, int addr_len);
+
+ int (*backlog_rcv) (struct sock *sk,
+ struct sk_buff *skb);
+
+ /* Keeping track of sk's, looking them up, and port selection methods. */
+ void (*hash)(struct sock *sk);
+ void (*unhash)(struct sock *sk);
+ int (*get_port)(struct sock *sk, unsigned short snum);
+
+ unsigned short max_header;
+ unsigned long retransmits;
+ char name[32];
+ int inuse, highestinuse;
+};
+
+#define TIME_WRITE 1 /* Not yet used */
+#define TIME_RETRANS 2 /* Retransmit timer */
+#define TIME_DACK 3 /* Delayed ack timer */
+#define TIME_CLOSE 4
+#define TIME_KEEPOPEN 5
+#define TIME_DESTROY 6
+#define TIME_DONE 7 /* Used to absorb those last few packets */
+#define TIME_PROBE0 8
+
+/* About 10 seconds */
+#define SOCK_DESTROY_TIME (10*HZ)
+
+/* Sockets 0-1023 can't be bound to unless you are superuser */
+#define PROT_SOCK 1024
+
+#define SHUTDOWN_MASK 3
+#define RCV_SHUTDOWN 1
+#define SEND_SHUTDOWN 2
+
+/* Per-protocol hash table implementations use this to make sure
+ * nothing changes.
+ */
+#define SOCKHASH_LOCK() start_bh_atomic()
+#define SOCKHASH_UNLOCK() end_bh_atomic()
+
+/* Some things in the kernel just want to get at a protocols
+ * entire socket list commensurate, thus...
+ */
+static __inline__ void __add_to_prot_sklist(struct sock *sk)
+{
+ struct proto *p = sk->prot;
+
+ sk->sklist_prev = (struct sock *) p;
+ sk->sklist_next = p->sklist_next;
+ p->sklist_next->sklist_prev = sk;
+ p->sklist_next = sk;
+
+ /* Charge the protocol. */
+ sk->prot->inuse += 1;
+ if(sk->prot->highestinuse < sk->prot->inuse)
+ sk->prot->highestinuse = sk->prot->inuse;
+}
+
+static __inline__ void add_to_prot_sklist(struct sock *sk)
+{
+ SOCKHASH_LOCK();
+ if(!sk->sklist_next)
+ __add_to_prot_sklist(sk);
+ SOCKHASH_UNLOCK();
+}
+
+static __inline__ void del_from_prot_sklist(struct sock *sk)
+{
+ SOCKHASH_LOCK();
+ if(sk->sklist_next) {
+ sk->sklist_next->sklist_prev = sk->sklist_prev;
+ sk->sklist_prev->sklist_next = sk->sklist_next;
+ sk->sklist_next = NULL;
+ sk->prot->inuse--;
+ }
+ SOCKHASH_UNLOCK();
+}
+
+/*
+ * Used by processes to "lock" a socket state, so that
+ * interrupts and bottom half handlers won't change it
+ * from under us. It essentially blocks any incoming
+ * packets, so that we won't get any new data or any
+ * packets that change the state of the socket.
+ *
+ * Note the 'barrier()' calls: gcc may not move a lock
+ * "downwards" or a unlock "upwards" when optimizing.
+ */
+extern void __release_sock(struct sock *sk);
+
+static inline void lock_sock(struct sock *sk)
+{
+#if 0
+/* debugging code: the test isn't even 100% correct, but it can catch bugs */
+/* Note that a double lock is ok in theory - it's just _usually_ a bug */
+/* Actually it can easily happen with multiple writers */
+ if (atomic_read(&sk->sock_readers)) {
+ printk("double lock on socket at %p\n", gethere());
+here:
+ }
+#endif
+ atomic_inc(&sk->sock_readers);
+ synchronize_bh();
+}
+
+static inline void release_sock(struct sock *sk)
+{
+ barrier();
+ if (atomic_dec_and_test(&sk->sock_readers))
+ __release_sock(sk);
+}
+
+/*
+ * This might not be the most appropriate place for this two
+ * but since they are used by a lot of the net related code
+ * at least they get declared on a include that is common to all
+ */
+
+static __inline__ int min(unsigned int a, unsigned int b)
+{
+ if (a > b)
+ a = b;
+ return a;
+}
+
+static __inline__ int max(unsigned int a, unsigned int b)
+{
+ if (a < b)
+ a = b;
+ return a;
+}
+
+extern struct sock * sk_alloc(int family, int priority, int zero_it);
+extern void sk_free(struct sock *sk);
+extern void destroy_sock(struct sock *sk);
+
+extern struct sk_buff *sock_wmalloc(struct sock *sk,
+ unsigned long size, int force,
+ int priority);
+extern struct sk_buff *sock_rmalloc(struct sock *sk,
+ unsigned long size, int force,
+ int priority);
+extern void sock_wfree(struct sk_buff *skb);
+extern void sock_rfree(struct sk_buff *skb);
+extern unsigned long sock_rspace(struct sock *sk);
+extern unsigned long sock_wspace(struct sock *sk);
+
+extern int sock_setsockopt(struct socket *sock, int level,
+ int op, char *optval,
+ int optlen);
+
+extern int sock_getsockopt(struct socket *sock, int level,
+ int op, char *optval,
+ int *optlen);
+extern struct sk_buff *sock_alloc_send_skb(struct sock *sk,
+ unsigned long size,
+ unsigned long fallback,
+ int noblock,
+ int *errcode);
+extern void *sock_kmalloc(struct sock *sk, int size, int priority);
+extern void sock_kfree_s(struct sock *sk, void *mem, int size);
+
+
+/*
+ * Functions to fill in entries in struct proto_ops when a protocol
+ * does not implement a particular function.
+ */
+extern int sock_no_dup(struct socket *, struct socket *);
+extern int sock_no_release(struct socket *,
+ struct socket *);
+extern int sock_no_bind(struct socket *,
+ struct sockaddr *, int);
+extern int sock_no_connect(struct socket *,
+ struct sockaddr *, int, int);
+extern int sock_no_socketpair(struct socket *,
+ struct socket *);
+extern int sock_no_accept(struct socket *,
+ struct socket *, int);
+extern int sock_no_getname(struct socket *,
+ struct sockaddr *, int *, int);
+extern unsigned int sock_no_poll(struct file *, struct socket *,
+ struct poll_table_struct *);
+extern int sock_no_ioctl(struct socket *, unsigned int,
+ unsigned long);
+extern int sock_no_listen(struct socket *, int);
+extern int sock_no_shutdown(struct socket *, int);
+extern int sock_no_getsockopt(struct socket *, int , int,
+ char *, int *);
+extern int sock_no_setsockopt(struct socket *, int, int,
+ char *, int);
+extern int sock_no_fcntl(struct socket *,
+ unsigned int, unsigned long);
+extern int sock_no_sendmsg(struct socket *,
+ struct msghdr *, int,
+ struct scm_cookie *);
+extern int sock_no_recvmsg(struct socket *,
+ struct msghdr *, int,
+ struct scm_cookie *);
+
+/*
+ * Default socket callbacks and setup code
+ */
+
+extern void sock_def_callback1(struct sock *);
+extern void sock_def_callback2(struct sock *, int);
+extern void sock_def_callback3(struct sock *);
+extern void sock_def_destruct(struct sock *);
+
+/* Initialise core socket variables */
+extern void sock_init_data(struct socket *sock, struct sock *sk);
+
+extern void sklist_remove_socket(struct sock **list, struct sock *sk);
+extern void sklist_insert_socket(struct sock **list, struct sock *sk);
+extern void sklist_destroy_socket(struct sock **list, struct sock *sk);
+
+#ifdef CONFIG_FILTER
+/*
+ * Run the filter code and then cut skb->data to correct size returned by
+ * sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller
+ * than pkt_len we keep whole skb->data.
+ */
+extern __inline__ int sk_filter(struct sk_buff *skb, struct sk_filter *filter)
+{
+ int pkt_len;
+
+ pkt_len = sk_run_filter(skb, filter->insns, filter->len);
+ if(!pkt_len)
+ return 1; /* Toss Packet */
+ else
+ skb_trim(skb, pkt_len);
+
+ return 0;
+}
+
+extern __inline__ void sk_filter_release(struct sock *sk, struct sk_filter *fp)
+{
+ unsigned int size = sk_filter_len(fp);
+
+ atomic_sub(size, &sk->omem_alloc);
+
+ if (atomic_dec_and_test(&fp->refcnt))
+ kfree_s(fp, size);
+}
+
+extern __inline__ void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
+{
+ atomic_inc(&fp->refcnt);
+ atomic_add(sk_filter_len(fp), &sk->omem_alloc);
+}
+
+#endif /* CONFIG_FILTER */
+
+/*
+ * Queue a received datagram if it will fit. Stream and sequenced
+ * protocols can't normally use this as they need to fit buffers in
+ * and play with them.
+ *
+ * Inlined as it's very short and called for pretty much every
+ * packet ever received.
+ */
+
+extern __inline__ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
+{
+ skb->sk = sk;
+ skb->destructor = sock_wfree;
+ atomic_add(skb->truesize, &sk->wmem_alloc);
+}
+
+extern __inline__ void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+ skb->sk = sk;
+ skb->destructor = sock_rfree;
+ atomic_add(skb->truesize, &sk->rmem_alloc);
+}
+
+
+extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+#ifdef CONFIG_FILTER
+ struct sk_filter *filter;
+#endif
+ /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
+ number of warnings when compiling with -W --ANK
+ */
+ if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
+ return -ENOMEM;
+
+#ifdef CONFIG_FILTER
+ if ((filter = sk->filter) != NULL && sk_filter(skb, filter))
+ return -EPERM; /* Toss packet */
+#endif /* CONFIG_FILTER */
+
+ skb_set_owner_r(skb, sk);
+ skb_queue_tail(&sk->receive_queue, skb);
+ if (!sk->dead)
+ sk->data_ready(sk,skb->len);
+ return 0;
+}
+
+extern __inline__ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
+{
+ /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
+ number of warnings when compiling with -W --ANK
+ */
+ if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
+ return -ENOMEM;
+ skb_set_owner_r(skb, sk);
+ skb_queue_tail(&sk->error_queue,skb);
+ if (!sk->dead)
+ sk->data_ready(sk,skb->len);
+ return 0;
+}
+
+/*
+ * Recover an error report and clear atomically
+ */
+
+extern __inline__ int sock_error(struct sock *sk)
+{
+ int err=xchg(&sk->err,0);
+ return -err;
+}
+
+extern __inline__ unsigned long sock_wspace(struct sock *sk)
+{
+ int amt = 0;
+
+ if (!(sk->shutdown & SEND_SHUTDOWN)) {
+ amt = sk->sndbuf - atomic_read(&sk->wmem_alloc);
+ if (amt < 0)
+ amt = 0;
+ }
+ return amt;
+}
+
+/*
+ * Default write policy as shown to user space via poll/select/SIGIO
+ * Kernel internally doesn't use the MIN_WRITE_SPACE threshold.
+ */
+extern __inline__ int sock_writeable(struct sock *sk)
+{
+ return sock_wspace(sk) >= MIN_WRITE_SPACE;
+}
+
+/*
+ * Declarations from timer.c
+ */
+
+extern struct sock *timer_base;
+
+extern void net_delete_timer (struct sock *);
+extern void net_reset_timer (struct sock *, int, unsigned long);
+extern void net_timer (unsigned long);
+
+extern __inline__ int gfp_any(void)
+{
+ return in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+}
+
+/*
+ * Enable debug/info messages
+ */
+
+#if 1
+#define NETDEBUG(x) do { } while (0)
+#else
+#define NETDEBUG(x) do { x; } while (0)
+#endif
+
+#endif /* _SOCK_H */
diff --git a/pfinet/linux-src/include/net/spx.h b/pfinet/linux-src/include/net/spx.h
new file mode 100644
index 00000000..a449b891
--- /dev/null
+++ b/pfinet/linux-src/include/net/spx.h
@@ -0,0 +1,93 @@
+#ifndef __NET_SPX_H
+#define __NET_SPX_H
+
+#include <net/ipx.h>
+
+struct spxhdr
+{ __u8 cctl;
+ __u8 dtype;
+#define SPX_DTYPE_ECONN 0xFE /* Finished */
+#define SPX_DTYPE_ECACK 0xFF /* Ok */
+ __u16 sconn; /* Connection ID */
+ __u16 dconn; /* Connection ID */
+ __u16 sequence;
+ __u16 ackseq;
+ __u16 allocseq;
+};
+
+struct ipxspxhdr
+{ struct ipxhdr ipx;
+ struct spxhdr spx;
+};
+
+#define SPX_SYS_PKT_LEN (sizeof(struct ipxspxhdr))
+
+#ifdef __KERNEL__
+struct spx_opt
+{ int state;
+ int sndbuf;
+ int retries; /* Number of WD retries */
+ int retransmits; /* Number of retransmits */
+ int max_retries;
+ int wd_interval;
+ void *owner;
+ __u16 dest_connid; /* Net order */
+ __u16 source_connid; /* Net order */
+ __u16 sequence; /* Host order - our current pkt # */
+ __u16 alloc; /* Host order - max seq we can rcv now */
+ __u16 rmt_ack; /* Host order - last pkt ACKd by remote */
+ __u16 rmt_seq;
+ __u16 acknowledge;
+ __u16 rmt_alloc; /* Host order - max seq remote can handle now */
+ ipx_address dest_addr;
+ ipx_address source_addr;
+ struct timer_list watchdog; /* Idle watch */
+ struct timer_list retransmit; /* Retransmit timer */
+ struct sk_buff_head rcv_queue;
+ struct sk_buff_head transmit_queue;
+ struct sk_buff_head retransmit_queue;
+};
+
+/* Packet connectino control defines */
+#define CCTL_SPXII_XHD 0x01 /* SPX2 extended header */
+#define CCTL_SPX_UNKNOWN 0x02 /* Unknown (unused ??) */
+#define CCTL_SPXII_NEG 0x04 /* Negotiate size */
+#define CCTL_SPXII 0x08 /* Set for SPX2 */
+#define CCTL_EOM 0x10 /* End of message marker */
+#define CCTL_URG 0x20 /* Urgent marker in SPP (not used in SPX?) */
+#define CCTL_ACK 0x40 /* Send me an ACK */
+#define CCTL_CTL 0x80 /* Control message */
+#define CCTL_SYS CCTL_CTL /* Spec uses CCTL_SYS */
+
+/* Connection state defines */
+#define SPX_CLOSED 7
+#define SPX_CONNECTING 8
+#define SPX_CONNECTED 9
+
+/* Packet transmit types - Internal */
+#define DATA 0 /* Data */
+#define ACK 1 /* Data ACK */
+#define WDACK 2 /* WD ACK */
+#define CONACK 3 /* Connection Request ACK */
+#define CONREQ 4 /* Connection Request */
+#define WDREQ 5 /* WD Request */
+#define DISCON 6 /* Informed Disconnect */
+#define DISACK 7 /* Informed Disconnect ACK */
+#define RETRAN 8 /* Int. Retransmit of packet */
+#define TQUEUE 9 /* Int. Transmit of a queued packet */
+
+/*
+ * These are good canidates for IOcontrol calls
+ */
+
+/* Watchdog defines */
+#define VERIFY_TIMEOUT 3 * HZ
+#define ABORT_TIMEOUT 30 * HZ
+
+/* Packet retransmit defines */
+#define RETRY_COUNT 10
+#define RETRY_TIME 1 * HZ
+#define MAX_RETRY_DELAY 5 * HZ
+
+#endif /* __KERNEL__ */
+#endif /* def __NET_SPX_H */
diff --git a/pfinet/linux-src/include/net/spxcall.h b/pfinet/linux-src/include/net/spxcall.h
new file mode 100644
index 00000000..0461fbbe
--- /dev/null
+++ b/pfinet/linux-src/include/net/spxcall.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void spx_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/include/net/tcp.h b/pfinet/linux-src/include/net/tcp.h
new file mode 100644
index 00000000..8b050c63
--- /dev/null
+++ b/pfinet/linux-src/include/net/tcp.h
@@ -0,0 +1,1100 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the TCP module.
+ *
+ * Version: @(#)tcp.h 1.0.5 05/23/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _TCP_H
+#define _TCP_H
+
+#include <linux/config.h>
+#include <linux/tcp.h>
+#include <linux/slab.h>
+#include <net/checksum.h>
+
+/* This is for all connections with a full identity, no wildcards.
+ * New scheme, half the table is for TIME_WAIT, the other half is
+ * for the rest. I'll experiment with dynamic table growth later.
+ */
+#define TCP_HTABLE_SIZE 512
+
+/* This is for listening sockets, thus all sockets which possess wildcards. */
+#define TCP_LHTABLE_SIZE 32 /* Yes, really, this is all you need. */
+
+/* This is for all sockets, to keep track of the local port allocations. */
+#define TCP_BHTABLE_SIZE 512
+
+/* tcp_ipv4.c: These need to be shared by v4 and v6 because the lookup
+ * and hashing code needs to work with different AF's yet
+ * the port space is shared.
+ */
+extern struct sock *tcp_established_hash[TCP_HTABLE_SIZE];
+extern struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE];
+
+/* There are a few simple rules, which allow for local port reuse by
+ * an application. In essence:
+ *
+ * 1) Sockets bound to different interfaces may share a local port.
+ * Failing that, goto test 2.
+ * 2) If all sockets have sk->reuse set, and none of them are in
+ * TCP_LISTEN state, the port may be shared.
+ * Failing that, goto test 3.
+ * 3) If all sockets are bound to a specific sk->rcv_saddr local
+ * address, and none of them are the same, the port may be
+ * shared.
+ * Failing this, the port cannot be shared.
+ *
+ * The interesting point, is test #2. This is what an FTP server does
+ * all day. To optimize this case we use a specific flag bit defined
+ * below. As we add sockets to a bind bucket list, we perform a
+ * check of: (newsk->reuse && (newsk->state != TCP_LISTEN))
+ * As long as all sockets added to a bind bucket pass this test,
+ * the flag bit will be set.
+ * The resulting situation is that tcp_v[46]_verify_bind() can just check
+ * for this flag bit, if it is set and the socket trying to bind has
+ * sk->reuse set, we don't even have to walk the owners list at all,
+ * we return that it is ok to bind this socket to the requested local port.
+ *
+ * Sounds like a lot of work, but it is worth it. In a more naive
+ * implementation (ie. current FreeBSD etc.) the entire list of ports
+ * must be walked for each data port opened by an ftp server. Needless
+ * to say, this does not scale at all. With a couple thousand FTP
+ * users logged onto your box, isn't it nice to know that new data
+ * ports are created in O(1) time? I thought so. ;-) -DaveM
+ */
+struct tcp_bind_bucket {
+ unsigned short port;
+ unsigned short fastreuse;
+ struct tcp_bind_bucket *next;
+ struct sock *owners;
+ struct tcp_bind_bucket **pprev;
+};
+
+extern struct tcp_bind_bucket *tcp_bound_hash[TCP_BHTABLE_SIZE];
+extern kmem_cache_t *tcp_bucket_cachep;
+extern struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum);
+extern void tcp_bucket_unlock(struct sock *sk);
+extern int tcp_port_rover;
+
+/* Level-1 socket-demux cache. */
+#define TCP_NUM_REGS 32
+extern struct sock *tcp_regs[TCP_NUM_REGS];
+
+#define TCP_RHASH_FN(__fport) \
+ ((((__fport) >> 7) ^ (__fport)) & (TCP_NUM_REGS - 1))
+#define TCP_RHASH(__fport) tcp_regs[TCP_RHASH_FN((__fport))]
+#define TCP_SK_RHASH_FN(__sock) TCP_RHASH_FN((__sock)->dport)
+#define TCP_SK_RHASH(__sock) tcp_regs[TCP_SK_RHASH_FN((__sock))]
+
+static __inline__ void tcp_reg_zap(struct sock *sk)
+{
+ struct sock **rpp;
+
+ rpp = &(TCP_SK_RHASH(sk));
+ if(*rpp == sk)
+ *rpp = NULL;
+}
+
+/* These are AF independent. */
+static __inline__ int tcp_bhashfn(__u16 lport)
+{
+ return (lport & (TCP_BHTABLE_SIZE - 1));
+}
+
+/* This is a TIME_WAIT bucket. It works around the memory consumption
+ * problems of sockets in such a state on heavily loaded servers, but
+ * without violating the protocol specification.
+ */
+struct tcp_tw_bucket {
+ /* These _must_ match the beginning of struct sock precisely.
+ * XXX Yes I know this is gross, but I'd have to edit every single
+ * XXX networking file if I created a "struct sock_header". -DaveM
+ * Just don't forget -fno-strict-aliasing, but it should be really
+ * fixed -AK
+ */
+ struct sock *sklist_next;
+ struct sock *sklist_prev;
+ struct sock *bind_next;
+ struct sock **bind_pprev;
+ __u32 daddr;
+ __u32 rcv_saddr;
+ __u16 dport;
+ unsigned short num;
+ int bound_dev_if;
+ struct sock *next;
+ struct sock **pprev;
+ unsigned char state,
+ zapped;
+ __u16 sport;
+ unsigned short family;
+ unsigned char reuse,
+ nonagle;
+
+ /* And these are ours. */
+ __u32 rcv_nxt, snd_nxt;
+ __u16 window;
+ struct tcp_func *af_specific;
+ struct tcp_bind_bucket *tb;
+ struct tcp_tw_bucket *next_death;
+ struct tcp_tw_bucket **pprev_death;
+ int death_slot;
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct in6_addr v6_daddr;
+ struct in6_addr v6_rcv_saddr;
+#endif
+};
+
+extern kmem_cache_t *tcp_timewait_cachep;
+
+/* Socket demux engine toys. */
+#ifdef __BIG_ENDIAN
+#define TCP_COMBINED_PORTS(__sport, __dport) \
+ (((__u32)(__sport)<<16) | (__u32)(__dport))
+#else /* __LITTLE_ENDIAN */
+#define TCP_COMBINED_PORTS(__sport, __dport) \
+ (((__u32)(__dport)<<16) | (__u32)(__sport))
+#endif
+
+#if (BITS_PER_LONG == 64)
+#ifdef __BIG_ENDIAN
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr) \
+ __u64 __name = (((__u64)(__saddr))<<32)|((__u64)(__daddr));
+#else /* __LITTLE_ENDIAN */
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr) \
+ __u64 __name = (((__u64)(__daddr))<<32)|((__u64)(__saddr));
+#endif /* __BIG_ENDIAN */
+#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
+ (((*((__u64 *)&((__sk)->daddr)))== (__cookie)) && \
+ ((*((__u32 *)&((__sk)->dport)))== (__ports)) && \
+ (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+#else /* 32-bit arch */
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr)
+#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
+ (((__sk)->daddr == (__saddr)) && \
+ ((__sk)->rcv_saddr == (__daddr)) && \
+ ((*((__u32 *)&((__sk)->dport)))== (__ports)) && \
+ (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+#endif /* 64-bit arch */
+
+#define TCP_IPV6_MATCH(__sk, __saddr, __daddr, __ports, __dif) \
+ (((*((__u32 *)&((__sk)->dport)))== (__ports)) && \
+ ((__sk)->family == AF_INET6) && \
+ !ipv6_addr_cmp(&(__sk)->net_pinfo.af_inet6.daddr, (__saddr)) && \
+ !ipv6_addr_cmp(&(__sk)->net_pinfo.af_inet6.rcv_saddr, (__daddr)) && \
+ (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+
+/* These can have wildcards, don't try too hard. */
+static __inline__ int tcp_lhashfn(unsigned short num)
+{
+ return num & (TCP_LHTABLE_SIZE - 1);
+}
+
+static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
+{
+ return tcp_lhashfn(sk->num);
+}
+
+/* Note, that it is > than ipv6 header */
+#define NETHDR_SIZE (sizeof(struct iphdr) + 40)
+
+/*
+ * 40 is maximal IP options size
+ * 20 is the maximum TCP options size we can currently construct on a SYN.
+ * 40 is the maximum possible TCP options size.
+ */
+
+#define MAX_SYN_SIZE (NETHDR_SIZE + sizeof(struct tcphdr) + 20 + MAX_HEADER + 15)
+#define MAX_FIN_SIZE (NETHDR_SIZE + sizeof(struct tcphdr) + MAX_HEADER + 15)
+#define BASE_ACK_SIZE (NETHDR_SIZE + MAX_HEADER + 15)
+#define MAX_ACK_SIZE (NETHDR_SIZE + sizeof(struct tcphdr) + MAX_HEADER + 15)
+#define MAX_RESET_SIZE (NETHDR_SIZE + sizeof(struct tcphdr) + MAX_HEADER + 15)
+#define MAX_TCPHEADER_SIZE (NETHDR_SIZE + sizeof(struct tcphdr) + 20 + MAX_HEADER + 15)
+
+/*
+ * Never offer a window over 32767 without using window scaling. Some
+ * poor stacks do signed 16bit maths!
+ */
+#define MAX_WINDOW 32767
+#define MIN_WINDOW 2048
+#define MAX_ACK_BACKLOG 2
+#define MAX_DELAY_ACK 2
+#define TCP_WINDOW_DIFF 2048
+
+/* urg_data states */
+#define URG_VALID 0x0100
+#define URG_NOTYET 0x0200
+#define URG_READ 0x0400
+
+#define TCP_RETR1 7 /*
+ * This is how many retries it does before it
+ * tries to figure out if the gateway is
+ * down.
+ */
+
+#define TCP_RETR2 15 /*
+ * This should take at least
+ * 90 minutes to time out.
+ */
+
+#define TCP_TIMEOUT_LEN (15*60*HZ) /* should be about 15 mins */
+#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to successfully
+ * close the socket, about 60 seconds */
+#define TCP_FIN_TIMEOUT (3*60*HZ) /* BSD style FIN_WAIT2 deadlock breaker */
+
+#define TCP_ACK_TIME (3*HZ) /* time to delay before sending an ACK */
+#define TCP_DONE_TIME (5*HZ/2)/* maximum time to wait before actually
+ * destroying a socket */
+#define TCP_WRITE_TIME (30*HZ) /* initial time to wait for an ACK,
+ * after last transmit */
+#define TCP_TIMEOUT_INIT (3*HZ) /* RFC 1122 initial timeout value */
+#define TCP_SYN_RETRIES 10 /* number of times to retry opening a
+ * connection (TCP_RETR2-....) */
+#define TCP_PROBEWAIT_LEN (1*HZ)/* time to wait between probes when
+ * I've got something to write and
+ * there is no window */
+#define TCP_KEEPALIVE_TIME (120*60*HZ) /* two hours */
+#define TCP_KEEPALIVE_PROBES 9 /* Max of 9 keepalive probes */
+#define TCP_KEEPALIVE_PERIOD ((75*HZ)>>2) /* period of keepalive check */
+
+#define TCP_SYNACK_PERIOD (HZ/2) /* How often to run the synack slow timer */
+#define TCP_QUICK_TRIES 8 /* How often we try to retransmit, until
+ * we tell the link layer that it is something
+ * wrong (e.g. that it can expire redirects) */
+
+#define TCP_BUCKETGC_PERIOD (HZ)
+
+/* TIME_WAIT reaping mechanism. */
+#define TCP_TWKILL_SLOTS 8 /* Please keep this a power of 2. */
+#define TCP_TWKILL_PERIOD ((HZ*60)/TCP_TWKILL_SLOTS)
+
+/*
+ * TCP option
+ */
+
+#define TCPOPT_NOP 1 /* Padding */
+#define TCPOPT_EOL 0 /* End of options */
+#define TCPOPT_MSS 2 /* Segment size negotiating */
+#define TCPOPT_WINDOW 3 /* Window scaling */
+#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
+#define TCPOPT_SACK 5 /* SACK Block */
+#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
+
+/*
+ * TCP option lengths
+ */
+
+#define TCPOLEN_MSS 4
+#define TCPOLEN_WINDOW 3
+#define TCPOLEN_SACK_PERM 2
+#define TCPOLEN_TIMESTAMP 10
+
+/* But this is what stacks really send out. */
+#define TCPOLEN_TSTAMP_ALIGNED 12
+#define TCPOLEN_WSCALE_ALIGNED 4
+#define TCPOLEN_SACKPERM_ALIGNED 4
+#define TCPOLEN_SACK_BASE 2
+#define TCPOLEN_SACK_BASE_ALIGNED 4
+#define TCPOLEN_SACK_PERBLOCK 8
+
+struct open_request;
+
+struct or_calltable {
+ void (*rtx_syn_ack) (struct sock *sk, struct open_request *req);
+ void (*destructor) (struct open_request *req);
+ void (*send_reset) (struct sk_buff *skb);
+};
+
+struct tcp_v4_open_req {
+ __u32 loc_addr;
+ __u32 rmt_addr;
+ struct ip_options *opt;
+};
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+struct tcp_v6_open_req {
+ struct in6_addr loc_addr;
+ struct in6_addr rmt_addr;
+ struct sk_buff *pktopts;
+ int iif;
+};
+#endif
+
+/* this structure is too big */
+struct open_request {
+ struct open_request *dl_next; /* Must be first member! */
+ __u32 rcv_isn;
+ __u32 snt_isn;
+ __u16 rmt_port;
+ __u16 mss;
+ __u8 retrans;
+ __u8 __pad;
+ unsigned snd_wscale : 4,
+ rcv_wscale : 4,
+ tstamp_ok : 1,
+ sack_ok : 1,
+ wscale_ok : 1;
+ /* The following two fields can be easily recomputed I think -AK */
+ __u32 window_clamp; /* window clamp at creation time */
+ __u32 rcv_wnd; /* rcv_wnd offered first time */
+ __u32 ts_recent;
+ unsigned long expires;
+ struct or_calltable *class;
+ struct sock *sk;
+ union {
+ struct tcp_v4_open_req v4_req;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct tcp_v6_open_req v6_req;
+#endif
+ } af;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ __u16 lcl_port; /* LVE */
+#endif
+};
+
+/* SLAB cache for open requests. */
+extern kmem_cache_t *tcp_openreq_cachep;
+
+#define tcp_openreq_alloc() kmem_cache_alloc(tcp_openreq_cachep, SLAB_ATOMIC)
+#define tcp_openreq_free(req) kmem_cache_free(tcp_openreq_cachep, req)
+
+/*
+ * Pointers to address related TCP functions
+ * (i.e. things that depend on the address family)
+ *
+ * BUGGG_FUTURE: all the idea behind this struct is wrong.
+ * It mixes socket frontend with transport function.
+ * With port sharing between IPv6/v4 it gives the only advantage,
+ * only poor IPv6 needs to permanently recheck, that it
+ * is still IPv6 8)8) It must be cleaned up as soon as possible.
+ * --ANK (980802)
+ */
+
+struct tcp_func {
+ void (*queue_xmit) (struct sk_buff *skb);
+
+ void (*send_check) (struct sock *sk,
+ struct tcphdr *th,
+ int len,
+ struct sk_buff *skb);
+
+ int (*rebuild_header) (struct sock *sk);
+
+ int (*conn_request) (struct sock *sk,
+ struct sk_buff *skb,
+ __u32 isn);
+
+ struct sock * (*syn_recv_sock) (struct sock *sk,
+ struct sk_buff *skb,
+ struct open_request *req,
+ struct dst_entry *dst);
+
+ struct sock * (*get_sock) (struct sk_buff *skb,
+ struct tcphdr *th);
+
+ __u16 net_header_len;
+
+
+
+ int (*setsockopt) (struct sock *sk,
+ int level,
+ int optname,
+ char *optval,
+ int optlen);
+
+ int (*getsockopt) (struct sock *sk,
+ int level,
+ int optname,
+ char *optval,
+ int *optlen);
+
+
+ void (*addr2sockaddr) (struct sock *sk,
+ struct sockaddr *);
+
+ int sockaddr_len;
+};
+
+/*
+ * The next routines deal with comparing 32 bit unsigned ints
+ * and worry about wraparound (automatic with unsigned arithmetic).
+ */
+
+extern __inline int before(__u32 seq1, __u32 seq2)
+{
+ return (__s32)(seq1-seq2) < 0;
+}
+
+extern __inline int after(__u32 seq1, __u32 seq2)
+{
+ return (__s32)(seq2-seq1) < 0;
+}
+
+
+/* is s2<=s1<=s3 ? */
+extern __inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
+{
+ return seq3 - seq2 >= seq1 - seq2;
+}
+
+
+extern struct proto tcp_prot;
+extern struct tcp_mib tcp_statistics;
+
+extern void tcp_put_port(struct sock *sk);
+extern void __tcp_put_port(struct sock *sk);
+extern void tcp_inherit_port(struct sock *sk, struct sock *child);
+
+extern void tcp_v4_err(struct sk_buff *skb,
+ unsigned char *, int);
+
+extern void tcp_shutdown (struct sock *sk, int how);
+
+extern int tcp_v4_rcv(struct sk_buff *skb,
+ unsigned short len);
+
+extern int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg);
+
+extern int tcp_ioctl(struct sock *sk,
+ int cmd,
+ unsigned long arg);
+
+extern int tcp_rcv_state_process(struct sock *sk,
+ struct sk_buff *skb,
+ struct tcphdr *th,
+ unsigned len);
+
+extern int tcp_rcv_established(struct sock *sk,
+ struct sk_buff *skb,
+ struct tcphdr *th,
+ unsigned len);
+
+enum tcp_tw_status {
+ TCP_TW_SUCCESS = 0,
+ TCP_TW_RST = 1,
+ TCP_TW_ACK = 2
+ };
+
+extern enum tcp_tw_status tcp_timewait_state_process(struct tcp_tw_bucket *tw,
+ struct sk_buff *skb,
+ struct tcphdr *th,
+ unsigned len);
+
+extern void tcp_close(struct sock *sk,
+ long timeout);
+extern struct sock * tcp_accept(struct sock *sk, int flags);
+extern unsigned int tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
+extern void tcp_write_space(struct sock *sk);
+
+extern int tcp_getsockopt(struct sock *sk, int level,
+ int optname, char *optval,
+ int *optlen);
+extern int tcp_setsockopt(struct sock *sk, int level,
+ int optname, char *optval,
+ int optlen);
+extern void tcp_set_keepalive(struct sock *sk, int val);
+extern int tcp_recvmsg(struct sock *sk,
+ struct msghdr *msg,
+ int len, int nonblock,
+ int flags, int *addr_len);
+
+extern void tcp_parse_options(struct sock *sk, struct tcphdr *th,
+ struct tcp_opt *tp, int no_fancy);
+
+/*
+ * TCP v4 functions exported for the inet6 API
+ */
+
+extern int tcp_v4_rebuild_header(struct sock *sk);
+
+extern int tcp_v4_build_header(struct sock *sk,
+ struct sk_buff *skb);
+
+extern void tcp_v4_send_check(struct sock *sk,
+ struct tcphdr *th, int len,
+ struct sk_buff *skb);
+
+extern int tcp_v4_conn_request(struct sock *sk,
+ struct sk_buff *skb,
+ __u32 isn);
+
+extern struct sock * tcp_create_openreq_child(struct sock *sk,
+ struct open_request *req,
+ struct sk_buff *skb);
+
+extern struct sock * tcp_v4_syn_recv_sock(struct sock *sk,
+ struct sk_buff *skb,
+ struct open_request *req,
+ struct dst_entry *dst);
+
+extern int tcp_v4_do_rcv(struct sock *sk,
+ struct sk_buff *skb);
+
+extern int tcp_v4_connect(struct sock *sk,
+ struct sockaddr *uaddr,
+ int addr_len);
+
+extern void tcp_connect(struct sock *sk,
+ struct sk_buff *skb,
+ int est_mss);
+
+extern struct sk_buff * tcp_make_synack(struct sock *sk,
+ struct dst_entry *dst,
+ struct open_request *req,
+ int mss);
+
+
+/* From syncookies.c */
+extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ struct ip_options *opt);
+extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
+ __u16 *mss);
+
+/* tcp_output.c */
+
+extern void tcp_read_wakeup(struct sock *);
+extern void tcp_write_xmit(struct sock *);
+extern void tcp_time_wait(struct sock *);
+extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
+extern void tcp_fack_retransmit(struct sock *);
+extern void tcp_xmit_retransmit_queue(struct sock *);
+extern void tcp_simple_retransmit(struct sock *);
+
+extern void tcp_send_probe0(struct sock *);
+extern void tcp_send_partial(struct sock *);
+extern void tcp_write_wakeup(struct sock *);
+extern void tcp_send_fin(struct sock *sk);
+extern void tcp_send_active_reset(struct sock *sk);
+extern int tcp_send_synack(struct sock *);
+extern void tcp_transmit_skb(struct sock *, struct sk_buff *);
+extern void tcp_send_skb(struct sock *, struct sk_buff *, int force_queue);
+extern void tcp_send_ack(struct sock *sk);
+extern void tcp_send_delayed_ack(struct tcp_opt *tp, int max_timeout);
+
+/* CONFIG_IP_TRANSPARENT_PROXY */
+extern int tcp_chkaddr(struct sk_buff *);
+
+/* tcp_timer.c */
+#define tcp_reset_msl_timer(x,y,z) net_reset_timer(x,y,z)
+extern void tcp_reset_xmit_timer(struct sock *, int, unsigned long);
+extern void tcp_init_xmit_timers(struct sock *);
+extern void tcp_clear_xmit_timers(struct sock *);
+
+extern void tcp_retransmit_timer(unsigned long);
+extern void tcp_delack_timer(unsigned long);
+extern void tcp_probe_timer(unsigned long);
+
+extern struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
+ struct open_request *req);
+
+/*
+ * TCP slow timer
+ */
+extern struct timer_list tcp_slow_timer;
+
+struct tcp_sl_timer {
+ atomic_t count;
+ unsigned long period;
+ unsigned long last;
+ void (*handler) (unsigned long);
+};
+
+#define TCP_SLT_SYNACK 0
+#define TCP_SLT_KEEPALIVE 1
+#define TCP_SLT_TWKILL 2
+#define TCP_SLT_MAX 3
+
+extern struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX];
+
+extern int tcp_sync_mss(struct sock *sk, u32 pmtu);
+
+/* Compute the current effective MSS, taking SACKs and IP options,
+ * and even PMTU discovery events into account.
+ */
+
+static __inline__ unsigned int tcp_current_mss(struct sock *sk)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct dst_entry *dst = sk->dst_cache;
+ int mss_now = tp->mss_cache;
+
+ if (dst && dst->pmtu != tp->pmtu_cookie)
+ mss_now = tcp_sync_mss(sk, dst->pmtu);
+
+ if(tp->sack_ok && tp->num_sacks)
+ mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
+ (tp->num_sacks * TCPOLEN_SACK_PERBLOCK));
+ return mss_now > 8 ? mss_now : 8;
+}
+
+/* Compute the actual receive window we are currently advertising.
+ * Rcv_nxt can be after the window if our peer push more data
+ * than the offered window.
+ */
+static __inline__ u32 tcp_receive_window(struct tcp_opt *tp)
+{
+ s32 win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt;
+
+ if (win < 0)
+ win = 0;
+ return (u32) win;
+}
+
+/* Choose a new window, without checks for shrinking, and without
+ * scaling applied to the result. The caller does these things
+ * if necessary. This is a "raw" window selection.
+ */
+extern u32 __tcp_select_window(struct sock *sk);
+
+/* Chose a new window to advertise, update state in tcp_opt for the
+ * socket, and return result with RFC1323 scaling applied. The return
+ * value can be stuffed directly into th->window for an outgoing
+ * frame.
+ */
+extern __inline__ u16 tcp_select_window(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ u32 cur_win = tcp_receive_window(tp);
+ u32 new_win = __tcp_select_window(sk);
+
+ /* Never shrink the offered window */
+ if(new_win < cur_win) {
+ /* Danger Will Robinson!
+ * Don't update rcv_wup/rcv_wnd here or else
+ * we will not be able to advertise a zero
+ * window in time. --DaveM
+ */
+ new_win = cur_win;
+ } else {
+ tp->rcv_wnd = new_win;
+ tp->rcv_wup = tp->rcv_nxt;
+ }
+
+ /* RFC1323 scaling applied */
+ return new_win >> tp->rcv_wscale;
+}
+
+/* See if we can advertise non-zero, and if so how much we
+ * can increase our advertisement. If it becomes more than
+ * twice what we are talking about right now, return true.
+ */
+extern __inline__ int tcp_raise_window(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ u32 cur_win = tcp_receive_window(tp);
+ u32 new_win = __tcp_select_window(sk);
+
+ return (new_win && (new_win > (cur_win << 1)));
+}
+
+/* Recalculate snd_ssthresh, we want to set it to:
+ *
+ * one half the current congestion window, but no
+ * less than two segments
+ *
+ * We must take into account the current send window
+ * as well, however we keep track of that using different
+ * units so a conversion is necessary. -DaveM
+ */
+extern __inline__ __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
+{
+ __u32 snd_wnd_packets = tp->snd_wnd / max(tp->mss_cache, 1);
+
+ return max(min(snd_wnd_packets, tp->snd_cwnd) >> 1, 2);
+}
+
+/* TCP timestamps are only 32-bits, this causes a slight
+ * complication on 64-bit systems since we store a snapshot
+ * of jiffies in the buffer control blocks below. We decidely
+ * only use of the low 32-bits of jiffies and hide the ugly
+ * casts with the following macro.
+ */
+#define tcp_time_stamp ((__u32)(jiffies))
+
+/* This is what the send packet queueing engine uses to pass
+ * TCP per-packet control information to the transmission
+ * code. We also store the host-order sequence numbers in
+ * here too. This is 36 bytes on 32-bit architectures,
+ * 40 bytes on 64-bit machines, if this grows please adjust
+ * skbuff.h:skbuff->cb[xxx] size appropriately.
+ */
+struct tcp_skb_cb {
+ union {
+ struct inet_skb_parm h4;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct inet6_skb_parm h6;
+#endif
+ } header; /* For incoming frames */
+ __u32 seq; /* Starting sequence number */
+ __u32 end_seq; /* SEQ + FIN + SYN + datalen */
+ __u32 when; /* used to compute rtt's */
+ __u8 flags; /* TCP header flags. */
+
+ /* NOTE: These must match up to the flags byte in a
+ * real TCP header.
+ */
+#define TCPCB_FLAG_FIN 0x01
+#define TCPCB_FLAG_SYN 0x02
+#define TCPCB_FLAG_RST 0x04
+#define TCPCB_FLAG_PSH 0x08
+#define TCPCB_FLAG_ACK 0x10
+#define TCPCB_FLAG_URG 0x20
+
+ __u8 sacked; /* State flags for SACK/FACK. */
+#define TCPCB_SACKED_ACKED 0x01 /* SKB ACK'd by a SACK block */
+#define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */
+
+ __u16 urg_ptr; /* Valid w/URG flags is set. */
+ __u32 ack_seq; /* Sequence number ACK'd */
+};
+
+#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
+
+/* This determines how many packets are "in the network" to the best
+ * of our knowledge. In many cases it is conservative, but where
+ * detailed information is available from the receiver (via SACK
+ * blocks etc.) we can make more aggressive calculations.
+ *
+ * Use this for decisions involving congestion control, use just
+ * tp->packets_out to determine if the send queue is empty or not.
+ *
+ * Read this equation as:
+ *
+ * "Packets sent once on transmission queue" MINUS
+ * "Packets acknowledged by FACK information" PLUS
+ * "Packets fast retransmitted"
+ */
+static __inline__ int tcp_packets_in_flight(struct tcp_opt *tp)
+{
+ return tp->packets_out - tp->fackets_out + tp->retrans_out;
+}
+
+/* This checks if the data bearing packet SKB (usually tp->send_head)
+ * should be put on the wire right now.
+ */
+static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int nagle_check = 1;
+
+ /* RFC 1122 - section 4.2.3.4
+ *
+ * We must queue if
+ *
+ * a) The right edge of this frame exceeds the window
+ * b) There are packets in flight and we have a small segment
+ * [SWS avoidance and Nagle algorithm]
+ * (part of SWS is done on packetization)
+ * c) We are retransmiting [Nagle]
+ * d) We have too many packets 'in flight'
+ *
+ * Don't use the nagle rule for urgent data (or
+ * for the final FIN -DaveM).
+ */
+ if ((sk->nonagle == 2 && (skb->len < tp->mss_cache)) ||
+ (!sk->nonagle &&
+ skb->len < (tp->mss_cache >> 1) &&
+ tp->packets_out &&
+ !(TCP_SKB_CB(skb)->flags & (TCPCB_FLAG_URG|TCPCB_FLAG_FIN))))
+ nagle_check = 0;
+
+ /* Don't be strict about the congestion window for the
+ * final FIN frame. -DaveM
+ */
+ return (nagle_check &&
+ ((tcp_packets_in_flight(tp) < tp->snd_cwnd) ||
+ (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
+ !after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) &&
+ tp->retransmits == 0);
+}
+
+/* Push out any pending frames which were held back due to
+ * TCP_CORK or attempt at coalescing tiny packets.
+ * The socket must be locked by the caller.
+ */
+static __inline__ void tcp_push_pending_frames(struct sock *sk, struct tcp_opt *tp)
+{
+ if(tp->send_head) {
+ if(tcp_snd_test(sk, tp->send_head))
+ tcp_write_xmit(sk);
+ else if(tp->packets_out == 0 && !tp->pending) {
+ /* We held off on this in tcp_send_skb() */
+ tp->pending = TIME_PROBE0;
+ tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto);
+ }
+ }
+}
+
+/* This tells the input processing path that an ACK should go out
+ * right now.
+ */
+#define tcp_enter_quickack_mode(__tp) ((__tp)->ato |= (1<<31))
+#define tcp_exit_quickack_mode(__tp) ((__tp)->ato &= ~(1<<31))
+#define tcp_in_quickack_mode(__tp) (((__tp)->ato & (1 << 31)) != 0)
+
+/*
+ * List all states of a TCP socket that can be viewed as a "connected"
+ * state. This now includes TCP_SYN_RECV, although I am not yet fully
+ * convinced that this is the solution for the 'getpeername(2)'
+ * problem. Thanks to Stephen A. Wood <saw@cebaf.gov> -FvK
+ */
+
+extern __inline const int tcp_connected(const int state)
+{
+ return ((1 << state) &
+ (TCPF_ESTABLISHED|TCPF_CLOSE_WAIT|TCPF_FIN_WAIT1|
+ TCPF_FIN_WAIT2|TCPF_SYN_RECV));
+}
+
+/*
+ * Calculate(/check) TCP checksum
+ */
+static __inline__ u16 tcp_v4_check(struct tcphdr *th, int len,
+ unsigned long saddr, unsigned long daddr,
+ unsigned long base)
+{
+ return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
+}
+
+#undef STATE_TRACE
+
+#ifdef STATE_TRACE
+static char *statename[]={
+ "Unused","Established","Syn Sent","Syn Recv",
+ "Fin Wait 1","Fin Wait 2","Time Wait", "Close",
+ "Close Wait","Last ACK","Listen","Closing"
+};
+#endif
+
+static __inline__ void tcp_set_state(struct sock *sk, int state)
+{
+ int oldstate = sk->state;
+
+ sk->state = state;
+
+#ifdef STATE_TRACE
+ SOCK_DEBUG(sk, "TCP sk=%p, State %s -> %s\n",sk, statename[oldstate],statename[state]);
+#endif
+
+ switch (state) {
+ case TCP_ESTABLISHED:
+ if (oldstate != TCP_ESTABLISHED)
+ tcp_statistics.TcpCurrEstab++;
+ break;
+
+ case TCP_CLOSE:
+ {
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ /* Should be about 2 rtt's */
+ net_reset_timer(sk, TIME_DONE, min(tp->srtt * 2, TCP_DONE_TIME));
+ sk->prot->unhash(sk);
+ /* fall through */
+ }
+ default:
+ if (oldstate==TCP_ESTABLISHED)
+ tcp_statistics.TcpCurrEstab--;
+ }
+}
+
+static __inline__ void tcp_build_and_update_options(__u32 *ptr, struct tcp_opt *tp, __u32 tstamp)
+{
+ if (tp->tstamp_ok) {
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl(tstamp);
+ *ptr++ = htonl(tp->ts_recent);
+ }
+ if(tp->sack_ok && tp->num_sacks) {
+ int this_sack;
+
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_SACK << 8) |
+ (TCPOLEN_SACK_BASE +
+ (tp->num_sacks * TCPOLEN_SACK_PERBLOCK)));
+ for(this_sack = 0; this_sack < tp->num_sacks; this_sack++) {
+ *ptr++ = htonl(tp->selective_acks[this_sack].start_seq);
+ *ptr++ = htonl(tp->selective_acks[this_sack].end_seq);
+ }
+ }
+}
+
+/* Construct a tcp options header for a SYN or SYN_ACK packet.
+ * If this is every changed make sure to change the definition of
+ * MAX_SYN_SIZE to match the new maximum number of options that you
+ * can generate.
+ */
+extern __inline__ void tcp_syn_build_options(__u32 *ptr, int mss, int ts, int sack,
+ int offer_wscale, int wscale, __u32 tstamp, __u32 ts_recent)
+{
+ /* We always get an MSS option.
+ * The option bytes which will be seen in normal data
+ * packets should timestamps be used, must be in the MSS
+ * advertised. But we subtract them from sk->mss so
+ * that calculations in tcp_sendmsg are simpler etc.
+ * So account for this fact here if necessary. If we
+ * don't do this correctly, as a receiver we won't
+ * recognize data packets as being full sized when we
+ * should, and thus we won't abide by the delayed ACK
+ * rules correctly.
+ * SACKs don't matter, we never delay an ACK when we
+ * have any of those going out.
+ */
+ *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
+ if (ts) {
+ if(sack)
+ *ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) |
+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ else
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl(tstamp); /* TSVAL */
+ *ptr++ = htonl(ts_recent); /* TSECR */
+ } else if(sack)
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM);
+ if (offer_wscale)
+ *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
+}
+
+/* Determine a window scaling and initial window to offer.
+ * Based on the assumption that the given amount of space
+ * will be offered. Store the results in the tp structure.
+ * NOTE: for smooth operation initial space offering should
+ * be a multiple of mss if possible. We assume here that mss >= 1.
+ * This MUST be enforced by all callers.
+ */
+extern __inline__ void tcp_select_initial_window(__u32 space, __u16 mss,
+ __u32 *rcv_wnd,
+ __u32 *window_clamp,
+ int wscale_ok,
+ __u8 *rcv_wscale)
+{
+ /* If no clamp set the clamp to the max possible scaled window */
+ if (*window_clamp == 0)
+ (*window_clamp) = (65535<<14);
+ space = min(*window_clamp,space);
+
+ /* Quantize space offering to a multiple of mss if possible. */
+ if (space > mss)
+ space = (space/mss)*mss;
+
+ /* NOTE: offering an initial window larger than 32767
+ * will break some buggy TCP stacks. We try to be nice.
+ * If we are not window scaling, then this truncates
+ * our initial window offering to 32k. There should also
+ * be a sysctl option to stop being nice.
+ */
+ (*rcv_wnd) = min(space, MAX_WINDOW);
+ (*rcv_wscale) = 0;
+ if (wscale_ok) {
+ /* See RFC1323 for an explanation of the limit to 14 */
+ while (space > 65535 && (*rcv_wscale) < 14) {
+ space >>= 1;
+ (*rcv_wscale)++;
+ }
+ }
+ /* Set the clamp no higher than max representable value */
+ (*window_clamp) = min(65535<<(*rcv_wscale),*window_clamp);
+}
+
+extern __inline__ void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req, struct open_request *prev)
+{
+ if(!req->dl_next)
+ tp->syn_wait_last = (struct open_request **)prev;
+ prev->dl_next = req->dl_next;
+}
+
+extern __inline__ void tcp_synq_queue(struct tcp_opt *tp, struct open_request *req)
+{
+ req->dl_next = NULL;
+ *tp->syn_wait_last = req;
+ tp->syn_wait_last = &req->dl_next;
+}
+
+extern __inline__ void tcp_synq_init(struct tcp_opt *tp)
+{
+ tp->syn_wait_queue = NULL;
+ tp->syn_wait_last = &tp->syn_wait_queue;
+}
+
+extern void __tcp_inc_slow_timer(struct tcp_sl_timer *slt);
+extern __inline__ void tcp_inc_slow_timer(int timer)
+{
+ struct tcp_sl_timer *slt = &tcp_slt_array[timer];
+
+ if (atomic_read(&slt->count) == 0)
+ {
+ __tcp_inc_slow_timer(slt);
+ }
+
+ atomic_inc(&slt->count);
+}
+
+extern __inline__ void tcp_dec_slow_timer(int timer)
+{
+ struct tcp_sl_timer *slt = &tcp_slt_array[timer];
+
+ atomic_dec(&slt->count);
+}
+
+extern const char timer_bug_msg[];
+
+static inline void tcp_clear_xmit_timer(struct sock *sk, int what)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct timer_list *timer;
+
+ switch (what) {
+ case TIME_RETRANS:
+ timer = &tp->retransmit_timer;
+ break;
+ case TIME_DACK:
+ timer = &tp->delack_timer;
+ break;
+ case TIME_PROBE0:
+ timer = &tp->probe_timer;
+ break;
+ default:
+ printk(timer_bug_msg);
+ return;
+ };
+ if(timer->prev != NULL)
+ del_timer(timer);
+}
+
+static inline int tcp_timer_is_set(struct sock *sk, int what)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ switch (what) {
+ case TIME_RETRANS:
+ return tp->retransmit_timer.prev != NULL;
+ break;
+ case TIME_DACK:
+ return tp->delack_timer.prev != NULL;
+ break;
+ case TIME_PROBE0:
+ return tp->probe_timer.prev != NULL;
+ break;
+ default:
+ printk(timer_bug_msg);
+ };
+ return 0;
+}
+
+
+#endif /* _TCP_H */
diff --git a/pfinet/linux-src/include/net/transp_v6.h b/pfinet/linux-src/include/net/transp_v6.h
new file mode 100644
index 00000000..d49bc86e
--- /dev/null
+++ b/pfinet/linux-src/include/net/transp_v6.h
@@ -0,0 +1,46 @@
+#ifndef _TRANSP_V6_H
+#define _TRANSP_V6_H
+
+#include <net/checksum.h>
+
+/*
+ * IPv6 transport protocols
+ */
+
+#ifdef __KERNEL__
+
+extern struct proto rawv6_prot;
+extern struct proto udpv6_prot;
+extern struct proto tcpv6_prot;
+
+struct flowi;
+
+extern void rawv6_init(void);
+extern void udpv6_init(void);
+extern void tcpv6_init(void);
+
+extern int udpv6_connect(struct sock *sk,
+ struct sockaddr *uaddr,
+ int addr_len);
+
+extern int datagram_recv_ctl(struct sock *sk,
+ struct msghdr *msg,
+ struct sk_buff *skb);
+
+extern int datagram_send_ctl(struct msghdr *msg,
+ struct flowi *fl,
+ struct ipv6_txoptions *opt,
+ int *hlimit);
+
+#define LOOPBACK4_IPV6 __constant_htonl(0x7f000006)
+
+/*
+ * address family specific functions
+ */
+extern struct tcp_func ipv4_specific;
+
+extern int inet6_destroy_sock(struct sock *sk);
+
+#endif
+
+#endif
diff --git a/pfinet/linux-src/include/net/udp.h b/pfinet/linux-src/include/net/udp.h
new file mode 100644
index 00000000..f3ceadb5
--- /dev/null
+++ b/pfinet/linux-src/include/net/udp.h
@@ -0,0 +1,66 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the UDP module.
+ *
+ * Version: @(#)udp.h 1.0.2 05/07/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * Fixes:
+ * Alan Cox : Turned on udp checksums. I don't want to
+ * chase 'memory corruption' bugs that aren't!
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _UDP_H
+#define _UDP_H
+
+#include <linux/udp.h>
+#include <net/sock.h>
+
+#define UDP_HTABLE_SIZE 128
+
+/* udp.c: This needs to be shared by v4 and v6 because the lookup
+ * and hashing code needs to work with different AF's yet
+ * the port space is shared.
+ */
+extern struct sock *udp_hash[UDP_HTABLE_SIZE];
+
+#define UDP_NO_CHECK 0
+
+extern int udp_port_rover;
+
+static inline int udp_lport_inuse(u16 num)
+{
+ struct sock *sk = udp_hash[num & (UDP_HTABLE_SIZE - 1)];
+
+ for(; sk != NULL; sk = sk->next) {
+ if(sk->num == num)
+ return 1;
+ }
+ return 0;
+}
+
+extern struct proto udp_prot;
+
+
+extern void udp_err(struct sk_buff *, unsigned char *, int);
+extern int udp_connect(struct sock *sk,
+ struct sockaddr *usin, int addr_len);
+
+extern int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len);
+
+extern int udp_rcv(struct sk_buff *skb, unsigned short len);
+extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+
+/* CONFIG_IP_TRANSPARENT_PROXY */
+extern int udp_chkaddr(struct sk_buff *skb);
+
+#endif /* _UDP_H */
diff --git a/pfinet/linux-src/include/net/x25.h b/pfinet/linux-src/include/net/x25.h
new file mode 100644
index 00000000..5ac507bd
--- /dev/null
+++ b/pfinet/linux-src/include/net/x25.h
@@ -0,0 +1,221 @@
+/*
+ * Declarations of X.25 Packet Layer type objects.
+ *
+ * Jonathan Naylor 17/11/96
+ */
+
+#ifndef _X25_H
+#define _X25_H
+#include <linux/x25.h>
+
+#define X25_ADDR_LEN 16
+
+#define X25_MAX_L2_LEN 18 /* 802.2 LLC */
+
+#define X25_STD_MIN_LEN 3
+#define X25_EXT_MIN_LEN 4
+
+#define X25_GFI_SEQ_MASK 0x30
+#define X25_GFI_STDSEQ 0x10
+#define X25_GFI_EXTSEQ 0x20
+
+#define X25_Q_BIT 0x80
+#define X25_D_BIT 0x40
+#define X25_STD_M_BIT 0x10
+#define X25_EXT_M_BIT 0x01
+
+#define X25_CALL_REQUEST 0x0B
+#define X25_CALL_ACCEPTED 0x0F
+#define X25_CLEAR_REQUEST 0x13
+#define X25_CLEAR_CONFIRMATION 0x17
+#define X25_DATA 0x00
+#define X25_INTERRUPT 0x23
+#define X25_INTERRUPT_CONFIRMATION 0x27
+#define X25_RR 0x01
+#define X25_RNR 0x05
+#define X25_REJ 0x09
+#define X25_RESET_REQUEST 0x1B
+#define X25_RESET_CONFIRMATION 0x1F
+#define X25_REGISTRATION_REQUEST 0xF3
+#define X25_REGISTRATION_CONFIRMATION 0xF7
+#define X25_RESTART_REQUEST 0xFB
+#define X25_RESTART_CONFIRMATION 0xFF
+#define X25_DIAGNOSTIC 0xF1
+#define X25_ILLEGAL 0xFD
+
+/* Define the various conditions that may exist */
+
+#define X25_COND_ACK_PENDING 0x01
+#define X25_COND_OWN_RX_BUSY 0x02
+#define X25_COND_PEER_RX_BUSY 0x04
+
+/* Define Link State constants. */
+enum {
+ X25_STATE_0, /* Ready */
+ X25_STATE_1, /* Awaiting Call Accepted */
+ X25_STATE_2, /* Awaiting Clear Confirmation */
+ X25_STATE_3, /* Data Transfer */
+ X25_STATE_4 /* Awaiting Reset Confirmation */
+};
+
+enum {
+ X25_LINK_STATE_0,
+ X25_LINK_STATE_1,
+ X25_LINK_STATE_2,
+ X25_LINK_STATE_3
+};
+
+#define X25_DEFAULT_T20 (180 * HZ) /* Default T20 value */
+#define X25_DEFAULT_T21 (200 * HZ) /* Default T21 value */
+#define X25_DEFAULT_T22 (180 * HZ) /* Default T22 value */
+#define X25_DEFAULT_T23 (180 * HZ) /* Default T23 value */
+#define X25_DEFAULT_T2 (3 * HZ) /* Default ack holdback value */
+
+#define X25_DEFAULT_WINDOW_SIZE 2 /* Default Window Size */
+#define X25_DEFAULT_PACKET_SIZE X25_PS128 /* Default Packet Size */
+#define X25_DEFAULT_THROUGHPUT 0x0A /* Deafult Throughput */
+#define X25_DEFAULT_REVERSE 0x00 /* Default Reverse Charging */
+
+#define X25_SMODULUS 8
+#define X25_EMODULUS 128
+
+/*
+ * X.25 Facilities constants.
+ */
+
+#define X25_FAC_CLASS_MASK 0xC0
+
+#define X25_FAC_CLASS_A 0x00
+#define X25_FAC_CLASS_B 0x40
+#define X25_FAC_CLASS_C 0x80
+#define X25_FAC_CLASS_D 0xC0
+
+#define X25_FAC_REVERSE 0x01
+#define X25_FAC_THROUGHPUT 0x02
+#define X25_FAC_PACKET_SIZE 0x42
+#define X25_FAC_WINDOW_SIZE 0x43
+
+#define X25_MAX_FAC_LEN 20 /* Plenty to spare */
+#define X25_MAX_CUD_LEN 128
+
+struct x25_route {
+ struct x25_route *next;
+ x25_address address; /* Start of address range */
+ unsigned int sigdigits; /* Number of sig digits */
+ struct device *dev; /* More than one for MLP */
+};
+
+struct x25_neigh {
+ struct x25_neigh *next;
+ struct device *dev;
+ unsigned int state;
+ unsigned int extended;
+ struct sk_buff_head queue;
+ unsigned long t20;
+ struct timer_list t20timer;
+};
+
+typedef struct {
+ x25_address source_addr, dest_addr;
+ struct x25_neigh *neighbour;
+ unsigned int lci;
+ unsigned char state, condition, qbitincl, intflag;
+ unsigned short vs, vr, va, vl;
+ unsigned long t2, t21, t22, t23;
+ unsigned short fraglen;
+ struct sk_buff_head ack_queue;
+ struct sk_buff_head fragment_queue;
+ struct sk_buff_head interrupt_in_queue;
+ struct sk_buff_head interrupt_out_queue;
+ struct sock *sk; /* Backlink to socket */
+ struct timer_list timer;
+ struct x25_causediag causediag;
+ struct x25_facilities facilities;
+ struct x25_calluserdata calluserdata;
+} x25_cb;
+
+/* af_x25.c */
+extern int sysctl_x25_restart_request_timeout;
+extern int sysctl_x25_call_request_timeout;
+extern int sysctl_x25_reset_request_timeout;
+extern int sysctl_x25_clear_request_timeout;
+extern int sysctl_x25_ack_holdback_timeout;
+
+extern int x25_addr_ntoa(unsigned char *, x25_address *, x25_address *);
+extern int x25_addr_aton(unsigned char *, x25_address *, x25_address *);
+extern unsigned int x25_new_lci(struct x25_neigh *);
+extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
+extern void x25_destroy_socket(struct sock *);
+extern int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int);
+extern void x25_kill_by_neigh(struct x25_neigh *);
+
+#include <net/x25call.h>
+
+/* x25_dev.c */
+extern void x25_send_frame(struct sk_buff *, struct x25_neigh *);
+extern int x25_lapb_receive_frame(struct sk_buff *, struct device *, struct packet_type *);
+extern int x25_llc_receive_frame(struct sk_buff *, struct device *, struct packet_type *);
+extern void x25_establish_link(struct x25_neigh *);
+extern void x25_terminate_link(struct x25_neigh *);
+
+/* x25_facilities.c */
+extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *);
+extern int x25_create_facilities(unsigned char *, struct x25_facilities *);
+extern int x25_negotiate_facilities(struct sk_buff *, struct sock *, struct x25_facilities *);
+extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
+
+/* x25_in.c */
+extern int x25_process_rx_frame(struct sock *, struct sk_buff *);
+
+/* x25_link.c */
+extern void x25_link_control(struct sk_buff *, struct x25_neigh *, unsigned short);
+extern void x25_link_device_up(struct device *);
+extern void x25_link_device_down(struct device *);
+extern void x25_link_established(struct x25_neigh *);
+extern void x25_link_terminated(struct x25_neigh *);
+extern void x25_transmit_restart_request(struct x25_neigh *);
+extern void x25_transmit_restart_confirmation(struct x25_neigh *);
+extern void x25_transmit_diagnostic(struct x25_neigh *, unsigned char);
+extern void x25_transmit_clear_request(struct x25_neigh *, unsigned int, unsigned char);
+extern void x25_transmit_link(struct sk_buff *, struct x25_neigh *);
+extern int x25_subscr_ioctl(unsigned int, void *);
+extern struct x25_neigh *x25_get_neigh(struct device *);
+extern void x25_link_free(void);
+
+/* x25_out.c */
+extern void x25_output(struct sock *, struct sk_buff *);
+extern void x25_kick(struct sock *);
+extern void x25_enquiry_response(struct sock *);
+
+/* x25_route.c */
+extern struct device *x25_get_route(x25_address *);
+extern struct device *x25_dev_get(char *);
+extern void x25_route_device_down(struct device *);
+extern int x25_route_ioctl(unsigned int, void *);
+extern int x25_routes_get_info(char *, char **, off_t, int, int);
+extern void x25_route_free(void);
+
+/* x25_subr.c */
+extern void x25_clear_queues(struct sock *);
+extern void x25_frames_acked(struct sock *, unsigned short);
+extern void x25_requeue_frames(struct sock *);
+extern int x25_validate_nr(struct sock *, unsigned short);
+extern void x25_write_internal(struct sock *, int);
+extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *);
+extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
+
+/* x25_timer.c */
+extern void x25_start_heartbeat(struct sock *);
+extern void x25_start_t2timer(struct sock *);
+extern void x25_start_t21timer(struct sock *);
+extern void x25_start_t22timer(struct sock *);
+extern void x25_start_t23timer(struct sock *);
+extern void x25_stop_heartbeat(struct sock *);
+extern void x25_stop_timer(struct sock *);
+extern unsigned long x25_display_timer(struct sock *);
+
+/* sysctl_net_x25.c */
+extern void x25_register_sysctl(void);
+extern void x25_unregister_sysctl(void);
+
+#endif
diff --git a/pfinet/linux-src/include/net/x25call.h b/pfinet/linux-src/include/net/x25call.h
new file mode 100644
index 00000000..7c478a1d
--- /dev/null
+++ b/pfinet/linux-src/include/net/x25call.h
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void x25_proto_init(struct net_proto *pro);
diff --git a/pfinet/linux-src/net/core/Makefile b/pfinet/linux-src/net/core/Makefile
new file mode 100644
index 00000000..5df65cd2
--- /dev/null
+++ b/pfinet/linux-src/net/core/Makefile
@@ -0,0 +1,41 @@
+#
+# Makefile for the Linux networking core.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := core.o
+
+O_OBJS := sock.o skbuff.o iovec.o datagram.o scm.o
+
+ifeq ($(CONFIG_SYSCTL),y)
+ifeq ($(CONFIG_NET),y)
+O_OBJS += sysctl_net_core.o
+endif
+endif
+
+ifdef CONFIG_FILTER
+O_OBJS += filter.o
+endif
+
+ifdef CONFIG_NET
+
+O_OBJS += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o
+
+ifdef CONFIG_FIREWALL
+OX_OBJS += firewall.o
+endif
+
+endif
+
+ifdef CONFIG_NET_PROFILE
+OX_OBJS += profile.o
+endif
+
+include $(TOPDIR)/Rules.make
+
+tar:
+ tar -cvf /dev/f1 .
diff --git a/pfinet/linux-src/net/core/datagram.c b/pfinet/linux-src/net/core/datagram.c
new file mode 100644
index 00000000..9bb68fa4
--- /dev/null
+++ b/pfinet/linux-src/net/core/datagram.c
@@ -0,0 +1,249 @@
+/*
+ * SUCS NET3:
+ *
+ * Generic datagram handling routines. These are generic for all protocols. Possibly a generic IP version on top
+ * of these would make sense. Not tonight however 8-).
+ * This is used because UDP, RAW, PACKET, DDP, IPX, AX.25 and NetROM layer all have identical poll code and mostly
+ * identical recvmsg() code. So we share it here. The poll was shared before but buried in udp.c so I moved it.
+ *
+ * Authors: Alan Cox <alan@redhat.com>. (datagram_poll() from old udp.c code)
+ *
+ * Fixes:
+ * Alan Cox : NULL return from skb_peek_copy() understood
+ * Alan Cox : Rewrote skb_read_datagram to avoid the skb_peek_copy stuff.
+ * Alan Cox : Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but
+ * AX.25 now works right, and SPX is feasible.
+ * Alan Cox : Fixed write poll of non IP protocol crash.
+ * Florian La Roche: Changed for my new skbuff handling.
+ * Darryl Miles : Fixed non-blocking SOCK_SEQPACKET.
+ * Linus Torvalds : BSD semantic fixes.
+ * Alan Cox : Datagram iovec handling
+ * Darryl Miles : Fixed non-blocking SOCK_STREAM.
+ * Alan Cox : POSIXisms
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+
+
+/*
+ * Wait for a packet..
+ *
+ * Interrupts off so that no packet arrives before we begin sleeping.
+ * Otherwise we might miss our wake up
+ */
+
+static inline void wait_for_packet(struct sock * sk)
+{
+ struct wait_queue wait = { current, NULL };
+
+ add_wait_queue(sk->sleep, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+
+ if (skb_peek(&sk->receive_queue) == NULL)
+ schedule();
+
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+}
+
+/*
+ * Is a socket 'connection oriented' ?
+ */
+
+static inline int connection_based(struct sock *sk)
+{
+ return (sk->type==SOCK_SEQPACKET || sk->type==SOCK_STREAM);
+}
+
+/*
+ * Get a datagram skbuff, understands the peeking, nonblocking wakeups and possible
+ * races. This replaces identical code in packet,raw and udp, as well as the IPX
+ * AX.25 and Appletalk. It also finally fixes the long standing peek and read
+ * race for datagram sockets. If you alter this routine remember it must be
+ * re-entrant.
+ *
+ * This function will lock the socket if a skb is returned, so the caller
+ * needs to unlock the socket in that case (usually by calling skb_free_datagram)
+ *
+ * * It does not lock socket since today. This function is
+ * * free of race conditions. This measure should/can improve
+ * * significantly datagram socket latencies at high loads,
+ * * when data copying to user space takes lots of time.
+ * * (BTW I've just killed the last cli() in IP/IPv6/core/netlink/packet
+ * * 8) Great win.)
+ * * --ANK (980729)
+ *
+ * The order of the tests when we find no data waiting are specified
+ * quite explicitly by POSIX 1003.1g, don't change them without having
+ * the standard around please.
+ */
+
+struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
+{
+ int error;
+ struct sk_buff *skb;
+
+ /* Caller is allowed not to check sk->err before skb_recv_datagram() */
+ error = sock_error(sk);
+ if (error)
+ goto no_packet;
+
+restart:
+ while(skb_queue_empty(&sk->receive_queue)) /* No data */
+ {
+ /* Socket errors? */
+ error = sock_error(sk);
+ if (error)
+ goto no_packet;
+
+ /* Socket shut down? */
+ if (sk->shutdown & RCV_SHUTDOWN)
+ goto no_packet;
+
+ /* Sequenced packets can come disconnected. If so we report the problem */
+ error = -ENOTCONN;
+ if(connection_based(sk) && sk->state!=TCP_ESTABLISHED)
+ goto no_packet;
+
+ /* handle signals */
+ error = -ERESTARTSYS;
+ if (signal_pending(current))
+ goto no_packet;
+
+ /* User doesn't want to wait */
+ error = -EAGAIN;
+ if (noblock)
+ goto no_packet;
+
+ wait_for_packet(sk);
+ }
+
+ /* Again only user level code calls this function, so nothing interrupt level
+ will suddenly eat the receive_queue */
+ if (flags & MSG_PEEK)
+ {
+ unsigned long cpu_flags;
+
+ /* It is the only POTENTIAL race condition
+ in this function. skb may be stolen by
+ another receiver after peek, but before
+ incrementing use count, provided kernel
+ is reentearble (it is not) or this function
+ is called by interrupts.
+
+ Protect it with global skb spinlock,
+ though for now even this is overkill.
+ --ANK (980728)
+ */
+ spin_lock_irqsave(&skb_queue_lock, cpu_flags);
+ skb = skb_peek(&sk->receive_queue);
+ if(skb!=NULL)
+ atomic_inc(&skb->users);
+ spin_unlock_irqrestore(&skb_queue_lock, cpu_flags);
+ } else
+ skb = skb_dequeue(&sk->receive_queue);
+
+ if (!skb) /* Avoid race if someone beats us to the data */
+ goto restart;
+ return skb;
+
+no_packet:
+ *err = error;
+ return NULL;
+}
+
+void skb_free_datagram(struct sock * sk, struct sk_buff *skb)
+{
+ kfree_skb(skb);
+}
+
+/*
+ * Copy a datagram to a linear buffer.
+ */
+
+int skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
+{
+ int err = -EFAULT;
+
+ if (!copy_to_user(to, skb->h.raw + offset, size))
+ err = 0;
+ return err;
+}
+
+
+/*
+ * Copy a datagram to an iovec.
+ * Note: the iovec is modified during the copy.
+ */
+
+int skb_copy_datagram_iovec(struct sk_buff *skb, int offset, struct iovec *to,
+ int size)
+{
+ return memcpy_toiovec(to, skb->h.raw + offset, size);
+}
+
+/*
+ * Datagram poll: Again totally generic. This also handles
+ * sequenced packet sockets providing the socket receive queue
+ * is only ever holding data ready to receive.
+ *
+ * Note: when you _don't_ use this routine for this protocol,
+ * and you use a different write policy from sock_writeable()
+ * then please supply your own write_space callback.
+ */
+
+unsigned int datagram_poll(struct file * file, struct socket *sock, poll_table *wait)
+{
+ struct sock *sk = sock->sk;
+ unsigned int mask;
+
+ poll_wait(file, sk->sleep, wait);
+ mask = 0;
+
+ /* exceptional events? */
+ if (sk->err || !skb_queue_empty(&sk->error_queue))
+ mask |= POLLERR;
+ if (sk->shutdown & RCV_SHUTDOWN)
+ mask |= POLLHUP;
+
+ /* readable? */
+ if (!skb_queue_empty(&sk->receive_queue))
+ mask |= POLLIN | POLLRDNORM;
+
+ /* Connection-based need to check for termination and startup */
+ if (connection_based(sk)) {
+ if (sk->state==TCP_CLOSE)
+ mask |= POLLHUP;
+ /* connection hasn't started yet? */
+ if (sk->state == TCP_SYN_SENT)
+ return mask;
+ }
+
+ /* writable? */
+ if (sock_writeable(sk))
+ mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+ else
+ sk->socket->flags |= SO_NOSPACE;
+
+ return mask;
+}
diff --git a/pfinet/linux-src/net/core/dev.c b/pfinet/linux-src/net/core/dev.c
new file mode 100644
index 00000000..cc9584a1
--- /dev/null
+++ b/pfinet/linux-src/net/core/dev.c
@@ -0,0 +1,2026 @@
+/*
+ * NET3 Protocol independent device support routines.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Derived from the non IP parts of dev.c 1.0.19
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ *
+ * Additional Authors:
+ * Florian la Roche <rzsfl@rz.uni-sb.de>
+ * Alan Cox <gw4pts@gw4pts.ampr.org>
+ * David Hinds <dhinds@allegro.stanford.edu>
+ * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+ * Adam Sulmicki <adam@cfar.umd.edu>
+ *
+ * Changes:
+ * Marcelo Tosatti <marcelo@conectiva.com.br> : dont accept mtu 0 or <
+ * Alan Cox : device private ioctl copies fields back.
+ * Alan Cox : Transmit queue code does relevant stunts to
+ * keep the queue safe.
+ * Alan Cox : Fixed double lock.
+ * Alan Cox : Fixed promisc NULL pointer trap
+ * ???????? : Support the full private ioctl range
+ * Alan Cox : Moved ioctl permission check into drivers
+ * Tim Kordas : SIOCADDMULTI/SIOCDELMULTI
+ * Alan Cox : 100 backlog just doesn't cut it when
+ * you start doing multicast video 8)
+ * Alan Cox : Rewrote net_bh and list manager.
+ * Alan Cox : Fix ETH_P_ALL echoback lengths.
+ * Alan Cox : Took out transmit every packet pass
+ * Saved a few bytes in the ioctl handler
+ * Alan Cox : Network driver sets packet type before calling netif_rx. Saves
+ * a function call a packet.
+ * Alan Cox : Hashed net_bh()
+ * Richard Kooijman: Timestamp fixes.
+ * Alan Cox : Wrong field in SIOCGIFDSTADDR
+ * Alan Cox : Device lock protection.
+ * Alan Cox : Fixed nasty side effect of device close changes.
+ * Rudi Cilibrasi : Pass the right thing to set_mac_address()
+ * Dave Miller : 32bit quantity for the device lock to make it work out
+ * on a Sparc.
+ * Bjorn Ekwall : Added KERNELD hack.
+ * Alan Cox : Cleaned up the backlog initialise.
+ * Craig Metz : SIOCGIFCONF fix if space for under
+ * 1 device.
+ * Thomas Bogendoerfer : Return ENODEV for dev_open, if there
+ * is no device open function.
+ * Andi Kleen : Fix error reporting for SIOCGIFCONF
+ * Michael Chastain : Fix signed/unsigned for SIOCGIFCONF
+ * Cyrus Durgin : Cleaned for KMOD
+ * Adam Sulmicki : Bug Fix : Network Device Unload
+ * A network device unload needs to purge
+ * the backlog queue.
+ * Paul Rusty Russel : SIOCSIFNAME
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/notifier.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/rtnetlink.h>
+#include <net/slhc.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <net/br.h>
+#include <net/dst.h>
+#include <net/pkt_sched.h>
+#include <net/profile.h>
+#include <linux/init.h>
+#include <linux/kmod.h>
+#ifdef CONFIG_NET_RADIO
+#include <linux/wireless.h>
+#endif /* CONFIG_NET_RADIO */
+#ifdef CONFIG_PLIP
+extern int plip_init(void);
+#endif
+
+NET_PROFILE_DEFINE(dev_queue_xmit)
+NET_PROFILE_DEFINE(net_bh)
+NET_PROFILE_DEFINE(net_bh_skb)
+
+
+const char *if_port_text[] = {
+ "unknown",
+ "BNC",
+ "10baseT",
+ "AUI",
+ "100baseT",
+ "100baseTX",
+ "100baseFX"
+};
+
+/*
+ * The list of packet types we will receive (as opposed to discard)
+ * and the routines to invoke.
+ *
+ * Why 16. Because with 16 the only overlap we get on a hash of the
+ * low nibble of the protocol value is RARP/SNAP/X.25.
+ *
+ * 0800 IP
+ * 0001 802.3
+ * 0002 AX.25
+ * 0004 802.2
+ * 8035 RARP
+ * 0005 SNAP
+ * 0805 X.25
+ * 0806 ARP
+ * 8137 IPX
+ * 0009 Localtalk
+ * 86DD IPv6
+ */
+
+struct packet_type *ptype_base[16]; /* 16 way hashed list */
+struct packet_type *ptype_all = NULL; /* Taps */
+
+/*
+ * Device list lock. Setting it provides that interface
+ * will not disappear unexpectedly while kernel sleeps.
+ */
+
+atomic_t dev_lockct = ATOMIC_INIT(0);
+
+/*
+ * Our notifier list
+ */
+
+static struct notifier_block *netdev_chain=NULL;
+
+/*
+ * Device drivers call our routines to queue packets here. We empty the
+ * queue in the bottom half handler.
+ */
+
+static struct sk_buff_head backlog;
+
+#ifdef CONFIG_NET_FASTROUTE
+int netdev_fastroute;
+int netdev_fastroute_obstacles;
+struct net_fastroute_stats dev_fastroute_stat;
+#endif
+
+static void dev_clear_backlog(struct device *dev);
+
+
+/******************************************************************************************
+
+ Protocol management and registration routines
+
+*******************************************************************************************/
+
+/*
+ * For efficiency
+ */
+
+int netdev_nit=0;
+
+/*
+ * Add a protocol ID to the list. Now that the input handler is
+ * smarter we can dispense with all the messy stuff that used to be
+ * here.
+ *
+ * BEWARE!!! Protocol handlers, mangling input packets,
+ * MUST BE last in hash buckets and checking protocol handlers
+ * MUST start from promiscous ptype_all chain in net_bh.
+ * It is true now, do not change it.
+ * Explantion follows: if protocol handler, mangling packet, will
+ * be the first on list, it is not able to sense, that packet
+ * is cloned and should be copied-on-write, so that it will
+ * change it and subsequent readers will get broken packet.
+ * --ANK (980803)
+ */
+
+void dev_add_pack(struct packet_type *pt)
+{
+ int hash;
+#ifdef CONFIG_NET_FASTROUTE
+ /* Hack to detect packet socket */
+ if (pt->data) {
+ netdev_fastroute_obstacles++;
+ dev_clear_fastroute(pt->dev);
+ }
+#endif
+ if(pt->type==htons(ETH_P_ALL))
+ {
+ netdev_nit++;
+ pt->next=ptype_all;
+ ptype_all=pt;
+ }
+ else
+ {
+ hash=ntohs(pt->type)&15;
+ pt->next = ptype_base[hash];
+ ptype_base[hash] = pt;
+ }
+}
+
+
+/*
+ * Remove a protocol ID from the list.
+ */
+
+void dev_remove_pack(struct packet_type *pt)
+{
+ struct packet_type **pt1;
+ if(pt->type==htons(ETH_P_ALL))
+ {
+ netdev_nit--;
+ pt1=&ptype_all;
+ }
+ else
+ pt1=&ptype_base[ntohs(pt->type)&15];
+ for(; (*pt1)!=NULL; pt1=&((*pt1)->next))
+ {
+ if(pt==(*pt1))
+ {
+ *pt1=pt->next;
+ synchronize_bh();
+#ifdef CONFIG_NET_FASTROUTE
+ if (pt->data)
+ netdev_fastroute_obstacles--;
+#endif
+ return;
+ }
+ }
+ printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);
+}
+
+/*****************************************************************************************
+
+ Device Interface Subroutines
+
+******************************************************************************************/
+
+/*
+ * Find an interface by name.
+ */
+
+struct device *dev_get(const char *name)
+{
+ struct device *dev;
+
+ for (dev = dev_base; dev != NULL; dev = dev->next)
+ {
+ if (strcmp(dev->name, name) == 0)
+ return(dev);
+ }
+ return NULL;
+}
+
+struct device * dev_get_by_index(int ifindex)
+{
+ struct device *dev;
+
+ for (dev = dev_base; dev != NULL; dev = dev->next)
+ {
+ if (dev->ifindex == ifindex)
+ return(dev);
+ }
+ return NULL;
+}
+
+struct device *dev_getbyhwaddr(unsigned short type, char *ha)
+{
+ struct device *dev;
+
+ for (dev = dev_base; dev != NULL; dev = dev->next)
+ {
+ if (dev->type == type &&
+ memcmp(dev->dev_addr, ha, dev->addr_len) == 0)
+ return(dev);
+ }
+ return(NULL);
+}
+
+/*
+ * Passed a format string - eg "lt%d" it will try and find a suitable
+ * id. Not efficient for many devices, not called a lot..
+ */
+
+int dev_alloc_name(struct device *dev, const char *name)
+{
+ int i;
+ /*
+ * If you need over 100 please also fix the algorithm...
+ */
+ for(i=0;i<100;i++)
+ {
+ sprintf(dev->name,name,i);
+ if(dev_get(dev->name)==NULL)
+ return i;
+ }
+ return -ENFILE; /* Over 100 of the things .. bail out! */
+}
+
+struct device *dev_alloc(const char *name, int *err)
+{
+ struct device *dev=kmalloc(sizeof(struct device)+16, GFP_KERNEL);
+ if(dev==NULL)
+ {
+ *err=-ENOBUFS;
+ return NULL;
+ }
+ dev->name=(char *)(dev+1); /* Name string space */
+ *err=dev_alloc_name(dev,name);
+ if(*err<0)
+ {
+ kfree(dev);
+ return NULL;
+ }
+ return dev;
+}
+
+void netdev_state_change(struct device *dev)
+{
+ if (dev->flags&IFF_UP)
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+}
+
+
+/*
+ * Find and possibly load an interface.
+ */
+
+#ifdef CONFIG_KMOD
+
+void dev_load(const char *name)
+{
+ if(!dev_get(name) && capable(CAP_SYS_MODULE))
+ request_module(name);
+}
+
+#else
+
+extern inline void dev_load(const char *unused){;}
+
+#endif
+
+static int default_rebuild_header(struct sk_buff *skb)
+{
+ printk(KERN_DEBUG "%s: default_rebuild_header called -- BUG!\n", skb->dev ? skb->dev->name : "NULL!!!");
+ kfree_skb(skb);
+ return 1;
+}
+
+/*
+ * Prepare an interface for use.
+ */
+
+int dev_open(struct device *dev)
+{
+ int ret = 0;
+
+ /*
+ * Is it already up?
+ */
+
+ if (dev->flags&IFF_UP)
+ return 0;
+
+ /*
+ * Call device private open method
+ */
+
+ if (dev->open)
+ ret = dev->open(dev);
+
+ /*
+ * If it went open OK then:
+ */
+
+ if (ret == 0)
+ {
+ /*
+ * nil rebuild_header routine,
+ * that should be never called and used as just bug trap.
+ */
+
+ if (dev->rebuild_header == NULL)
+ dev->rebuild_header = default_rebuild_header;
+
+ /*
+ * Set the flags.
+ */
+ dev->flags |= (IFF_UP | IFF_RUNNING);
+
+ /*
+ * Initialize multicasting status
+ */
+ dev_mc_upload(dev);
+
+ /*
+ * Wakeup transmit queue engine
+ */
+ dev_activate(dev);
+
+ /*
+ * ... and announce new interface.
+ */
+ notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
+
+ }
+ return(ret);
+}
+
+#ifdef CONFIG_NET_FASTROUTE
+
+static __inline__ void dev_do_clear_fastroute(struct device *dev)
+{
+ if (dev->accept_fastpath) {
+ int i;
+
+ for (i=0; i<=NETDEV_FASTROUTE_HMASK; i++)
+ dst_release_irqwait(xchg(dev->fastpath+i, NULL));
+ }
+}
+
+void dev_clear_fastroute(struct device *dev)
+{
+ if (dev) {
+ dev_do_clear_fastroute(dev);
+ } else {
+ for (dev = dev_base; dev; dev = dev->next)
+ dev_do_clear_fastroute(dev);
+ }
+}
+#endif
+
+/*
+ * Completely shutdown an interface.
+ */
+
+int dev_close(struct device *dev)
+{
+ if (!(dev->flags&IFF_UP))
+ return 0;
+
+ dev_deactivate(dev);
+
+ dev_lock_wait();
+
+ /*
+ * Call the device specific close. This cannot fail.
+ * Only if device is UP
+ */
+
+ if (dev->stop)
+ dev->stop(dev);
+
+ if (dev->start)
+ printk("dev_close: bug %s still running\n", dev->name);
+
+ /*
+ * Device is now down.
+ */
+ dev_clear_backlog(dev);
+
+ dev->flags&=~(IFF_UP|IFF_RUNNING);
+#ifdef CONFIG_NET_FASTROUTE
+ dev_clear_fastroute(dev);
+#endif
+
+ /*
+ * Tell people we are going down
+ */
+ notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
+
+ return(0);
+}
+
+
+/*
+ * Device change register/unregister. These are not inline or static
+ * as we export them to the world.
+ */
+
+int register_netdevice_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_register(&netdev_chain, nb);
+}
+
+int unregister_netdevice_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_unregister(&netdev_chain,nb);
+}
+
+/*
+ * Support routine. Sends outgoing frames to any network
+ * taps currently in use.
+ */
+
+void dev_queue_xmit_nit(struct sk_buff *skb, struct device *dev)
+{
+ struct packet_type *ptype;
+ get_fast_time(&skb->stamp);
+
+ for (ptype = ptype_all; ptype!=NULL; ptype = ptype->next)
+ {
+ /* Never send packets back to the socket
+ * they originated from - MvS (miquels@drinkel.ow.org)
+ */
+ if ((ptype->dev == dev || !ptype->dev) &&
+ ((struct sock *)ptype->data != skb->sk))
+ {
+ struct sk_buff *skb2;
+ if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
+ break;
+
+ /* Code, following below is wrong.
+
+ The only reason, why it does work is that
+ ONLY packet sockets receive outgoing
+ packets. If such a packet will be (occasionally)
+ received by normal packet handler, which expects
+ that mac header is pulled...
+ */
+
+ /* More sensible variant. skb->nh should be correctly
+ set by sender, so that the second statement is
+ just protection against buggy protocols.
+ */
+ skb2->mac.raw = skb2->data;
+
+ if (skb2->nh.raw < skb2->data || skb2->nh.raw >= skb2->tail) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "protocol %04x is buggy, dev %s\n", skb2->protocol, dev->name);
+ skb2->nh.raw = skb2->data;
+ if (dev->hard_header)
+ skb2->nh.raw += dev->hard_header_len;
+ }
+
+ skb2->h.raw = skb2->nh.raw;
+ skb2->pkt_type = PACKET_OUTGOING;
+ ptype->func(skb2, skb->dev, ptype);
+ }
+ }
+}
+
+/*
+ * Fast path for loopback frames.
+ */
+
+void dev_loopback_xmit(struct sk_buff *skb)
+{
+ struct sk_buff *newskb=skb_clone(skb, GFP_ATOMIC);
+ if (newskb==NULL)
+ return;
+
+ newskb->mac.raw = newskb->data;
+ skb_pull(newskb, newskb->nh.raw - newskb->data);
+ newskb->pkt_type = PACKET_LOOPBACK;
+ newskb->ip_summed = CHECKSUM_UNNECESSARY;
+ if (newskb->dst==NULL)
+ printk(KERN_DEBUG "BUG: packet without dst looped back 1\n");
+ netif_rx(newskb);
+}
+
+int dev_queue_xmit(struct sk_buff *skb)
+{
+ struct device *dev = skb->dev;
+ struct Qdisc *q;
+
+#ifdef CONFIG_NET_PROFILE
+ start_bh_atomic();
+ NET_PROFILE_ENTER(dev_queue_xmit);
+#endif
+
+ start_bh_atomic();
+ q = dev->qdisc;
+ if (q->enqueue) {
+ q->enqueue(skb, q);
+ qdisc_wakeup(dev);
+ end_bh_atomic();
+
+#ifdef CONFIG_NET_PROFILE
+ NET_PROFILE_LEAVE(dev_queue_xmit);
+ end_bh_atomic();
+#endif
+
+ return 0;
+ }
+
+ /* The device has no queue. Common case for software devices:
+ loopback, all the sorts of tunnels...
+
+ Really, it is unlikely that bh protection is necessary here:
+ virtual devices do not generate EOI events.
+ However, it is possible, that they rely on bh protection
+ made by us here.
+ */
+ if (dev->flags&IFF_UP) {
+ if (netdev_nit)
+ dev_queue_xmit_nit(skb,dev);
+ if (dev->hard_start_xmit(skb, dev) == 0) {
+ end_bh_atomic();
+
+#ifdef CONFIG_NET_PROFILE
+ NET_PROFILE_LEAVE(dev_queue_xmit);
+ end_bh_atomic();
+#endif
+
+ return 0;
+ }
+ if (net_ratelimit())
+ printk(KERN_DEBUG "Virtual device %s asks to queue packet!\n", dev->name);
+ }
+ end_bh_atomic();
+
+ kfree_skb(skb);
+
+#ifdef CONFIG_NET_PROFILE
+ NET_PROFILE_LEAVE(dev_queue_xmit);
+ end_bh_atomic();
+#endif
+
+ return 0;
+}
+
+
+/*=======================================================================
+ Receiver rotutines
+ =======================================================================*/
+
+int netdev_dropping = 0;
+int netdev_max_backlog = 300;
+atomic_t netdev_rx_dropped;
+#ifdef CONFIG_CPU_IS_SLOW
+int net_cpu_congestion;
+#endif
+
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+int netdev_throttle_events;
+static unsigned long netdev_fc_mask = 1;
+unsigned long netdev_fc_xoff = 0;
+
+static struct
+{
+ void (*stimul)(struct device *);
+ struct device *dev;
+} netdev_fc_slots[32];
+
+int netdev_register_fc(struct device *dev, void (*stimul)(struct device *dev))
+{
+ int bit = 0;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ if (netdev_fc_mask != ~0UL) {
+ bit = ffz(netdev_fc_mask);
+ netdev_fc_slots[bit].stimul = stimul;
+ netdev_fc_slots[bit].dev = dev;
+ set_bit(bit, &netdev_fc_mask);
+ clear_bit(bit, &netdev_fc_xoff);
+ }
+ restore_flags(flags);
+ return bit;
+}
+
+void netdev_unregister_fc(int bit)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ if (bit > 0) {
+ netdev_fc_slots[bit].stimul = NULL;
+ netdev_fc_slots[bit].dev = NULL;
+ clear_bit(bit, &netdev_fc_mask);
+ clear_bit(bit, &netdev_fc_xoff);
+ }
+ restore_flags(flags);
+}
+
+static void netdev_wakeup(void)
+{
+ unsigned long xoff;
+
+ cli();
+ xoff = netdev_fc_xoff;
+ netdev_fc_xoff = 0;
+ netdev_dropping = 0;
+ netdev_throttle_events++;
+ while (xoff) {
+ int i = ffz(~xoff);
+ xoff &= ~(1<<i);
+ netdev_fc_slots[i].stimul(netdev_fc_slots[i].dev);
+ }
+ sti();
+}
+#endif
+
+static void dev_clear_backlog(struct device *dev)
+{
+ struct sk_buff *prev, *curr;
+
+ /*
+ *
+ * Let now clear backlog queue. -AS
+ *
+ * We are competing here both with netif_rx() and net_bh().
+ * We don't want either of those to mess with skb ptrs
+ * while we work on them, thus cli()/sti().
+ *
+ * It looks better to use net_bh trick, at least
+ * to be sure, that we keep interrupt latency really low. --ANK (980727)
+ */
+
+ if (backlog.qlen) {
+ start_bh_atomic();
+ curr = backlog.next;
+ while ( curr != (struct sk_buff *)(&backlog) ) {
+ unsigned long flags;
+ curr=curr->next;
+ if ( curr->prev->dev == dev ) {
+ prev = curr->prev;
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ __skb_unlink(prev, &backlog);
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
+ kfree_skb(prev);
+ }
+ }
+ end_bh_atomic();
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+ if (netdev_dropping)
+ netdev_wakeup();
+#else
+ netdev_dropping = 0;
+#endif
+ }
+}
+
+/*
+ * Receive a packet from a device driver and queue it for the upper
+ * (protocol) levels. It always succeeds.
+ */
+
+void netif_rx(struct sk_buff *skb)
+{
+#ifndef CONFIG_CPU_IS_SLOW
+ if(skb->stamp.tv_sec==0)
+ get_fast_time(&skb->stamp);
+#else
+ skb->stamp = xtime;
+#endif
+
+ /* The code is rearranged so that the path is the most
+ short when CPU is congested, but is still operating.
+ */
+
+ if (backlog.qlen <= netdev_max_backlog) {
+ if (backlog.qlen) {
+ if (netdev_dropping == 0) {
+ skb_queue_tail(&backlog,skb);
+ mark_bh(NET_BH);
+ return;
+ }
+ atomic_inc(&netdev_rx_dropped);
+ kfree_skb(skb);
+ return;
+ }
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+ if (netdev_dropping)
+ netdev_wakeup();
+#else
+ netdev_dropping = 0;
+#endif
+ skb_queue_tail(&backlog,skb);
+ mark_bh(NET_BH);
+ return;
+ }
+ netdev_dropping = 1;
+ atomic_inc(&netdev_rx_dropped);
+ kfree_skb(skb);
+}
+
+#ifdef CONFIG_BRIDGE
+static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
+{
+ if (br_stats.flags & BR_UP && br_protocol_ok(ntohs(type)))
+ {
+ /*
+ * We pass the bridge a complete frame. This means
+ * recovering the MAC header first.
+ */
+
+ int offset;
+
+ skb=skb_clone(skb, GFP_ATOMIC);
+ if(skb==NULL)
+ return;
+
+ offset=skb->data-skb->mac.raw;
+ skb_push(skb,offset); /* Put header back on for bridge */
+
+ if(br_receive_frame(skb))
+ return;
+ kfree_skb(skb);
+ }
+ return;
+}
+#endif
+
+
+/*
+ * When we are called the queue is ready to grab, the interrupts are
+ * on and hardware can interrupt and queue to the receive queue as we
+ * run with no problems.
+ * This is run as a bottom half after an interrupt handler that does
+ * mark_bh(NET_BH);
+ */
+
+void net_bh(void)
+{
+ struct packet_type *ptype;
+ struct packet_type *pt_prev;
+ unsigned short type;
+ unsigned long start_time = jiffies;
+#ifdef CONFIG_CPU_IS_SLOW
+ static unsigned long start_busy = 0;
+ static unsigned long ave_busy = 0;
+
+ if (start_busy == 0)
+ start_busy = start_time;
+ net_cpu_congestion = ave_busy>>8;
+#endif
+
+ NET_PROFILE_ENTER(net_bh);
+ /*
+ * Can we send anything now? We want to clear the
+ * decks for any more sends that get done as we
+ * process the input. This also minimises the
+ * latency on a transmit interrupt bh.
+ */
+
+ if (qdisc_head.forw != &qdisc_head)
+ qdisc_run_queues();
+
+ /*
+ * Any data left to process. This may occur because a
+ * mark_bh() is done after we empty the queue including
+ * that from the device which does a mark_bh() just after
+ */
+
+ /*
+ * While the queue is not empty..
+ *
+ * Note that the queue never shrinks due to
+ * an interrupt, so we can do this test without
+ * disabling interrupts.
+ */
+
+ while (!skb_queue_empty(&backlog))
+ {
+ struct sk_buff * skb;
+
+ /* Give chance to other bottom halves to run */
+ if (jiffies - start_time > 1)
+ goto net_bh_break;
+
+ /*
+ * We have a packet. Therefore the queue has shrunk
+ */
+ skb = skb_dequeue(&backlog);
+
+#ifdef CONFIG_CPU_IS_SLOW
+ if (ave_busy > 128*16) {
+ kfree_skb(skb);
+ while ((skb = skb_dequeue(&backlog)) != NULL)
+ kfree_skb(skb);
+ break;
+ }
+#endif
+
+
+#if 0
+ NET_PROFILE_SKB_PASSED(skb, net_bh_skb);
+#endif
+#ifdef CONFIG_NET_FASTROUTE
+ if (skb->pkt_type == PACKET_FASTROUTE) {
+ dev_queue_xmit(skb);
+ continue;
+ }
+#endif
+
+ /*
+ * Bump the pointer to the next structure.
+ *
+ * On entry to the protocol layer. skb->data and
+ * skb->nh.raw point to the MAC and encapsulated data
+ */
+
+ /* XXX until we figure out every place to modify.. */
+ skb->h.raw = skb->nh.raw = skb->data;
+
+ if (skb->mac.raw < skb->head || skb->mac.raw > skb->data) {
+ printk(KERN_CRIT "%s: wrong mac.raw ptr, proto=%04x\n", skb->dev->name, skb->protocol);
+ kfree_skb(skb);
+ continue;
+ }
+
+ /*
+ * Fetch the packet protocol ID.
+ */
+
+ type = skb->protocol;
+
+#ifdef CONFIG_BRIDGE
+ /*
+ * If we are bridging then pass the frame up to the
+ * bridging code (if this protocol is to be bridged).
+ * If it is bridged then move on
+ */
+ handle_bridge(skb, type);
+#endif
+
+ /*
+ * We got a packet ID. Now loop over the "known protocols"
+ * list. There are two lists. The ptype_all list of taps (normally empty)
+ * and the main protocol list which is hashed perfectly for normal protocols.
+ */
+
+ pt_prev = NULL;
+ for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)
+ {
+ if (!ptype->dev || ptype->dev == skb->dev) {
+ if(pt_prev)
+ {
+ struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
+ if(skb2)
+ pt_prev->func(skb2,skb->dev, pt_prev);
+ }
+ pt_prev=ptype;
+ }
+ }
+
+ for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)
+ {
+ if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
+ {
+ /*
+ * We already have a match queued. Deliver
+ * to it and then remember the new match
+ */
+ if(pt_prev)
+ {
+ struct sk_buff *skb2;
+
+ skb2=skb_clone(skb, GFP_ATOMIC);
+
+ /*
+ * Kick the protocol handler. This should be fast
+ * and efficient code.
+ */
+
+ if(skb2)
+ pt_prev->func(skb2, skb->dev, pt_prev);
+ }
+ /* Remember the current last to do */
+ pt_prev=ptype;
+ }
+ } /* End of protocol list loop */
+
+ /*
+ * Is there a last item to send to ?
+ */
+
+ if(pt_prev)
+ pt_prev->func(skb, skb->dev, pt_prev);
+ /*
+ * Has an unknown packet has been received ?
+ */
+
+ else {
+ kfree_skb(skb);
+ }
+ } /* End of queue loop */
+
+ /*
+ * We have emptied the queue
+ */
+
+ /*
+ * One last output flush.
+ */
+
+ if (qdisc_head.forw != &qdisc_head)
+ qdisc_run_queues();
+
+#ifdef CONFIG_CPU_IS_SLOW
+ if (1) {
+ unsigned long start_idle = jiffies;
+ ave_busy += ((start_idle - start_busy)<<3) - (ave_busy>>4);
+ start_busy = 0;
+ }
+#endif
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+ if (netdev_dropping)
+ netdev_wakeup();
+#else
+ netdev_dropping = 0;
+#endif
+ NET_PROFILE_LEAVE(net_bh);
+ return;
+
+net_bh_break:
+ mark_bh(NET_BH);
+ NET_PROFILE_LEAVE(net_bh);
+ return;
+}
+
+/* Protocol dependent address dumping routines */
+
+static gifconf_func_t * gifconf_list [NPROTO];
+
+int register_gifconf(unsigned int family, gifconf_func_t * gifconf)
+{
+ if (family>=NPROTO)
+ return -EINVAL;
+ gifconf_list[family] = gifconf;
+ return 0;
+}
+
+
+/*
+ * Map an interface index to its name (SIOCGIFNAME)
+ */
+
+/*
+ * This call is useful, but I'd remove it too.
+ *
+ * The reason is purely aestetical, it is the only call
+ * from SIOC* family using struct ifreq in reversed manner.
+ * Besides that, it is pretty silly to put "drawing" facility
+ * to kernel, it is useful only to print ifindices
+ * in readable form, is not it? --ANK
+ *
+ * We need this ioctl for efficient implementation of the
+ * if_indextoname() function required by the IPv6 API. Without
+ * it, we would have to search all the interfaces to find a
+ * match. --pb
+ */
+
+static int dev_ifname(struct ifreq *arg)
+{
+ struct device *dev;
+ struct ifreq ifr;
+ int err;
+
+ /*
+ * Fetch the caller's info block.
+ */
+
+ err = copy_from_user(&ifr, arg, sizeof(struct ifreq));
+ if (err)
+ return -EFAULT;
+
+ dev = dev_get_by_index(ifr.ifr_ifindex);
+ if (!dev)
+ return -ENODEV;
+
+ strcpy(ifr.ifr_name, dev->name);
+
+ err = copy_to_user(arg, &ifr, sizeof(struct ifreq));
+ return (err)?-EFAULT:0;
+}
+
+/*
+ * Perform a SIOCGIFCONF call. This structure will change
+ * size eventually, and there is nothing I can do about it.
+ * Thus we will need a 'compatibility mode'.
+ */
+
+static int dev_ifconf(char *arg)
+{
+ struct ifconf ifc;
+ struct device *dev;
+ char *pos;
+ int len;
+ int total;
+ int i;
+
+ /*
+ * Fetch the caller's info block.
+ */
+
+ if (copy_from_user(&ifc, arg, sizeof(struct ifconf)))
+ return -EFAULT;
+
+ pos = ifc.ifc_buf;
+ len = ifc.ifc_len;
+
+ /*
+ * Loop over the interfaces, and write an info block for each.
+ */
+
+ total = 0;
+ for (dev = dev_base; dev != NULL; dev = dev->next) {
+ for (i=0; i<NPROTO; i++) {
+ if (gifconf_list[i]) {
+ int done;
+ if (pos==NULL) {
+ done = gifconf_list[i](dev, NULL, 0);
+ } else {
+ done = gifconf_list[i](dev, pos+total, len-total);
+ }
+ if (done<0)
+ return -EFAULT;
+ total += done;
+ }
+ }
+ }
+
+ /*
+ * All done. Write the updated control block back to the caller.
+ */
+ ifc.ifc_len = total;
+
+ if (copy_to_user(arg, &ifc, sizeof(struct ifconf)))
+ return -EFAULT;
+
+ /*
+ * Both BSD and Solaris return 0 here, so we do too.
+ */
+ return 0;
+}
+
+/*
+ * This is invoked by the /proc filesystem handler to display a device
+ * in detail.
+ */
+
+#ifdef CONFIG_PROC_FS
+static int sprintf_stats(char *buffer, struct device *dev)
+{
+ struct net_device_stats *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
+ int size;
+
+ if (stats)
+ size = sprintf(buffer, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu %8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
+ dev->name,
+ stats->rx_bytes,
+ stats->rx_packets, stats->rx_errors,
+ stats->rx_dropped + stats->rx_missed_errors,
+ stats->rx_fifo_errors,
+ stats->rx_length_errors + stats->rx_over_errors
+ + stats->rx_crc_errors + stats->rx_frame_errors,
+ stats->rx_compressed, stats->multicast,
+ stats->tx_bytes,
+ stats->tx_packets, stats->tx_errors, stats->tx_dropped,
+ stats->tx_fifo_errors, stats->collisions,
+ stats->tx_carrier_errors + stats->tx_aborted_errors
+ + stats->tx_window_errors + stats->tx_heartbeat_errors,
+ stats->tx_compressed);
+ else
+ size = sprintf(buffer, "%6s: No statistics available.\n", dev->name);
+
+ return size;
+}
+
+/*
+ * Called from the PROCfs module. This now uses the new arbitrary sized /proc/net interface
+ * to create /proc/net/dev
+ */
+
+int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len=0;
+ off_t begin=0;
+ off_t pos=0;
+ int size;
+
+ struct device *dev;
+
+
+ size = sprintf(buffer,
+ "Inter-| Receive | Transmit\n"
+ " face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n");
+
+ pos+=size;
+ len+=size;
+
+
+ for (dev = dev_base; dev != NULL; dev = dev->next)
+ {
+ size = sprintf_stats(buffer+len, dev);
+ len+=size;
+ pos=begin+len;
+
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ break;
+ }
+
+ *start=buffer+(offset-begin); /* Start of wanted data */
+ len-=(offset-begin); /* Start slop */
+ if(len>length)
+ len=length; /* Ending slop */
+ return len;
+}
+
+static int dev_proc_stats(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+{
+ int len;
+
+ len = sprintf(buffer, "%08x %08x %08x %08x %08x\n",
+ atomic_read(&netdev_rx_dropped),
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+ netdev_throttle_events,
+#else
+ 0,
+#endif
+#ifdef CONFIG_NET_FASTROUTE
+ dev_fastroute_stat.hits,
+ dev_fastroute_stat.succeed,
+ dev_fastroute_stat.deferred
+#else
+ 0, 0, 0
+#endif
+ );
+
+ len -= offset;
+
+ if (len > length)
+ len = length;
+ if(len < 0)
+ len = 0;
+
+ *start = buffer + offset;
+ *eof = 1;
+
+ return len;
+}
+
+#endif /* CONFIG_PROC_FS */
+
+
+#ifdef CONFIG_NET_RADIO
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Print one entry of /proc/net/wireless
+ * This is a clone of /proc/net/dev (just above)
+ */
+static int sprintf_wireless_stats(char *buffer, struct device *dev)
+{
+ /* Get stats from the driver */
+ struct iw_statistics *stats = (dev->get_wireless_stats ?
+ dev->get_wireless_stats(dev) :
+ (struct iw_statistics *) NULL);
+ int size;
+
+ if(stats != (struct iw_statistics *) NULL)
+ size = sprintf(buffer,
+ "%6s: %02x %3d%c %3d%c %3d%c %5d %5d %5d\n",
+ dev->name,
+ stats->status,
+ stats->qual.qual,
+ stats->qual.updated & 1 ? '.' : ' ',
+ stats->qual.level,
+ stats->qual.updated & 2 ? '.' : ' ',
+ stats->qual.noise,
+ stats->qual.updated & 3 ? '.' : ' ',
+ stats->discard.nwid,
+ stats->discard.code,
+ stats->discard.misc);
+ else
+ size = 0;
+
+ return size;
+}
+
+/*
+ * Print info for /proc/net/wireless (print all entries)
+ * This is a clone of /proc/net/dev (just above)
+ */
+int dev_get_wireless_info(char * buffer, char **start, off_t offset,
+ int length, int dummy)
+{
+ int len = 0;
+ off_t begin = 0;
+ off_t pos = 0;
+ int size;
+
+ struct device * dev;
+
+ size = sprintf(buffer,
+ "Inter-|sta| Quality | Discarded packets\n"
+ " face |tus|link level noise| nwid crypt misc\n");
+
+ pos+=size;
+ len+=size;
+
+ for(dev = dev_base; dev != NULL; dev = dev->next)
+ {
+ size = sprintf_wireless_stats(buffer+len, dev);
+ len+=size;
+ pos=begin+len;
+
+ if(pos < offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos > offset + length)
+ break;
+ }
+
+ *start = buffer + (offset - begin); /* Start of wanted data */
+ len -= (offset - begin); /* Start slop */
+ if(len > length)
+ len = length; /* Ending slop */
+
+ return len;
+}
+#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_NET_RADIO */
+
+void dev_set_promiscuity(struct device *dev, int inc)
+{
+ unsigned short old_flags = dev->flags;
+
+ dev->flags |= IFF_PROMISC;
+ if ((dev->promiscuity += inc) == 0)
+ dev->flags &= ~IFF_PROMISC;
+ if (dev->flags^old_flags) {
+#ifdef CONFIG_NET_FASTROUTE
+ if (dev->flags&IFF_PROMISC) {
+ netdev_fastroute_obstacles++;
+ dev_clear_fastroute(dev);
+ } else
+ netdev_fastroute_obstacles--;
+#endif
+ dev_mc_upload(dev);
+ printk(KERN_INFO "device %s %s promiscuous mode\n",
+ dev->name, (dev->flags&IFF_PROMISC) ? "entered" : "left");
+ }
+}
+
+void dev_set_allmulti(struct device *dev, int inc)
+{
+ unsigned short old_flags = dev->flags;
+
+ dev->flags |= IFF_ALLMULTI;
+ if ((dev->allmulti += inc) == 0)
+ dev->flags &= ~IFF_ALLMULTI;
+ if (dev->flags^old_flags)
+ dev_mc_upload(dev);
+}
+
+int dev_change_flags(struct device *dev, unsigned flags)
+{
+ int ret;
+ int old_flags = dev->flags;
+
+ /*
+ * Set the flags on our device.
+ */
+
+ dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_RUNNING|IFF_NOARP|
+ IFF_SLAVE|IFF_MASTER|IFF_DYNAMIC|
+ IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) |
+ (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI));
+
+ /*
+ * Load in the correct multicast list now the flags have changed.
+ */
+
+ dev_mc_upload(dev);
+
+ /*
+ * Have we downed the interface. We handle IFF_UP ourselves
+ * according to user attempts to set it, rather than blindly
+ * setting it.
+ */
+
+ ret = 0;
+ if ((old_flags^flags)&IFF_UP) /* Bit is different ? */
+ {
+ ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
+
+ if (ret == 0)
+ dev_mc_upload(dev);
+ }
+
+ if (dev->flags&IFF_UP &&
+ ((old_flags^dev->flags)&~(IFF_UP|IFF_RUNNING|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE)))
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+
+ if ((flags^dev->gflags)&IFF_PROMISC) {
+ int inc = (flags&IFF_PROMISC) ? +1 : -1;
+ dev->gflags ^= IFF_PROMISC;
+ dev_set_promiscuity(dev, inc);
+ }
+
+ /* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI
+ is important. Some (broken) drivers set IFF_PROMISC, when
+ IFF_ALLMULTI is requested not asking us and not reporting.
+ */
+ if ((flags^dev->gflags)&IFF_ALLMULTI) {
+ int inc = (flags&IFF_ALLMULTI) ? +1 : -1;
+ dev->gflags ^= IFF_ALLMULTI;
+ dev_set_allmulti(dev, inc);
+ }
+
+ return ret;
+}
+
+/*
+ * Perform the SIOCxIFxxx calls.
+ */
+
+static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
+{
+ struct device *dev;
+ int err;
+
+ if ((dev = dev_get(ifr->ifr_name)) == NULL)
+ return -ENODEV;
+
+ switch(cmd)
+ {
+ case SIOCGIFFLAGS: /* Get interface flags */
+ ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
+ |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
+ return 0;
+
+ case SIOCSIFFLAGS: /* Set interface flags */
+ return dev_change_flags(dev, ifr->ifr_flags);
+
+ case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */
+ ifr->ifr_metric = 0;
+ return 0;
+
+ case SIOCSIFMETRIC: /* Set the metric on the interface (currently unused) */
+ return -EOPNOTSUPP;
+
+ case SIOCGIFMTU: /* Get the MTU of a device */
+ ifr->ifr_mtu = dev->mtu;
+ return 0;
+
+ case SIOCSIFMTU: /* Set the MTU of a device */
+ if (ifr->ifr_mtu == dev->mtu)
+ return 0;
+
+ /*
+ * MTU must be positive.
+ */
+
+ if (ifr->ifr_mtu<=0)
+ return -EINVAL;
+
+ if (dev->change_mtu)
+ err = dev->change_mtu(dev, ifr->ifr_mtu);
+ else {
+ dev->mtu = ifr->ifr_mtu;
+ err = 0;
+ }
+ if (!err && dev->flags&IFF_UP)
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGEMTU, dev);
+ return err;
+
+ case SIOCGIFHWADDR:
+ memcpy(ifr->ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN);
+ ifr->ifr_hwaddr.sa_family=dev->type;
+ return 0;
+
+ case SIOCSIFHWADDR:
+ if(dev->set_mac_address==NULL)
+ return -EOPNOTSUPP;
+ if(ifr->ifr_hwaddr.sa_family!=dev->type)
+ return -EINVAL;
+ err=dev->set_mac_address(dev,&ifr->ifr_hwaddr);
+ if (!err)
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+ return err;
+
+ case SIOCSIFHWBROADCAST:
+ if(ifr->ifr_hwaddr.sa_family!=dev->type)
+ return -EINVAL;
+ memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, MAX_ADDR_LEN);
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+ return 0;
+
+ case SIOCGIFMAP:
+ ifr->ifr_map.mem_start=dev->mem_start;
+ ifr->ifr_map.mem_end=dev->mem_end;
+ ifr->ifr_map.base_addr=dev->base_addr;
+ ifr->ifr_map.irq=dev->irq;
+ ifr->ifr_map.dma=dev->dma;
+ ifr->ifr_map.port=dev->if_port;
+ return 0;
+
+ case SIOCSIFMAP:
+ if (dev->set_config)
+ return dev->set_config(dev,&ifr->ifr_map);
+ return -EOPNOTSUPP;
+
+ case SIOCADDMULTI:
+ if(dev->set_multicast_list==NULL ||
+ ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
+ return -EINVAL;
+ dev_mc_add(dev,ifr->ifr_hwaddr.sa_data, dev->addr_len, 1);
+ return 0;
+
+ case SIOCDELMULTI:
+ if(dev->set_multicast_list==NULL ||
+ ifr->ifr_hwaddr.sa_family!=AF_UNSPEC)
+ return -EINVAL;
+ dev_mc_delete(dev,ifr->ifr_hwaddr.sa_data,dev->addr_len, 1);
+ return 0;
+
+ case SIOCGIFINDEX:
+ ifr->ifr_ifindex = dev->ifindex;
+ return 0;
+
+ case SIOCGIFTXQLEN:
+ ifr->ifr_qlen = dev->tx_queue_len;
+ return 0;
+
+ case SIOCSIFTXQLEN:
+ if(ifr->ifr_qlen<0)
+ return -EINVAL;
+ dev->tx_queue_len = ifr->ifr_qlen;
+ return 0;
+
+ case SIOCSIFNAME:
+ if (dev->flags&IFF_UP)
+ return -EBUSY;
+ if (dev_get(ifr->ifr_newname))
+ return -EEXIST;
+ memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
+ dev->name[IFNAMSIZ-1] = 0;
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
+ return 0;
+
+ /*
+ * Unknown or private ioctl
+ */
+
+ default:
+ if(cmd >= SIOCDEVPRIVATE &&
+ cmd <= SIOCDEVPRIVATE + 15) {
+ if (dev->do_ioctl)
+ return dev->do_ioctl(dev, ifr, cmd);
+ return -EOPNOTSUPP;
+ }
+
+#ifdef CONFIG_NET_RADIO
+ if(cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
+ if (dev->do_ioctl)
+ return dev->do_ioctl(dev, ifr, cmd);
+ return -EOPNOTSUPP;
+ }
+#endif /* CONFIG_NET_RADIO */
+
+ }
+ return -EINVAL;
+}
+
+
+/*
+ * This function handles all "interface"-type I/O control requests. The actual
+ * 'doing' part of this is dev_ifsioc above.
+ */
+
+int dev_ioctl(unsigned int cmd, void *arg)
+{
+ struct ifreq ifr;
+ int ret;
+ char *colon;
+
+ /* One special case: SIOCGIFCONF takes ifconf argument
+ and requires shared lock, because it sleeps writing
+ to user space.
+ */
+
+ if (cmd == SIOCGIFCONF) {
+ rtnl_shlock();
+ ret = dev_ifconf((char *) arg);
+ rtnl_shunlock();
+ return ret;
+ }
+ if (cmd == SIOCGIFNAME) {
+ return dev_ifname((struct ifreq *)arg);
+ }
+
+ if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
+ return -EFAULT;
+
+ ifr.ifr_name[IFNAMSIZ-1] = 0;
+
+ colon = strchr(ifr.ifr_name, ':');
+ if (colon)
+ *colon = 0;
+
+ /*
+ * See which interface the caller is talking about.
+ */
+
+ switch(cmd)
+ {
+ /*
+ * These ioctl calls:
+ * - can be done by all.
+ * - atomic and do not require locking.
+ * - return a value
+ */
+
+ case SIOCGIFFLAGS:
+ case SIOCGIFMETRIC:
+ case SIOCGIFMTU:
+ case SIOCGIFHWADDR:
+ case SIOCGIFSLAVE:
+ case SIOCGIFMAP:
+ case SIOCGIFINDEX:
+ case SIOCGIFTXQLEN:
+ dev_load(ifr.ifr_name);
+ ret = dev_ifsioc(&ifr, cmd);
+ if (!ret) {
+ if (colon)
+ *colon = ':';
+ if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ }
+ return ret;
+
+ /*
+ * These ioctl calls:
+ * - require superuser power.
+ * - require strict serialization.
+ * - do not return a value
+ */
+
+ case SIOCSIFFLAGS:
+ case SIOCSIFMETRIC:
+ case SIOCSIFMTU:
+ case SIOCSIFMAP:
+ case SIOCSIFHWADDR:
+ case SIOCSIFSLAVE:
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ case SIOCSIFHWBROADCAST:
+ case SIOCSIFTXQLEN:
+ case SIOCSIFNAME:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ dev_load(ifr.ifr_name);
+ rtnl_lock();
+ ret = dev_ifsioc(&ifr, cmd);
+ rtnl_unlock();
+ return ret;
+
+ case SIOCGIFMEM:
+ /* Get the per device memory space. We can add this but currently
+ do not support it */
+ case SIOCSIFMEM:
+ /* Set the per device memory buffer space. Not applicable in our case */
+ case SIOCSIFLINK:
+ return -EINVAL;
+
+ /*
+ * Unknown or private ioctl.
+ */
+
+ default:
+ if (cmd >= SIOCDEVPRIVATE &&
+ cmd <= SIOCDEVPRIVATE + 15) {
+ dev_load(ifr.ifr_name);
+ rtnl_lock();
+ ret = dev_ifsioc(&ifr, cmd);
+ rtnl_unlock();
+ if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ return ret;
+ }
+#ifdef CONFIG_NET_RADIO
+ if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
+ dev_load(ifr.ifr_name);
+ if (IW_IS_SET(cmd)) {
+ if (!suser())
+ return -EPERM;
+ rtnl_lock();
+ }
+ ret = dev_ifsioc(&ifr, cmd);
+ if (IW_IS_SET(cmd))
+ rtnl_unlock();
+ if (!ret && IW_IS_GET(cmd) &&
+ copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ return ret;
+ }
+#endif /* CONFIG_NET_RADIO */
+ return -EINVAL;
+ }
+}
+
+int dev_new_index(void)
+{
+ static int ifindex;
+ for (;;) {
+ if (++ifindex <= 0)
+ ifindex=1;
+ if (dev_get_by_index(ifindex) == NULL)
+ return ifindex;
+ }
+}
+
+static int dev_boot_phase = 1;
+
+
+int register_netdevice(struct device *dev)
+{
+ struct device *d, **dp;
+
+ if (dev_boot_phase) {
+ /* This is NOT bug, but I am not sure, that all the
+ devices, initialized before netdev module is started
+ are sane.
+
+ Now they are chained to device boot list
+ and probed later. If a module is initialized
+ before netdev, but assumes that dev->init
+ is really called by register_netdev(), it will fail.
+
+ So that this message should be printed for a while.
+ */
+ printk(KERN_INFO "early initialization of device %s is deferred\n", dev->name);
+
+ /* Check for existence, and append to tail of chain */
+ for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
+ if (d == dev || strcmp(d->name, dev->name) == 0)
+ return -EEXIST;
+ }
+ dev->next = NULL;
+ *dp = dev;
+ return 0;
+ }
+
+ dev->iflink = -1;
+
+ /* Init, if this function is available */
+ if (dev->init && dev->init(dev) != 0)
+ return -EIO;
+
+ /* Check for existence, and append to tail of chain */
+ for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
+ if (d == dev || strcmp(d->name, dev->name) == 0)
+ return -EEXIST;
+ }
+ dev->next = NULL;
+ dev_init_scheduler(dev);
+ dev->ifindex = dev_new_index();
+ if (dev->iflink == -1)
+ dev->iflink = dev->ifindex;
+ *dp = dev;
+
+ /* Notify protocols, that a new device appeared. */
+ notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+
+ return 0;
+}
+
+int unregister_netdevice(struct device *dev)
+{
+ struct device *d, **dp;
+
+ if (dev_boot_phase == 0) {
+ /* If device is running, close it.
+ It is very bad idea, really we should
+ complain loudly here, but random hackery
+ in linux/drivers/net likes it.
+ */
+ if (dev->flags & IFF_UP)
+ dev_close(dev);
+
+#ifdef CONFIG_NET_FASTROUTE
+ dev_clear_fastroute(dev);
+#endif
+
+ /* Shutdown queueing discipline. */
+ dev_shutdown(dev);
+
+ /* Notify protocols, that we are about to destroy
+ this device. They should clean all the things.
+ */
+ notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+
+ /*
+ * Flush the multicast chain
+ */
+ dev_mc_discard(dev);
+
+ /* To avoid pointers looking to nowhere,
+ we wait for end of critical section */
+ dev_lock_wait();
+ }
+
+ /* And unlink it from device chain. */
+ for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {
+ if (d == dev) {
+ *dp = d->next;
+ synchronize_bh();
+ d->next = NULL;
+
+ if (dev->destructor)
+ dev->destructor(dev);
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+
+
+/*
+ * Initialize the DEV module. At boot time this walks the device list and
+ * unhooks any devices that fail to initialise (normally hardware not
+ * present) and leaves us with a valid list of present and active devices.
+ *
+ */
+extern int lance_init(void);
+extern int bpq_init(void);
+extern int scc_init(void);
+extern void sdla_setup(void);
+extern void dlci_setup(void);
+extern int dmascc_init(void);
+extern int sm_init(void);
+
+extern int baycom_ser_fdx_init(void);
+extern int baycom_ser_hdx_init(void);
+extern int baycom_par_init(void);
+
+extern int lapbeth_init(void);
+extern void arcnet_init(void);
+extern void ip_auto_config(void);
+#ifdef CONFIG_8xx
+extern int cpm_enet_init(void);
+#endif /* CONFIG_8xx */
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_dev = {
+ PROC_NET_DEV, 3, "dev",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ dev_get_info
+};
+#endif
+
+#ifdef CONFIG_NET_RADIO
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_wireless = {
+ PROC_NET_WIRELESS, 8, "wireless",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ dev_get_wireless_info
+};
+#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_NET_RADIO */
+
+__initfunc(int net_dev_init(void))
+{
+ struct device *dev, **dp;
+
+#ifdef CONFIG_NET_SCHED
+ pktsched_init();
+#endif
+
+ /*
+ * Initialise the packet receive queue.
+ */
+
+ skb_queue_head_init(&backlog);
+
+ /*
+ * The bridge has to be up before the devices
+ */
+
+#ifdef CONFIG_BRIDGE
+ br_init();
+#endif
+
+ /*
+ * This is Very Ugly(tm).
+ *
+ * Some devices want to be initialized early..
+ */
+
+#if defined(CONFIG_SCC)
+ scc_init();
+#endif
+#if defined(CONFIG_DMASCC)
+ dmascc_init();
+#endif
+#if defined(CONFIG_BPQETHER)
+ bpq_init();
+#endif
+#if defined(CONFIG_DLCI)
+ dlci_setup();
+#endif
+#if defined(CONFIG_SDLA)
+ sdla_setup();
+#endif
+#if defined(CONFIG_BAYCOM_PAR)
+ baycom_par_init();
+#endif
+#if defined(CONFIG_BAYCOM_SER_FDX)
+ baycom_ser_fdx_init();
+#endif
+#if defined(CONFIG_BAYCOM_SER_HDX)
+ baycom_ser_hdx_init();
+#endif
+#if defined(CONFIG_SOUNDMODEM)
+ sm_init();
+#endif
+#if defined(CONFIG_LAPBETHER)
+ lapbeth_init();
+#endif
+#if defined(CONFIG_PLIP)
+ plip_init();
+#endif
+#if defined(CONFIG_ARCNET)
+ arcnet_init();
+#endif
+#if defined(CONFIG_8xx)
+ cpm_enet_init();
+#endif
+ /*
+ * SLHC if present needs attaching so other people see it
+ * even if not opened.
+ */
+
+#ifdef CONFIG_INET
+#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
+ || defined(CONFIG_PPP) \
+ || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
+ slhc_install();
+#endif
+#endif
+
+#ifdef CONFIG_NET_PROFILE
+ net_profile_init();
+ NET_PROFILE_REGISTER(dev_queue_xmit);
+ NET_PROFILE_REGISTER(net_bh);
+#if 0
+ NET_PROFILE_REGISTER(net_bh_skb);
+#endif
+#endif
+ /*
+ * Add the devices.
+ * If the call to dev->init fails, the dev is removed
+ * from the chain disconnecting the device until the
+ * next reboot.
+ */
+
+ dp = &dev_base;
+ while ((dev = *dp) != NULL)
+ {
+ dev->iflink = -1;
+ if (dev->init && dev->init(dev))
+ {
+ /*
+ * It failed to come up. Unhook it.
+ */
+ *dp = dev->next;
+ synchronize_bh();
+ }
+ else
+ {
+ dp = &dev->next;
+ dev->ifindex = dev_new_index();
+ if (dev->iflink == -1)
+ dev->iflink = dev->ifindex;
+ dev_init_scheduler(dev);
+ }
+ }
+
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&proc_net_dev);
+ {
+ struct proc_dir_entry *ent = create_proc_entry("net/dev_stat", 0, 0);
+ ent->read_proc = dev_proc_stats;
+ }
+#endif
+
+#ifdef CONFIG_NET_RADIO
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&proc_net_wireless);
+#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_NET_RADIO */
+
+ init_bh(NET_BH, net_bh);
+
+ dev_boot_phase = 0;
+
+ dev_mcast_init();
+
+#ifdef CONFIG_IP_PNP
+ ip_auto_config();
+#endif
+
+ return 0;
+}
diff --git a/pfinet/linux-src/net/core/dev_mcast.c b/pfinet/linux-src/net/core/dev_mcast.c
new file mode 100644
index 00000000..bce3f4a4
--- /dev/null
+++ b/pfinet/linux-src/net/core/dev_mcast.c
@@ -0,0 +1,252 @@
+/*
+ * Linux NET3: Multicast List maintenance.
+ *
+ * Authors:
+ * Tim Kordas <tjk@nostromo.eeap.cwru.edu>
+ * Richard Underwood <richard@wuzz.demon.co.uk>
+ *
+ * Stir fried together from the IP multicast and CAP patches above
+ * Alan Cox <Alan.Cox@linux.org>
+ *
+ * Fixes:
+ * Alan Cox : Update the device on a real delete
+ * rather than any time but...
+ * Alan Cox : IFF_ALLMULTI support.
+ * Alan Cox : New format set_multicast_list() calls.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/arp.h>
+
+
+/*
+ * Device multicast list maintenance.
+ *
+ * This is used both by IP and by the user level maintenance functions.
+ * Unlike BSD we maintain a usage count on a given multicast address so
+ * that a casual user application can add/delete multicasts used by
+ * protocols without doing damage to the protocols when it deletes the
+ * entries. It also helps IP as it tracks overlapping maps.
+ *
+ * Device mc lists are changed by bh at least if IPv6 is enabled,
+ * so that it must be bh protected.
+ */
+
+/*
+ * Update the multicast list into the physical NIC controller.
+ */
+
+void dev_mc_upload(struct device *dev)
+{
+ /* Don't do anything till we up the interface
+ [dev_open will call this function so the list will
+ stay sane] */
+
+ if(!(dev->flags&IFF_UP))
+ return;
+
+ /*
+ * Devices with no set multicast don't get set
+ */
+
+ if(dev->set_multicast_list==NULL)
+ return;
+
+ start_bh_atomic();
+ dev->set_multicast_list(dev);
+ end_bh_atomic();
+}
+
+/*
+ * Delete a device level multicast
+ */
+
+int dev_mc_delete(struct device *dev, void *addr, int alen, int glbl)
+{
+ int err = 0;
+ struct dev_mc_list *dmi, **dmip;
+
+ start_bh_atomic();
+ for (dmip=&dev->mc_list; (dmi=*dmip)!=NULL; dmip=&dmi->next) {
+ /*
+ * Find the entry we want to delete. The device could
+ * have variable length entries so check these too.
+ */
+ if (memcmp(dmi->dmi_addr,addr,dmi->dmi_addrlen)==0 && alen==dmi->dmi_addrlen) {
+ if (glbl) {
+ int old_glbl = dmi->dmi_gusers;
+ dmi->dmi_gusers = 0;
+ if (old_glbl == 0)
+ break;
+ }
+ if(--dmi->dmi_users)
+ goto done;
+
+ /*
+ * Last user. So delete the entry.
+ */
+ *dmip = dmi->next;
+ dev->mc_count--;
+ kfree_s(dmi,sizeof(*dmi));
+ /*
+ * We have altered the list, so the card
+ * loaded filter is now wrong. Fix it
+ */
+ end_bh_atomic();
+ dev_mc_upload(dev);
+ return 0;
+ }
+ }
+ err = -ENOENT;
+done:
+ end_bh_atomic();
+ return err;
+}
+
+/*
+ * Add a device level multicast
+ */
+
+int dev_mc_add(struct device *dev, void *addr, int alen, int glbl)
+{
+ int err = 0;
+ struct dev_mc_list *dmi, *dmi1;
+
+ dmi1 = (struct dev_mc_list *)kmalloc(sizeof(*dmi), gfp_any());
+
+ start_bh_atomic();
+ for(dmi=dev->mc_list; dmi!=NULL; dmi=dmi->next) {
+ if (memcmp(dmi->dmi_addr,addr,dmi->dmi_addrlen)==0 && dmi->dmi_addrlen==alen) {
+ if (glbl) {
+ int old_glbl = dmi->dmi_gusers;
+ dmi->dmi_gusers = 1;
+ if (old_glbl)
+ goto done;
+ }
+ dmi->dmi_users++;
+ goto done;
+ }
+ }
+
+ if ((dmi=dmi1)==NULL)
+ return -ENOMEM;
+ memcpy(dmi->dmi_addr, addr, alen);
+ dmi->dmi_addrlen=alen;
+ dmi->next=dev->mc_list;
+ dmi->dmi_users=1;
+ dmi->dmi_gusers=glbl ? 1 : 0;
+ dev->mc_list=dmi;
+ dev->mc_count++;
+ end_bh_atomic();
+ dev_mc_upload(dev);
+ return 0;
+
+done:
+ end_bh_atomic();
+ if (dmi1)
+ kfree(dmi1);
+ return err;
+}
+
+/*
+ * Discard multicast list when a device is downed
+ */
+
+void dev_mc_discard(struct device *dev)
+{
+ start_bh_atomic();
+ while (dev->mc_list!=NULL) {
+ struct dev_mc_list *tmp=dev->mc_list;
+ dev->mc_list=tmp->next;
+ if (tmp->dmi_users > tmp->dmi_gusers)
+ printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users);
+ kfree_s(tmp,sizeof(*tmp));
+ }
+ dev->mc_count=0;
+ end_bh_atomic();
+}
+
+#ifdef CONFIG_PROC_FS
+static int dev_mc_read_proc(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+{
+ off_t pos=0, begin=0;
+ struct dev_mc_list *m;
+ int len=0;
+ struct device *dev;
+
+ start_bh_atomic();
+
+ for (dev = dev_base; dev; dev = dev->next) {
+ for (m = dev->mc_list; m; m = m->next) {
+ int i;
+
+ len += sprintf(buffer+len,"%-4d %-15s %-5d %-5d ", dev->ifindex, dev->name,
+ m->dmi_users, m->dmi_gusers);
+
+ for (i=0; i<m->dmi_addrlen; i++)
+ len += sprintf(buffer+len, "%02x", m->dmi_addr[i]);
+
+ len+=sprintf(buffer+len, "\n");
+
+ pos=begin+len;
+ if (pos < offset) {
+ len=0;
+ begin=pos;
+ }
+ if (pos > offset+length)
+ goto done;
+ }
+ }
+ *eof = 1;
+
+done:
+ end_bh_atomic();
+ *start=buffer+(offset-begin);
+ len-=(offset-begin);
+ if(len>length)
+ len=length;
+ if(len<0)
+ len=0;
+ return len;
+}
+#endif
+
+__initfunc(void dev_mcast_init(void))
+{
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *ent;
+
+ ent = create_proc_entry("net/dev_mcast", 0, 0);
+ ent->read_proc = dev_mc_read_proc;
+#endif
+}
+
diff --git a/pfinet/linux-src/net/core/dst.c b/pfinet/linux-src/net/core/dst.c
new file mode 100644
index 00000000..9007dde6
--- /dev/null
+++ b/pfinet/linux-src/net/core/dst.c
@@ -0,0 +1,145 @@
+/*
+ * net/dst.c Protocol independent destination cache.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ */
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+
+#include <net/dst.h>
+
+struct dst_entry * dst_garbage_list;
+atomic_t dst_total = ATOMIC_INIT(0);
+
+static unsigned long dst_gc_timer_expires;
+static unsigned long dst_gc_timer_inc = DST_GC_MAX;
+static void dst_run_gc(unsigned long);
+
+static struct timer_list dst_gc_timer =
+ { NULL, NULL, DST_GC_MIN, 0L, dst_run_gc };
+
+#if RT_CACHE_DEBUG >= 2
+atomic_t hh_count;
+#endif
+
+static void dst_run_gc(unsigned long dummy)
+{
+ int delayed = 0;
+ struct dst_entry * dst, **dstp;
+
+ del_timer(&dst_gc_timer);
+ dstp = &dst_garbage_list;
+ while ((dst = *dstp) != NULL) {
+ if (atomic_read(&dst->use)) {
+ dstp = &dst->next;
+ delayed++;
+ continue;
+ }
+ *dstp = dst->next;
+ dst_destroy(dst);
+ }
+ if (!dst_garbage_list) {
+ dst_gc_timer_inc = DST_GC_MAX;
+ return;
+ }
+ if ((dst_gc_timer_expires += dst_gc_timer_inc) > DST_GC_MAX)
+ dst_gc_timer_expires = DST_GC_MAX;
+ dst_gc_timer_inc += DST_GC_INC;
+ dst_gc_timer.expires = jiffies + dst_gc_timer_expires;
+#if RT_CACHE_DEBUG >= 2
+ printk("dst_total: %d/%d %ld\n",
+ atomic_read(&dst_total), delayed, dst_gc_timer_expires);
+#endif
+ add_timer(&dst_gc_timer);
+}
+
+static int dst_discard(struct sk_buff *skb)
+{
+ kfree_skb(skb);
+ return 0;
+}
+
+static int dst_blackhole(struct sk_buff *skb)
+{
+ kfree_skb(skb);
+ return 0;
+}
+
+void * dst_alloc(int size, struct dst_ops * ops)
+{
+ struct dst_entry * dst;
+
+ if (ops->gc && atomic_read(&ops->entries) > ops->gc_thresh) {
+ if (ops->gc())
+ return NULL;
+ }
+ dst = kmalloc(size, GFP_ATOMIC);
+ if (!dst)
+ return NULL;
+ memset(dst, 0, size);
+ dst->ops = ops;
+ atomic_set(&dst->refcnt, 0);
+ dst->lastuse = jiffies;
+ dst->input = dst_discard;
+ dst->output = dst_blackhole;
+ atomic_inc(&dst_total);
+ atomic_inc(&ops->entries);
+ return dst;
+}
+
+void __dst_free(struct dst_entry * dst)
+{
+ start_bh_atomic();
+ /* The first case (dev==NULL) is required, when
+ protocol module is unloaded.
+ */
+ if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) {
+ dst->input = dst_discard;
+ dst->output = dst_blackhole;
+ dst->dev = &loopback_dev;
+ }
+ dst->obsolete = 2;
+ dst->next = dst_garbage_list;
+ dst_garbage_list = dst;
+ if (dst_gc_timer_inc > DST_GC_INC) {
+ del_timer(&dst_gc_timer);
+ dst_gc_timer_inc = DST_GC_INC;
+ dst_gc_timer_expires = DST_GC_MIN;
+ dst_gc_timer.expires = jiffies + dst_gc_timer_expires;
+ add_timer(&dst_gc_timer);
+ }
+ end_bh_atomic();
+}
+
+void dst_destroy(struct dst_entry * dst)
+{
+ struct neighbour *neigh = dst->neighbour;
+ struct hh_cache *hh = dst->hh;
+
+ dst->hh = NULL;
+ if (hh && atomic_dec_and_test(&hh->hh_refcnt))
+ kfree(hh);
+
+ if (neigh) {
+ dst->neighbour = NULL;
+ neigh_release(neigh);
+ }
+
+ atomic_dec(&dst->ops->entries);
+
+ if (dst->ops->destroy)
+ dst->ops->destroy(dst);
+ atomic_dec(&dst_total);
+ kfree(dst);
+}
diff --git a/pfinet/linux-src/net/core/filter.c b/pfinet/linux-src/net/core/filter.c
new file mode 100644
index 00000000..8e1ffb62
--- /dev/null
+++ b/pfinet/linux-src/net/core/filter.c
@@ -0,0 +1,454 @@
+/*
+ * Linux Socket Filter - Kernel level socket filtering
+ *
+ * Author:
+ * Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ *
+ * Based on the design of:
+ * - The Berkeley Packet Filter
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Andi Kleen - Fix a few bad bugs and races.
+ */
+
+#include <linux/config.h>
+#if defined(CONFIG_FILTER)
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/fcntl.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_packet.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/filter.h>
+
+/* No hurry in this branch */
+
+static u8 *load_pointer(struct sk_buff *skb, int k)
+{
+ u8 *ptr = NULL;
+
+ if (k>=SKF_NET_OFF)
+ ptr = skb->nh.raw + k - SKF_NET_OFF;
+ else if (k>=SKF_LL_OFF)
+ ptr = skb->mac.raw + k - SKF_LL_OFF;
+
+ if (ptr<skb->head && ptr < skb->tail)
+ return ptr;
+ return NULL;
+}
+
+/*
+ * Decode and apply filter instructions to the skb->data.
+ * Return length to keep, 0 for none. skb is the data we are
+ * filtering, filter is the array of filter instructions, and
+ * len is the number of filter blocks in the array.
+ */
+
+int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
+{
+ unsigned char *data = skb->data;
+ /* len is UNSIGNED. Byte wide insns relies only on implicit
+ type casts to prevent reading arbitrary memory locations.
+ */
+ unsigned int len = skb->len;
+ struct sock_filter *fentry; /* We walk down these */
+ u32 A = 0; /* Accumulator */
+ u32 X = 0; /* Index Register */
+ u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */
+ int k;
+ int pc;
+
+ /*
+ * Process array of filter instructions.
+ */
+
+ for(pc = 0; pc < flen; pc++)
+ {
+ fentry = &filter[pc];
+
+ switch(fentry->code)
+ {
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += fentry->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= fentry->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= fentry->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if(X == 0)
+ return (0);
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ if(fentry->k == 0)
+ return (0);
+ A /= fentry->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= fentry->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= fentry->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= fentry->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= fentry->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ A = -A;
+ continue;
+
+ case BPF_JMP|BPF_JA:
+ pc += fentry->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += (A > fentry->k) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += (A >= fentry->k) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += (A == fentry->k) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & fentry->k) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? fentry->jt : fentry->jf;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = fentry->k;
+load_w:
+ if(k+sizeof(u32) <= len) {
+ A = ntohl(*(u32*)&data[k]);
+ continue;
+ }
+ if (k<0) {
+ u8 *ptr;
+
+ if (k>=SKF_AD_OFF)
+ break;
+ if ((ptr = load_pointer(skb, k)) != NULL) {
+ A = ntohl(*(u32*)ptr);
+ continue;
+ }
+ }
+ return 0;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = fentry->k;
+load_h:
+ if(k + sizeof(u16) <= len) {
+ A = ntohs(*(u16*)&data[k]);
+ continue;
+ }
+ if (k<0) {
+ u8 *ptr;
+
+ if (k>=SKF_AD_OFF)
+ break;
+ if ((ptr = load_pointer(skb, k)) != NULL) {
+ A = ntohs(*(u16*)ptr);
+ continue;
+ }
+ }
+ return 0;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = fentry->k;
+load_b:
+ if(k < len) {
+ A = data[k];
+ continue;
+ }
+ if (k<0) {
+ u8 *ptr;
+
+ if (k>=SKF_AD_OFF)
+ break;
+ if ((ptr = load_pointer(skb, k)) != NULL) {
+ A = *ptr;
+ continue;
+ }
+ }
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = len;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = len;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + fentry->k;
+ goto load_w;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + fentry->k;
+ goto load_h;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + fentry->k;
+ goto load_b;
+
+ case BPF_LDX|BPF_B|BPF_MSH:
+ k = fentry->k;
+ if(k >= len)
+ return (0);
+ X = (data[k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = fentry->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = fentry->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[fentry->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[fentry->k];
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+ case BPF_RET|BPF_K:
+ return ((unsigned int)fentry->k);
+
+ case BPF_RET|BPF_A:
+ return ((unsigned int)A);
+
+ case BPF_ST:
+ mem[fentry->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[fentry->k] = X;
+ continue;
+
+ default:
+ /* Invalid instruction counts as RET */
+ return (0);
+ }
+
+ /* Handle ancillary data, which are impossible
+ (or very difficult) to get parsing packet contents.
+ */
+ switch (k-SKF_AD_OFF) {
+ case SKF_AD_PROTOCOL:
+ A = htons(skb->protocol);
+ continue;
+ case SKF_AD_PKTTYPE:
+ A = skb->pkt_type;
+ continue;
+ case SKF_AD_IFINDEX:
+ A = skb->dev->ifindex;
+ continue;
+ default:
+ return 0;
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * Check the user's filter code. If we let some ugly
+ * filter code slip through kaboom!
+ */
+
+int sk_chk_filter(struct sock_filter *filter, int flen)
+{
+ struct sock_filter *ftest;
+ int pc;
+
+ /*
+ * Check the filter code now.
+ */
+ for(pc = 0; pc < flen; pc++)
+ {
+ /*
+ * All jumps are forward as they are not signed
+ */
+
+ ftest = &filter[pc];
+ if(BPF_CLASS(ftest->code) == BPF_JMP)
+ {
+ /*
+ * But they mustn't jump off the end.
+ */
+ if(BPF_OP(ftest->code) == BPF_JA)
+ {
+ /* Note, the large ftest->k might cause
+ loops. Compare this with conditional
+ jumps below, where offsets are limited. --ANK (981016)
+ */
+ if (ftest->k >= (unsigned)(flen-pc-1))
+ return (-EINVAL);
+ }
+ else
+ {
+ /*
+ * For conditionals both must be safe
+ */
+ if(pc + ftest->jt +1 >= flen || pc + ftest->jf +1 >= flen)
+ return (-EINVAL);
+ }
+ }
+
+ /*
+ * Check that memory operations use valid addresses.
+ */
+
+ if (ftest->k >= BPF_MEMWORDS)
+ {
+ /*
+ * But it might not be a memory operation...
+ */
+ switch (ftest->code) {
+ case BPF_ST:
+ case BPF_STX:
+ case BPF_LD|BPF_MEM:
+ case BPF_LDX|BPF_MEM:
+ return -EINVAL;
+ }
+ }
+ }
+
+ /*
+ * The program must end with a return. We don't care where they
+ * jumped within the script (its always forwards) but in the
+ * end they _will_ hit this.
+ */
+
+ return (BPF_CLASS(filter[flen - 1].code) == BPF_RET)?0:-EINVAL;
+}
+
+/*
+ * Attach the user's filter code. We first run some sanity checks on
+ * it to make sure it does not explode on us later.
+ */
+
+int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
+{
+ struct sk_filter *fp;
+ unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
+ int err;
+
+ /* Make sure new filter is there and in the right amounts. */
+ if (fprog->filter == NULL || fprog->len > BPF_MAXINSNS)
+ return (-EINVAL);
+
+ fp = (struct sk_filter *)sock_kmalloc(sk, fsize+sizeof(*fp), GFP_KERNEL);
+ if(fp == NULL)
+ return (-ENOMEM);
+
+ if (copy_from_user(fp->insns, fprog->filter, fsize)) {
+ sock_kfree_s(sk, fp, fsize+sizeof(*fp));
+ return -EFAULT;
+ }
+
+ atomic_set(&fp->refcnt, 1);
+ fp->len = fprog->len;
+
+ if ((err = sk_chk_filter(fp->insns, fp->len))==0) {
+ struct sk_filter *old_fp = sk->filter;
+ sk->filter = fp;
+ synchronize_bh();
+ fp = old_fp;
+ }
+
+ if (fp)
+ sk_filter_release(sk, fp);
+
+ return (err);
+}
+#endif /* CONFIG_FILTER */
diff --git a/pfinet/linux-src/net/core/firewall.c b/pfinet/linux-src/net/core/firewall.c
new file mode 100644
index 00000000..fc7b1a51
--- /dev/null
+++ b/pfinet/linux-src/net/core/firewall.c
@@ -0,0 +1,160 @@
+/*
+ * Generic loadable firewalls. At the moment only IP will actually
+ * use these, but people can add the others as they are needed.
+ *
+ * Authors: Dave Bonn (for IP)
+ * much hacked by: Alan Cox
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/firewall.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/semaphore.h>
+
+struct semaphore firewall_sem = MUTEX;
+static int firewall_policy[NPROTO];
+static struct firewall_ops *firewall_chain[NPROTO];
+
+/*
+ * Register a firewall
+ */
+
+int register_firewall(int pf, struct firewall_ops *fw)
+{
+ struct firewall_ops **p;
+
+ if(pf<0||pf>=NPROTO)
+ return -EINVAL;
+
+ /*
+ * Don't allow two people to adjust at once.
+ */
+
+ down(&firewall_sem);
+
+ p=&firewall_chain[pf];
+
+ while(*p)
+ {
+ if(fw->fw_priority > (*p)->fw_priority)
+ break;
+ p=&((*p)->next);
+ }
+
+ /*
+ * We need to use a memory barrier to make sure that this
+ * works correctly even in SMP with weakly ordered writes.
+ *
+ * This is atomic wrt interrupts (and generally walking the
+ * chain), but not wrt itself (so you can't call this from
+ * an interrupt. Not that you'd want to).
+ */
+
+ fw->next=*p;
+ mb();
+ *p = fw;
+
+ /*
+ * And release the sleep lock
+ */
+
+ up(&firewall_sem);
+ return 0;
+}
+
+/*
+ * Unregister a firewall
+ */
+
+int unregister_firewall(int pf, struct firewall_ops *fw)
+{
+ struct firewall_ops **nl;
+
+ if(pf<0||pf>=NPROTO)
+ return -EINVAL;
+
+ /*
+ * Don't allow two people to adjust at once.
+ */
+
+ down(&firewall_sem);
+
+ nl=&firewall_chain[pf];
+
+ while(*nl!=NULL)
+ {
+ if(*nl==fw)
+ {
+ struct firewall_ops *f=fw->next;
+ *nl = f;
+ up(&firewall_sem);
+ synchronize_bh();
+ return 0;
+ }
+ nl=&((*nl)->next);
+ }
+ up(&firewall_sem);
+ return -ENOENT;
+}
+
+int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+{
+ struct firewall_ops *fw=firewall_chain[pf];
+
+ while(fw!=NULL)
+ {
+ int rc=fw->fw_forward(fw,pf,dev,phdr,arg,skb);
+ if(rc!=FW_SKIP)
+ return rc;
+ fw=fw->next;
+ }
+ return firewall_policy[pf];
+}
+
+/*
+ * Actual invocation of the chains
+ */
+
+int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+{
+ struct firewall_ops *fw=firewall_chain[pf];
+
+ while(fw!=NULL)
+ {
+ int rc=fw->fw_input(fw,pf,dev,phdr,arg,skb);
+ if(rc!=FW_SKIP)
+ return rc;
+ fw=fw->next;
+ }
+ return firewall_policy[pf];
+}
+
+int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **skb)
+{
+ struct firewall_ops *fw=firewall_chain[pf];
+
+ while(fw!=NULL)
+ {
+ int rc=fw->fw_output(fw,pf,dev,phdr,arg,skb);
+ if(rc!=FW_SKIP)
+ return rc;
+ fw=fw->next;
+ }
+ /* alan, is this right? */
+ return firewall_policy[pf];
+}
+
+EXPORT_SYMBOL(register_firewall);
+EXPORT_SYMBOL(unregister_firewall);
+EXPORT_SYMBOL(call_in_firewall);
+EXPORT_SYMBOL(call_out_firewall);
+EXPORT_SYMBOL(call_fw_firewall);
+
+__initfunc(void fwchain_init(void))
+{
+ int i;
+ for(i=0;i<NPROTO;i++)
+ firewall_policy[i]=FW_ACCEPT;
+}
diff --git a/pfinet/linux-src/net/core/iovec.c b/pfinet/linux-src/net/core/iovec.c
new file mode 100644
index 00000000..c20f8530
--- /dev/null
+++ b/pfinet/linux-src/net/core/iovec.c
@@ -0,0 +1,278 @@
+/*
+ * iovec manipulation routines.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ * Andrew Lunn : Errors in iovec copying.
+ * Pedro Roque : Added memcpy_fromiovecend and
+ * csum_..._fromiovecend.
+ * Andi Kleen : fixed error handling for 2.1
+ * Alexey Kuznetsov: 2.1 optimisations
+ * Andi Kleen : Fix csum*fromiovecend for IPv6.
+ */
+
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/net.h>
+#include <linux/in6.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+#include <net/checksum.h>
+
+/*
+ * Verify iovec. The caller must ensure that the iovec is big enough
+ * to hold the message iovec.
+ *
+ * Save time not doing verify_area. copy_*_user will make this work
+ * in any case.
+ */
+
+int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
+{
+ int size, err, ct;
+
+ if(m->msg_namelen)
+ {
+ if(mode==VERIFY_READ)
+ {
+ err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
+ if(err<0)
+ goto out;
+ }
+
+ m->msg_name = address;
+ } else
+ m->msg_name = NULL;
+
+ err = -EFAULT;
+ size = m->msg_iovlen * sizeof(struct iovec);
+ if (copy_from_user(iov, m->msg_iov, size))
+ goto out;
+ m->msg_iov=iov;
+
+ for (err = 0, ct = 0; ct < m->msg_iovlen; ct++) {
+ err += iov[ct].iov_len;
+ /* Goal is not to verify user data, but to prevent returning
+ negative value, which is interpreted as errno.
+ Overflow is still possible, but it is harmless.
+ */
+ if (err < 0)
+ return -EMSGSIZE;
+ }
+out:
+ return err;
+}
+
+/*
+ * Copy kernel to iovec. Returns -EFAULT on error.
+ *
+ * Note: this modifies the original iovec.
+ */
+
+int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
+{
+ int err = -EFAULT;
+
+ while(len>0)
+ {
+ if(iov->iov_len)
+ {
+ int copy = min(iov->iov_len, len);
+ if (copy_to_user(iov->iov_base, kdata, copy))
+ goto out;
+ kdata+=copy;
+ len-=copy;
+ iov->iov_len-=copy;
+ iov->iov_base+=copy;
+ }
+ iov++;
+ }
+ err = 0;
+out:
+ return err;
+}
+
+/*
+ * In kernel copy to iovec. Returns -EFAULT on error.
+ *
+ * Note: this modifies the original iovec.
+ */
+
+void memcpy_tokerneliovec(struct iovec *iov, unsigned char *kdata, int len)
+{
+ while(len>0)
+ {
+ if(iov->iov_len)
+ {
+ int copy = min(iov->iov_len, len);
+ memcpy(iov->iov_base, kdata, copy);
+ kdata+=copy;
+ len-=copy;
+ iov->iov_len-=copy;
+ iov->iov_base+=copy;
+ }
+ iov++;
+ }
+}
+
+
+/*
+ * Copy iovec to kernel. Returns -EFAULT on error.
+ *
+ * Note: this modifies the original iovec.
+ */
+
+int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
+{
+ int err = -EFAULT;
+
+ while(len>0)
+ {
+ if(iov->iov_len)
+ {
+ int copy = min(len, iov->iov_len);
+ if (copy_from_user(kdata, iov->iov_base, copy))
+ goto out;
+ len-=copy;
+ kdata+=copy;
+ iov->iov_base+=copy;
+ iov->iov_len-=copy;
+ }
+ iov++;
+ }
+ err = 0;
+out:
+ return err;
+}
+
+
+/*
+ * For use with ip_build_xmit
+ */
+
+int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
+ int len)
+{
+ int err = -EFAULT;
+
+ /* Skip over the finished iovecs */
+ while(offset >= iov->iov_len)
+ {
+ offset -= iov->iov_len;
+ iov++;
+ }
+
+ while (len > 0)
+ {
+ u8 *base = iov->iov_base + offset;
+ int copy = min(len, iov->iov_len - offset);
+
+ offset = 0;
+ if (copy_from_user(kdata, base, copy))
+ goto out;
+ len -= copy;
+ kdata += copy;
+ iov++;
+ }
+ err = 0;
+out:
+ return err;
+}
+
+/*
+ * And now for the all-in-one: copy and checksum from a user iovec
+ * directly to a datagram
+ * Calls to csum_partial but the last must be in 32 bit chunks
+ *
+ * ip_build_xmit must ensure that when fragmenting only the last
+ * call to this function will be unaligned also.
+ */
+
+int csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov,
+ int offset, unsigned int len, int *csump)
+{
+ int csum = *csump;
+ int partial_cnt = 0, err = 0;
+
+ /* Skip over the finished iovecs */
+ while (offset >= iov->iov_len)
+ {
+ offset -= iov->iov_len;
+ iov++;
+ }
+
+ while (len > 0)
+ {
+ u8 *base = iov->iov_base + offset;
+ unsigned int copy = min(len, iov->iov_len - offset);
+
+ offset = 0;
+ /* There is a remnant from previous iov. */
+ if (partial_cnt)
+ {
+ int par_len = 4 - partial_cnt;
+
+ /* iov component is too short ... */
+ if (par_len > copy) {
+ if (copy_from_user(kdata, base, copy))
+ goto out_fault;
+ kdata += copy;
+ base += copy;
+ partial_cnt += copy;
+ len -= copy;
+ iov++;
+ if (len)
+ continue;
+ *csump = csum_partial(kdata - partial_cnt,
+ partial_cnt, csum);
+ goto out;
+ }
+ if (copy_from_user(kdata, base, par_len))
+ goto out_fault;
+ csum = csum_partial(kdata - partial_cnt, 4, csum);
+ kdata += par_len;
+ base += par_len;
+ copy -= par_len;
+ len -= par_len;
+ partial_cnt = 0;
+ }
+
+ if (len > copy)
+ {
+ partial_cnt = copy % 4;
+ if (partial_cnt)
+ {
+ copy -= partial_cnt;
+ if (copy_from_user(kdata + copy, base + copy,
+ partial_cnt))
+ goto out_fault;
+ }
+ }
+
+ if (copy) {
+ csum = csum_and_copy_from_user(base, kdata, copy,
+ csum, &err);
+ if (err)
+ goto out;
+ }
+ len -= copy + partial_cnt;
+ kdata += copy + partial_cnt;
+ iov++;
+ }
+ *csump = csum;
+out:
+ return err;
+
+out_fault:
+ err = -EFAULT;
+ goto out;
+}
diff --git a/pfinet/linux-src/net/core/neighbour.c b/pfinet/linux-src/net/core/neighbour.c
new file mode 100644
index 00000000..6afbfdcc
--- /dev/null
+++ b/pfinet/linux-src/net/core/neighbour.c
@@ -0,0 +1,1394 @@
+/*
+ * Generic address resolution entity
+ *
+ * Authors:
+ * Pedro Roque <roque@di.fc.ul.pt>
+ * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/socket.h>
+#include <linux/sched.h>
+#include <linux/netdevice.h>
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+#endif
+#include <net/neighbour.h>
+#include <net/dst.h>
+#include <net/sock.h>
+#include <linux/rtnetlink.h>
+
+/*
+ NOTE. The most unpleasent question is serialization of
+ accesses to resolved addresses. The problem is that addresses
+ are modified by bh, but they are referenced from normal
+ kernel thread. Before today no locking was made.
+ My reasoning was that corrupted address token will be copied
+ to packet with cosmologically small probability
+ (it is even difficult to estimate such small number)
+ and it is very silly to waste cycles in fast path to lock them.
+
+ But now I changed my mind, but not because previous statement
+ is wrong. Actually, neigh->ha MAY BE not opaque byte array,
+ but reference to some private data. In this case even neglibible
+ corruption probability becomes bug.
+
+ - hh cache is protected by rwlock. It assumes that
+ hh cache update procedure is short and fast, and that
+ read_lock is cheaper than start_bh_atomic().
+ - ha tokens, saved in neighbour entries, are protected
+ by bh_atomic().
+ - no protection is made in /proc reading. It is OK, because
+ /proc is broken by design in any case, and
+ corrupted output is normal behaviour there.
+
+ --ANK (981025)
+ */
+
+#define NEIGH_DEBUG 1
+
+#define NEIGH_PRINTK(x...) printk(x)
+#define NEIGH_NOPRINTK(x...) do { ; } while(0)
+#define NEIGH_PRINTK0 NEIGH_PRINTK
+#define NEIGH_PRINTK1 NEIGH_NOPRINTK
+#define NEIGH_PRINTK2 NEIGH_NOPRINTK
+
+#if NEIGH_DEBUG >= 1
+#undef NEIGH_PRINTK1
+#define NEIGH_PRINTK1 NEIGH_PRINTK
+#endif
+#if NEIGH_DEBUG >= 2
+#undef NEIGH_PRINTK2
+#define NEIGH_PRINTK2 NEIGH_PRINTK
+#endif
+
+static void neigh_timer_handler(unsigned long arg);
+#ifdef CONFIG_ARPD
+static void neigh_app_notify(struct neighbour *n);
+#endif
+static int pneigh_ifdown(struct neigh_table *tbl, struct device *dev);
+
+static int neigh_glbl_allocs;
+static struct neigh_table *neigh_tables;
+
+static int neigh_blackhole(struct sk_buff *skb)
+{
+ kfree_skb(skb);
+ return -ENETDOWN;
+}
+
+/*
+ * It is random distribution in the interval (1/2)*base...(3/2)*base.
+ * It corresponds to default IPv6 settings and is not overridable,
+ * because it is really reasonbale choice.
+ */
+
+unsigned long neigh_rand_reach_time(unsigned long base)
+{
+ return (net_random() % base) + (base>>1);
+}
+
+
+static int neigh_forced_gc(struct neigh_table *tbl)
+{
+ int shrunk = 0;
+ int i;
+
+ if (atomic_read(&tbl->lock))
+ return 0;
+
+ for (i=0; i<=NEIGH_HASHMASK; i++) {
+ struct neighbour *n, **np;
+
+ np = &tbl->hash_buckets[i];
+ while ((n = *np) != NULL) {
+ /* Neighbour record may be discarded if:
+ - nobody refers to it.
+ - it is not premanent
+ - (NEW and probably wrong)
+ INCOMPLETE entries are kept at least for
+ n->parms->retrans_time, otherwise we could
+ flood network with resolution requests.
+ It is not clear, what is better table overflow
+ or flooding.
+ */
+ if (atomic_read(&n->refcnt) == 0 &&
+ !(n->nud_state&NUD_PERMANENT) &&
+ (n->nud_state != NUD_INCOMPLETE ||
+ jiffies - n->used > n->parms->retrans_time)) {
+ *np = n->next;
+ n->tbl = NULL;
+ tbl->entries--;
+ shrunk = 1;
+ neigh_destroy(n);
+ continue;
+ }
+ np = &n->next;
+ }
+ }
+
+ tbl->last_flush = jiffies;
+ return shrunk;
+}
+
+int neigh_ifdown(struct neigh_table *tbl, struct device *dev)
+{
+ int i;
+
+ if (atomic_read(&tbl->lock)) {
+ NEIGH_PRINTK1("neigh_ifdown: impossible event 1763\n");
+ return -EBUSY;
+ }
+
+ start_bh_atomic();
+ for (i=0; i<=NEIGH_HASHMASK; i++) {
+ struct neighbour *n, **np;
+
+ np = &tbl->hash_buckets[i];
+ while ((n = *np) != NULL) {
+ if (dev && n->dev != dev) {
+ np = &n->next;
+ continue;
+ }
+ *np = n->next;
+ n->tbl = NULL;
+ tbl->entries--;
+ if (atomic_read(&n->refcnt)) {
+ /* The most unpleasant situation.
+ We must destroy neighbour entry,
+ but someone still uses it.
+
+ The destroy will be delayed until
+ the last user releases us, but
+ we must kill timers etc. and move
+ it to safe state.
+ */
+ if (n->nud_state & NUD_IN_TIMER)
+ del_timer(&n->timer);
+ n->parms = &tbl->parms;
+ skb_queue_purge(&n->arp_queue);
+ n->output = neigh_blackhole;
+ if (n->nud_state&NUD_VALID)
+ n->nud_state = NUD_NOARP;
+ else
+ n->nud_state = NUD_NONE;
+ NEIGH_PRINTK2("neigh %p is stray.\n", n);
+ } else
+ neigh_destroy(n);
+ }
+ }
+
+ del_timer(&tbl->proxy_timer);
+ skb_queue_purge(&tbl->proxy_queue);
+ pneigh_ifdown(tbl, dev);
+ end_bh_atomic();
+ return 0;
+}
+
+static struct neighbour *neigh_alloc(struct neigh_table *tbl, int creat)
+{
+ struct neighbour *n;
+ unsigned long now = jiffies;
+
+ if (tbl->entries > tbl->gc_thresh1) {
+ if (creat < 0)
+ return NULL;
+ if (tbl->entries > tbl->gc_thresh3 ||
+ (tbl->entries > tbl->gc_thresh2 &&
+ now - tbl->last_flush > 5*HZ)) {
+ if (neigh_forced_gc(tbl) == 0 &&
+ tbl->entries > tbl->gc_thresh3)
+ return NULL;
+ }
+ }
+
+ n = kmalloc(tbl->entry_size, GFP_ATOMIC);
+ if (n == NULL)
+ return NULL;
+
+ memset(n, 0, tbl->entry_size);
+
+ skb_queue_head_init(&n->arp_queue);
+ n->updated = n->used = now;
+ n->nud_state = NUD_NONE;
+ n->output = neigh_blackhole;
+ n->parms = &tbl->parms;
+ init_timer(&n->timer);
+ n->timer.function = neigh_timer_handler;
+ n->timer.data = (unsigned long)n;
+ tbl->stats.allocs++;
+ neigh_glbl_allocs++;
+ return n;
+}
+
+
+struct neighbour * __neigh_lookup(struct neigh_table *tbl, const void *pkey,
+ struct device *dev, int creat)
+{
+ struct neighbour *n;
+ u32 hash_val;
+ int key_len = tbl->key_len;
+
+ hash_val = *(u32*)(pkey + key_len - 4);
+ hash_val ^= (hash_val>>16);
+ hash_val ^= hash_val>>8;
+ hash_val ^= hash_val>>3;
+ hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
+
+ for (n = tbl->hash_buckets[hash_val]; n; n = n->next) {
+ if (dev == n->dev &&
+ memcmp(n->primary_key, pkey, key_len) == 0) {
+ atomic_inc(&n->refcnt);
+ return n;
+ }
+ }
+ if (!creat)
+ return NULL;
+
+ n = neigh_alloc(tbl, creat);
+ if (n == NULL)
+ return NULL;
+
+ memcpy(n->primary_key, pkey, key_len);
+ n->dev = dev;
+
+ /* Protocol specific setup. */
+ if (tbl->constructor && tbl->constructor(n) < 0) {
+ neigh_destroy(n);
+ return NULL;
+ }
+
+ /* Device specific setup. */
+ if (n->parms && n->parms->neigh_setup && n->parms->neigh_setup(n) < 0) {
+ neigh_destroy(n);
+ return NULL;
+ }
+
+ n->confirmed = jiffies - (n->parms->base_reachable_time<<1);
+ atomic_set(&n->refcnt, 1);
+ tbl->entries++;
+ n->next = tbl->hash_buckets[hash_val];
+ tbl->hash_buckets[hash_val] = n;
+ n->tbl = tbl;
+ NEIGH_PRINTK2("neigh %p is created.\n", n);
+ return n;
+}
+
+struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
+ struct device *dev, int creat)
+{
+ struct pneigh_entry *n;
+ u32 hash_val;
+ int key_len = tbl->key_len;
+
+ hash_val = *(u32*)(pkey + key_len - 4);
+ hash_val ^= (hash_val>>16);
+ hash_val ^= hash_val>>8;
+ hash_val ^= hash_val>>4;
+ hash_val &= PNEIGH_HASHMASK;
+
+ for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
+ if (memcmp(n->key, pkey, key_len) == 0 &&
+ (n->dev == dev || !n->dev))
+ return n;
+ }
+ if (!creat)
+ return NULL;
+
+ n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
+ if (n == NULL)
+ return NULL;
+
+ memcpy(n->key, pkey, key_len);
+ n->dev = dev;
+
+ if (tbl->pconstructor && tbl->pconstructor(n)) {
+ kfree(n);
+ return NULL;
+ }
+
+ n->next = tbl->phash_buckets[hash_val];
+ tbl->phash_buckets[hash_val] = n;
+ return n;
+}
+
+
+int pneigh_delete(struct neigh_table *tbl, const void *pkey, struct device *dev)
+{
+ struct pneigh_entry *n, **np;
+ u32 hash_val;
+ int key_len = tbl->key_len;
+
+ hash_val = *(u32*)(pkey + key_len - 4);
+ hash_val ^= (hash_val>>16);
+ hash_val ^= hash_val>>8;
+ hash_val ^= hash_val>>4;
+ hash_val &= PNEIGH_HASHMASK;
+
+ for (np = &tbl->phash_buckets[hash_val]; (n=*np) != NULL; np = &n->next) {
+ if (memcmp(n->key, pkey, key_len) == 0 && n->dev == dev) {
+ *np = n->next;
+ synchronize_bh();
+ if (tbl->pdestructor)
+ tbl->pdestructor(n);
+ kfree(n);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+static int pneigh_ifdown(struct neigh_table *tbl, struct device *dev)
+{
+ struct pneigh_entry *n, **np;
+ u32 h;
+
+ for (h=0; h<=PNEIGH_HASHMASK; h++) {
+ np = &tbl->phash_buckets[h];
+ while ((n=*np) != NULL) {
+ if (n->dev == dev || dev == NULL) {
+ *np = n->next;
+ synchronize_bh();
+ if (tbl->pdestructor)
+ tbl->pdestructor(n);
+ kfree(n);
+ continue;
+ }
+ np = &n->next;
+ }
+ }
+ return -ENOENT;
+}
+
+
+/*
+ * neighbour must already be out of the table;
+ *
+ */
+void neigh_destroy(struct neighbour *neigh)
+{
+ struct hh_cache *hh;
+
+ if (neigh->tbl || atomic_read(&neigh->refcnt)) {
+ NEIGH_PRINTK1("neigh_destroy: neighbour is use tbl=%p, ref=%d: "
+ "called from %p\n", neigh->tbl, atomic_read(&neigh->refcnt), __builtin_return_address(0));
+ return;
+ }
+
+ if (neigh->nud_state&NUD_IN_TIMER)
+ del_timer(&neigh->timer);
+
+ while ((hh = neigh->hh) != NULL) {
+ neigh->hh = hh->hh_next;
+ hh->hh_next = NULL;
+ hh->hh_output = neigh_blackhole;
+ if (atomic_dec_and_test(&hh->hh_refcnt))
+ kfree(hh);
+ }
+
+ if (neigh->ops && neigh->ops->destructor)
+ (neigh->ops->destructor)(neigh);
+
+ skb_queue_purge(&neigh->arp_queue);
+
+ NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
+
+ neigh_glbl_allocs--;
+ kfree(neigh);
+}
+
+/* Neighbour state is suspicious;
+ disable fast path.
+ */
+static void neigh_suspect(struct neighbour *neigh)
+{
+ struct hh_cache *hh;
+
+ NEIGH_PRINTK2("neigh %p is suspecteded.\n", neigh);
+
+ neigh->output = neigh->ops->output;
+
+ for (hh = neigh->hh; hh; hh = hh->hh_next)
+ hh->hh_output = neigh->ops->output;
+}
+
+/* Neighbour state is OK;
+ enable fast path.
+ */
+static void neigh_connect(struct neighbour *neigh)
+{
+ struct hh_cache *hh;
+
+ NEIGH_PRINTK2("neigh %p is connected.\n", neigh);
+
+ neigh->output = neigh->ops->connected_output;
+
+ for (hh = neigh->hh; hh; hh = hh->hh_next)
+ hh->hh_output = neigh->ops->hh_output;
+}
+
+/*
+ Transitions NUD_STALE <-> NUD_REACHABLE do not occur
+ when fast path is built: we have no timers assotiated with
+ these states, we do not have time to check state when sending.
+ neigh_periodic_timer check periodically neigh->confirmed
+ time and moves NUD_REACHABLE -> NUD_STALE.
+
+ If a routine wants to know TRUE entry state, it calls
+ neigh_sync before checking state.
+ */
+
+static void neigh_sync(struct neighbour *n)
+{
+ unsigned long now = jiffies;
+ u8 state = n->nud_state;
+
+ if (state&(NUD_NOARP|NUD_PERMANENT))
+ return;
+ if (state&NUD_REACHABLE) {
+ if (now - n->confirmed > n->parms->reachable_time) {
+ n->nud_state = NUD_STALE;
+ neigh_suspect(n);
+ }
+ } else if (state&NUD_VALID) {
+ if (now - n->confirmed < n->parms->reachable_time) {
+ if (state&NUD_IN_TIMER)
+ del_timer(&n->timer);
+ n->nud_state = NUD_REACHABLE;
+ neigh_connect(n);
+ }
+ }
+}
+
+static void neigh_periodic_timer(unsigned long arg)
+{
+ struct neigh_table *tbl = (struct neigh_table*)arg;
+ unsigned long now = jiffies;
+ int i;
+
+ if (atomic_read(&tbl->lock)) {
+ tbl->gc_timer.expires = now + 1*HZ;
+ add_timer(&tbl->gc_timer);
+ return;
+ }
+
+ /*
+ * periodicly recompute ReachableTime from random function
+ */
+
+ if (now - tbl->last_rand > 300*HZ) {
+ struct neigh_parms *p;
+ tbl->last_rand = now;
+ for (p=&tbl->parms; p; p = p->next)
+ p->reachable_time = neigh_rand_reach_time(p->base_reachable_time);
+ }
+
+ for (i=0; i <= NEIGH_HASHMASK; i++) {
+ struct neighbour *n, **np;
+
+ np = &tbl->hash_buckets[i];
+ while ((n = *np) != NULL) {
+ unsigned state = n->nud_state;
+
+ if (state&(NUD_PERMANENT|NUD_IN_TIMER))
+ goto next_elt;
+
+ if ((long)(n->used - n->confirmed) < 0)
+ n->used = n->confirmed;
+
+ if (atomic_read(&n->refcnt) == 0 &&
+ (state == NUD_FAILED || now - n->used > n->parms->gc_staletime)) {
+ *np = n->next;
+ n->tbl = NULL;
+ n->next = NULL;
+ tbl->entries--;
+ neigh_destroy(n);
+ continue;
+ }
+
+ if (n->nud_state&NUD_REACHABLE &&
+ now - n->confirmed > n->parms->reachable_time) {
+ n->nud_state = NUD_STALE;
+ neigh_suspect(n);
+ }
+
+next_elt:
+ np = &n->next;
+ }
+ }
+
+ tbl->gc_timer.expires = now + tbl->gc_interval;
+ add_timer(&tbl->gc_timer);
+}
+
+static __inline__ int neigh_max_probes(struct neighbour *n)
+{
+ struct neigh_parms *p = n->parms;
+ return p->ucast_probes + p->app_probes + p->mcast_probes;
+}
+
+
+/* Called when a timer expires for a neighbour entry. */
+
+static void neigh_timer_handler(unsigned long arg)
+{
+ unsigned long now = jiffies;
+ struct neighbour *neigh = (struct neighbour*)arg;
+ unsigned state = neigh->nud_state;
+
+ if (!(state&NUD_IN_TIMER)) {
+ NEIGH_PRINTK1("neigh: timer & !nud_in_timer\n");
+ return;
+ }
+
+ if ((state&NUD_VALID) &&
+ now - neigh->confirmed < neigh->parms->reachable_time) {
+ neigh->nud_state = NUD_REACHABLE;
+ NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
+ neigh_connect(neigh);
+ return;
+ }
+ if (state == NUD_DELAY) {
+ NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
+ neigh->nud_state = NUD_PROBE;
+ neigh->probes = 0;
+ }
+
+ if (neigh->probes >= neigh_max_probes(neigh)) {
+ struct sk_buff *skb;
+
+ neigh->nud_state = NUD_FAILED;
+ neigh->tbl->stats.res_failed++;
+ NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
+
+ /* It is very thin place. report_unreachable is very complicated
+ routine. Particularly, it can hit the same neighbour entry!
+
+ So that, we try to be accurate and avoid dead loop. --ANK
+ */
+ while(neigh->nud_state==NUD_FAILED && (skb=__skb_dequeue(&neigh->arp_queue)) != NULL)
+ neigh->ops->error_report(neigh, skb);
+ skb_queue_purge(&neigh->arp_queue);
+ return;
+ }
+
+ neigh->timer.expires = now + neigh->parms->retrans_time;
+ add_timer(&neigh->timer);
+
+ neigh->ops->solicit(neigh, skb_peek(&neigh->arp_queue));
+ neigh->probes++;
+}
+
+int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+{
+ start_bh_atomic();
+ if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE))) {
+ if (!(neigh->nud_state&(NUD_STALE|NUD_INCOMPLETE))) {
+ if (neigh->tbl == NULL) {
+ NEIGH_PRINTK2("neigh %p used after death.\n", neigh);
+ if (skb)
+ kfree_skb(skb);
+ end_bh_atomic();
+ return 1;
+ }
+ if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
+ neigh->probes = neigh->parms->ucast_probes;
+ neigh->nud_state = NUD_INCOMPLETE;
+ neigh->timer.expires = jiffies + neigh->parms->retrans_time;
+ add_timer(&neigh->timer);
+
+ neigh->ops->solicit(neigh, skb);
+ neigh->probes++;
+ } else {
+ neigh->nud_state = NUD_FAILED;
+ if (skb)
+ kfree_skb(skb);
+ end_bh_atomic();
+ return 1;
+ }
+ }
+ if (neigh->nud_state == NUD_INCOMPLETE) {
+ if (skb) {
+ if (skb_queue_len(&neigh->arp_queue) >= neigh->parms->queue_len) {
+ struct sk_buff *buff;
+ buff = neigh->arp_queue.prev;
+ __skb_unlink(buff, &neigh->arp_queue);
+ kfree_skb(buff);
+ }
+ __skb_queue_head(&neigh->arp_queue, skb);
+ }
+ end_bh_atomic();
+ return 1;
+ }
+ if (neigh->nud_state == NUD_STALE) {
+ NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+ neigh->nud_state = NUD_DELAY;
+ neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;
+ add_timer(&neigh->timer);
+ }
+ }
+ end_bh_atomic();
+ return 0;
+}
+
+static __inline__ void neigh_update_hhs(struct neighbour *neigh)
+{
+ struct hh_cache *hh;
+ void (*update)(struct hh_cache*, struct device*, unsigned char*) =
+ neigh->dev->header_cache_update;
+
+ if (update) {
+ for (hh=neigh->hh; hh; hh=hh->hh_next) {
+ write_lock_irq(&hh->hh_lock);
+ update(hh, neigh->dev, neigh->ha);
+ write_unlock_irq(&hh->hh_lock);
+ }
+ }
+}
+
+
+
+/* Generic update routine.
+ -- lladdr is new lladdr or NULL, if it is not supplied.
+ -- new is new state.
+ -- override==1 allows to override existing lladdr, if it is different.
+ -- arp==0 means that the change is administrative.
+ */
+
+int neigh_update(struct neighbour *neigh, u8 *lladdr, u8 new, int override, int arp)
+{
+ u8 old = neigh->nud_state;
+ struct device *dev = neigh->dev;
+
+ if (arp && (old&(NUD_NOARP|NUD_PERMANENT)))
+ return -EPERM;
+
+ if (!(new&NUD_VALID)) {
+ if (old&NUD_IN_TIMER)
+ del_timer(&neigh->timer);
+ if (old&NUD_CONNECTED)
+ neigh_suspect(neigh);
+ neigh->nud_state = new;
+ return 0;
+ }
+
+ /* Compare new lladdr with cached one */
+ if (dev->addr_len == 0) {
+ /* First case: device needs no address. */
+ lladdr = neigh->ha;
+ } else if (lladdr) {
+ /* The second case: if something is already cached
+ and a new address is proposed:
+ - compare new & old
+ - if they are different, check override flag
+ */
+ if (old&NUD_VALID) {
+ if (memcmp(lladdr, neigh->ha, dev->addr_len) == 0)
+ lladdr = neigh->ha;
+ else if (!override)
+ return -EPERM;
+ }
+ } else {
+ /* No address is supplied; if we know something,
+ use it, otherwise discard the request.
+ */
+ if (!(old&NUD_VALID))
+ return -EINVAL;
+ lladdr = neigh->ha;
+ }
+
+ neigh_sync(neigh);
+ old = neigh->nud_state;
+ if (new&NUD_CONNECTED)
+ neigh->confirmed = jiffies;
+ neigh->updated = jiffies;
+
+ /* If entry was valid and address is not changed,
+ do not change entry state, if new one is STALE.
+ */
+ if (old&NUD_VALID) {
+ if (lladdr == neigh->ha)
+ if (new == old || (new == NUD_STALE && (old&NUD_CONNECTED)))
+ return 0;
+ }
+ if (old&NUD_IN_TIMER)
+ del_timer(&neigh->timer);
+ neigh->nud_state = new;
+ if (lladdr != neigh->ha) {
+ memcpy(&neigh->ha, lladdr, dev->addr_len);
+ neigh_update_hhs(neigh);
+ neigh->confirmed = jiffies - (neigh->parms->base_reachable_time<<1);
+#ifdef CONFIG_ARPD
+ if (neigh->parms->app_probes)
+ neigh_app_notify(neigh);
+#endif
+ }
+ if (new == old)
+ return 0;
+ if (new&NUD_CONNECTED)
+ neigh_connect(neigh);
+ else
+ neigh_suspect(neigh);
+ if (!(old&NUD_VALID)) {
+ struct sk_buff *skb;
+
+ /* Again: avoid dead loop if something went wrong */
+
+ while (neigh->nud_state&NUD_VALID &&
+ (skb=__skb_dequeue(&neigh->arp_queue)) != NULL) {
+ struct neighbour *n1 = neigh;
+ /* On shaper/eql skb->dst->neighbour != neigh :( */
+ if (skb->dst && skb->dst->neighbour)
+ n1 = skb->dst->neighbour;
+ n1->output(skb);
+ }
+ skb_queue_purge(&neigh->arp_queue);
+ }
+ return 0;
+}
+
+struct neighbour * neigh_event_ns(struct neigh_table *tbl,
+ u8 *lladdr, void *saddr,
+ struct device *dev)
+{
+ struct neighbour *neigh;
+
+ neigh = __neigh_lookup(tbl, saddr, dev, lladdr || !dev->addr_len);
+ if (neigh)
+ neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+ return neigh;
+}
+
+static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, u16 protocol)
+{
+ struct hh_cache *hh = NULL;
+ struct device *dev = dst->dev;
+
+ for (hh=n->hh; hh; hh = hh->hh_next)
+ if (hh->hh_type == protocol)
+ break;
+
+ if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
+ memset(hh, 0, sizeof(struct hh_cache));
+ hh->hh_type = protocol;
+ atomic_set(&hh->hh_refcnt, 0);
+ hh->hh_next = NULL;
+ if (dev->hard_header_cache(n, hh)) {
+ kfree(hh);
+ hh = NULL;
+ } else {
+ atomic_inc(&hh->hh_refcnt);
+ hh->hh_next = n->hh;
+ n->hh = hh;
+ if (n->nud_state&NUD_CONNECTED)
+ hh->hh_output = n->ops->hh_output;
+ else
+ hh->hh_output = n->ops->output;
+ }
+ }
+ if (hh) {
+ atomic_inc(&hh->hh_refcnt);
+ dst->hh = hh;
+ }
+}
+
+/* This function can be used in contexts, where only old dev_queue_xmit
+ worked, f.e. if you want to override normal output path (eql, shaper),
+ but resoltution is not made yet.
+ */
+
+int neigh_compat_output(struct sk_buff *skb)
+{
+ struct device *dev = skb->dev;
+
+ __skb_pull(skb, skb->nh.raw - skb->data);
+
+ if (dev->hard_header &&
+ dev->hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL, skb->len) < 0 &&
+ dev->rebuild_header(skb))
+ return 0;
+
+ return dev_queue_xmit(skb);
+}
+
+/* Slow and careful. */
+
+int neigh_resolve_output(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct neighbour *neigh;
+
+ if (!dst || !(neigh = dst->neighbour))
+ goto discard;
+
+ __skb_pull(skb, skb->nh.raw - skb->data);
+
+ if (neigh_event_send(neigh, skb) == 0) {
+ int err;
+ struct device *dev = neigh->dev;
+ if (dev->hard_header_cache && dst->hh == NULL) {
+ start_bh_atomic();
+ if (dst->hh == NULL)
+ neigh_hh_init(neigh, dst, dst->ops->protocol);
+ err = dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len);
+ end_bh_atomic();
+ } else {
+ start_bh_atomic();
+ err = dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len);
+ end_bh_atomic();
+ }
+ if (err >= 0)
+ return neigh->ops->queue_xmit(skb);
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ return 0;
+
+discard:
+ NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n", dst, dst ? dst->neighbour : NULL);
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+/* As fast as possible without hh cache */
+
+int neigh_connected_output(struct sk_buff *skb)
+{
+ int err;
+ struct dst_entry *dst = skb->dst;
+ struct neighbour *neigh = dst->neighbour;
+ struct device *dev = neigh->dev;
+
+ __skb_pull(skb, skb->nh.raw - skb->data);
+
+ start_bh_atomic();
+ err = dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len);
+ end_bh_atomic();
+ if (err >= 0)
+ return neigh->ops->queue_xmit(skb);
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+static void neigh_proxy_process(unsigned long arg)
+{
+ struct neigh_table *tbl = (struct neigh_table *)arg;
+ long sched_next = 0;
+ unsigned long now = jiffies;
+ struct sk_buff *skb = tbl->proxy_queue.next;
+
+ while (skb != (struct sk_buff*)&tbl->proxy_queue) {
+ struct sk_buff *back = skb;
+ long tdif = back->stamp.tv_usec - now;
+
+ skb = skb->next;
+ if (tdif <= 0) {
+ __skb_unlink(back, &tbl->proxy_queue);
+ if (tbl->proxy_redo)
+ tbl->proxy_redo(back);
+ else
+ kfree_skb(back);
+ } else if (!sched_next || tdif < sched_next)
+ sched_next = tdif;
+ }
+ del_timer(&tbl->proxy_timer);
+ if (sched_next) {
+ tbl->proxy_timer.expires = jiffies + sched_next;
+ add_timer(&tbl->proxy_timer);
+ }
+}
+
+void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+ struct sk_buff *skb)
+{
+ unsigned long now = jiffies;
+ long sched_next = net_random()%p->proxy_delay;
+
+ if (tbl->proxy_queue.qlen > p->proxy_qlen) {
+ kfree_skb(skb);
+ return;
+ }
+ skb->stamp.tv_sec = 0;
+ skb->stamp.tv_usec = now + sched_next;
+ if (del_timer(&tbl->proxy_timer)) {
+ long tval = tbl->proxy_timer.expires - now;
+ if (tval < sched_next)
+ sched_next = tval;
+ }
+ tbl->proxy_timer.expires = now + sched_next;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ __skb_queue_tail(&tbl->proxy_queue, skb);
+ add_timer(&tbl->proxy_timer);
+}
+
+
+struct neigh_parms *neigh_parms_alloc(struct device *dev, struct neigh_table *tbl)
+{
+ struct neigh_parms *p;
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p) {
+ memcpy(p, &tbl->parms, sizeof(*p));
+ p->tbl = tbl;
+ p->reachable_time = neigh_rand_reach_time(p->base_reachable_time);
+ if (dev && dev->neigh_setup) {
+ if (dev->neigh_setup(dev, p)) {
+ kfree(p);
+ return NULL;
+ }
+ }
+ p->next = tbl->parms.next;
+ tbl->parms.next = p;
+ }
+ return p;
+}
+
+void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
+{
+ struct neigh_parms **p;
+
+ if (parms == NULL || parms == &tbl->parms)
+ return;
+ for (p = &tbl->parms.next; *p; p = &(*p)->next) {
+ if (*p == parms) {
+ *p = parms->next;
+ synchronize_bh();
+#ifdef CONFIG_SYSCTL
+ neigh_sysctl_unregister(parms);
+#endif
+ kfree(parms);
+ return;
+ }
+ }
+ NEIGH_PRINTK1("neigh_release_parms: not found\n");
+}
+
+
+void neigh_table_init(struct neigh_table *tbl)
+{
+ unsigned long now = jiffies;
+
+ tbl->parms.reachable_time = neigh_rand_reach_time(tbl->parms.base_reachable_time);
+
+ init_timer(&tbl->gc_timer);
+ tbl->gc_timer.data = (unsigned long)tbl;
+ tbl->gc_timer.function = neigh_periodic_timer;
+ tbl->gc_timer.expires = now + tbl->gc_interval + tbl->parms.reachable_time;
+ add_timer(&tbl->gc_timer);
+
+ init_timer(&tbl->proxy_timer);
+ tbl->proxy_timer.data = (unsigned long)tbl;
+ tbl->proxy_timer.function = neigh_proxy_process;
+ skb_queue_head_init(&tbl->proxy_queue);
+
+ tbl->last_flush = now;
+ tbl->last_rand = now + tbl->parms.reachable_time*20;
+ tbl->next = neigh_tables;
+ neigh_tables = tbl;
+}
+
+int neigh_table_clear(struct neigh_table *tbl)
+{
+ struct neigh_table **tp;
+
+ start_bh_atomic();
+ del_timer(&tbl->gc_timer);
+ del_timer(&tbl->proxy_timer);
+ skb_queue_purge(&tbl->proxy_queue);
+ neigh_ifdown(tbl, NULL);
+ end_bh_atomic();
+ if (tbl->entries)
+ printk(KERN_CRIT "neighbour leakage\n");
+ for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
+ if (*tp == tbl) {
+ *tp = tbl->next;
+ synchronize_bh();
+ break;
+ }
+ }
+#ifdef CONFIG_SYSCTL
+ neigh_sysctl_unregister(&tbl->parms);
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_RTNETLINK
+
+
+int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct ndmsg *ndm = NLMSG_DATA(nlh);
+ struct rtattr **nda = arg;
+ struct neigh_table *tbl;
+ struct device *dev = NULL;
+
+ if (ndm->ndm_ifindex) {
+ if ((dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)
+ return -ENODEV;
+ }
+
+ for (tbl=neigh_tables; tbl; tbl = tbl->next) {
+ int err = 0;
+ struct neighbour *n;
+
+ if (tbl->family != ndm->ndm_family)
+ continue;
+
+ if (nda[NDA_DST-1] == NULL ||
+ nda[NDA_DST-1]->rta_len != RTA_LENGTH(tbl->key_len))
+ return -EINVAL;
+
+ if (ndm->ndm_flags&NTF_PROXY)
+ return pneigh_delete(tbl, RTA_DATA(nda[NDA_DST-1]), dev);
+
+ if (dev == NULL)
+ return -EINVAL;
+
+ start_bh_atomic();
+ n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 0);
+ if (n) {
+ err = neigh_update(n, NULL, NUD_FAILED, 1, 0);
+ neigh_release(n);
+ }
+ end_bh_atomic();
+ return err;
+ }
+
+ return -EADDRNOTAVAIL;
+}
+
+int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct ndmsg *ndm = NLMSG_DATA(nlh);
+ struct rtattr **nda = arg;
+ struct neigh_table *tbl;
+ struct device *dev = NULL;
+
+ if (ndm->ndm_ifindex) {
+ if ((dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)
+ return -ENODEV;
+ }
+
+ for (tbl=neigh_tables; tbl; tbl = tbl->next) {
+ int err = 0;
+ struct neighbour *n;
+
+ if (tbl->family != ndm->ndm_family)
+ continue;
+ if (nda[NDA_DST-1] == NULL ||
+ nda[NDA_DST-1]->rta_len != RTA_LENGTH(tbl->key_len))
+ return -EINVAL;
+ if (ndm->ndm_flags&NTF_PROXY) {
+ if (pneigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 1))
+ return 0;
+ return -ENOBUFS;
+ }
+ if (dev == NULL)
+ return -EINVAL;
+ if (nda[NDA_LLADDR-1] != NULL &&
+ nda[NDA_LLADDR-1]->rta_len != RTA_LENGTH(dev->addr_len))
+ return -EINVAL;
+ start_bh_atomic();
+ n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 0);
+ if (n) {
+ if (nlh->nlmsg_flags&NLM_F_EXCL)
+ err = -EEXIST;
+ } else if (!(nlh->nlmsg_flags&NLM_F_CREATE))
+ err = -ENOENT;
+ else {
+ n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 1);
+ if (n == NULL)
+ err = -ENOBUFS;
+ }
+ if (err == 0) {
+ err = neigh_update(n, nda[NDA_LLADDR-1] ? RTA_DATA(nda[NDA_LLADDR-1]) : NULL,
+ ndm->ndm_state,
+ nlh->nlmsg_flags&NLM_F_REPLACE, 0);
+ }
+ if (n)
+ neigh_release(n);
+ end_bh_atomic();
+ return err;
+ }
+
+ return -EADDRNOTAVAIL;
+}
+
+
+static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
+ u32 pid, u32 seq, int event)
+{
+ unsigned long now = jiffies;
+ struct ndmsg *ndm;
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
+ struct nda_cacheinfo ci;
+
+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ndm));
+ ndm = NLMSG_DATA(nlh);
+ ndm->ndm_family = n->ops->family;
+ ndm->ndm_flags = n->flags;
+ ndm->ndm_type = n->type;
+ ndm->ndm_state = n->nud_state;
+ ndm->ndm_ifindex = n->dev->ifindex;
+ RTA_PUT(skb, NDA_DST, n->tbl->key_len, n->primary_key);
+ if (n->nud_state&NUD_VALID)
+ RTA_PUT(skb, NDA_LLADDR, n->dev->addr_len, n->ha);
+ ci.ndm_used = now - n->used;
+ ci.ndm_confirmed = now - n->confirmed;
+ ci.ndm_updated = now - n->updated;
+ ci.ndm_refcnt = atomic_read(&n->refcnt);
+ RTA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci);
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+
+static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct neighbour *n;
+ int h, s_h;
+ int idx, s_idx;
+
+ s_h = cb->args[1];
+ s_idx = idx = cb->args[2];
+ for (h=0; h <= NEIGH_HASHMASK; h++) {
+ if (h < s_h) continue;
+ if (h > s_h)
+ s_idx = 0;
+ start_bh_atomic();
+ for (n = tbl->hash_buckets[h], idx = 0; n;
+ n = n->next, idx++) {
+ if (idx < s_idx)
+ continue;
+ if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWNEIGH) <= 0) {
+ end_bh_atomic();
+ cb->args[1] = h;
+ cb->args[2] = idx;
+ return -1;
+ }
+ }
+ end_bh_atomic();
+ }
+
+ cb->args[1] = h;
+ cb->args[2] = idx;
+ return skb->len;
+}
+
+int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int t;
+ int s_t;
+ struct neigh_table *tbl;
+ int family = ((struct rtgenmsg*)NLMSG_DATA(cb->nlh))->rtgen_family;
+
+ s_t = cb->args[0];
+
+ for (tbl=neigh_tables, t=0; tbl; tbl = tbl->next, t++) {
+ if (t < s_t) continue;
+ if (family && tbl->family != family)
+ continue;
+ if (t > s_t)
+ memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
+ if (neigh_dump_table(tbl, skb, cb) < 0)
+ break;
+ }
+
+ cb->args[0] = t;
+
+ return skb->len;
+}
+
+#ifdef CONFIG_ARPD
+void neigh_app_ns(struct neighbour *n)
+{
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ int size = NLMSG_SPACE(sizeof(struct ndmsg)+256);
+
+ skb = alloc_skb(size, GFP_ATOMIC);
+ if (!skb)
+ return;
+
+ if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH) < 0) {
+ kfree_skb(skb);
+ return;
+ }
+ nlh = (struct nlmsghdr*)skb->data;
+ nlh->nlmsg_flags = NLM_F_REQUEST;
+ NETLINK_CB(skb).dst_groups = RTMGRP_NEIGH;
+ netlink_broadcast(rtnl, skb, 0, RTMGRP_NEIGH, GFP_ATOMIC);
+}
+
+static void neigh_app_notify(struct neighbour *n)
+{
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ int size = NLMSG_SPACE(sizeof(struct ndmsg)+256);
+
+ skb = alloc_skb(size, GFP_ATOMIC);
+ if (!skb)
+ return;
+
+ if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH) < 0) {
+ kfree_skb(skb);
+ return;
+ }
+ nlh = (struct nlmsghdr*)skb->data;
+ NETLINK_CB(skb).dst_groups = RTMGRP_NEIGH;
+ netlink_broadcast(rtnl, skb, 0, RTMGRP_NEIGH, GFP_ATOMIC);
+}
+
+
+
+#endif
+
+
+#endif
+
+#ifdef CONFIG_SYSCTL
+
+struct neigh_sysctl_table
+{
+ struct ctl_table_header *sysctl_header;
+ ctl_table neigh_vars[17];
+ ctl_table neigh_dev[2];
+ ctl_table neigh_neigh_dir[2];
+ ctl_table neigh_proto_dir[2];
+ ctl_table neigh_root_dir[2];
+} neigh_sysctl_template = {
+ NULL,
+ {{NET_NEIGH_MCAST_SOLICIT, "mcast_solicit",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_UCAST_SOLICIT, "ucast_solicit",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_APP_SOLICIT, "app_solicit",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_RETRANS_TIME, "retrans_time",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_REACHABLE_TIME, "base_reachable_time",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies},
+ {NET_NEIGH_DELAY_PROBE_TIME, "delay_first_probe_time",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies},
+ {NET_NEIGH_GC_STALE_TIME, "gc_stale_time",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies},
+ {NET_NEIGH_UNRES_QLEN, "unres_qlen",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_PROXY_QLEN, "proxy_qlen",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_ANYCAST_DELAY, "anycast_delay",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_PROXY_DELAY, "proxy_delay",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_LOCKTIME, "locktime",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_GC_INTERVAL, "gc_interval",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies},
+ {NET_NEIGH_GC_THRESH1, "gc_thresh1",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_GC_THRESH2, "gc_thresh2",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_NEIGH_GC_THRESH3, "gc_thresh3",
+ NULL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {0}},
+
+ {{NET_PROTO_CONF_DEFAULT, "default", NULL, 0, 0555, NULL},{0}},
+ {{0, "neigh", NULL, 0, 0555, NULL},{0}},
+ {{0, NULL, NULL, 0, 0555, NULL},{0}},
+ {{CTL_NET, "net", NULL, 0, 0555, NULL},{0}}
+};
+
+int neigh_sysctl_register(struct device *dev, struct neigh_parms *p,
+ int p_id, int pdev_id, char *p_name)
+{
+ struct neigh_sysctl_table *t;
+
+ t = kmalloc(sizeof(*t), GFP_KERNEL);
+ if (t == NULL)
+ return -ENOBUFS;
+ memcpy(t, &neigh_sysctl_template, sizeof(*t));
+ t->neigh_vars[0].data = &p->mcast_probes;
+ t->neigh_vars[1].data = &p->ucast_probes;
+ t->neigh_vars[2].data = &p->app_probes;
+ t->neigh_vars[3].data = &p->retrans_time;
+ t->neigh_vars[4].data = &p->base_reachable_time;
+ t->neigh_vars[5].data = &p->delay_probe_time;
+ t->neigh_vars[6].data = &p->gc_staletime;
+ t->neigh_vars[7].data = &p->queue_len;
+ t->neigh_vars[8].data = &p->proxy_qlen;
+ t->neigh_vars[9].data = &p->anycast_delay;
+ t->neigh_vars[10].data = &p->proxy_delay;
+ t->neigh_vars[11].data = &p->locktime;
+ if (dev) {
+ t->neigh_dev[0].procname = dev->name;
+ t->neigh_dev[0].ctl_name = dev->ifindex;
+ memset(&t->neigh_vars[12], 0, sizeof(ctl_table));
+ } else {
+ t->neigh_vars[12].data = (int*)(p+1);
+ t->neigh_vars[13].data = (int*)(p+1) + 1;
+ t->neigh_vars[14].data = (int*)(p+1) + 2;
+ t->neigh_vars[15].data = (int*)(p+1) + 3;
+ }
+ t->neigh_neigh_dir[0].ctl_name = pdev_id;
+
+ t->neigh_proto_dir[0].procname = p_name;
+ t->neigh_proto_dir[0].ctl_name = p_id;
+
+ t->neigh_dev[0].child = t->neigh_vars;
+ t->neigh_neigh_dir[0].child = t->neigh_dev;
+ t->neigh_proto_dir[0].child = t->neigh_neigh_dir;
+ t->neigh_root_dir[0].child = t->neigh_proto_dir;
+
+ t->sysctl_header = register_sysctl_table(t->neigh_root_dir, 0);
+ if (t->sysctl_header == NULL) {
+ kfree(t);
+ return -ENOBUFS;
+ }
+ p->sysctl_table = t;
+ return 0;
+}
+
+void neigh_sysctl_unregister(struct neigh_parms *p)
+{
+ if (p->sysctl_table) {
+ struct neigh_sysctl_table *t = p->sysctl_table;
+ p->sysctl_table = NULL;
+ unregister_sysctl_table(t->sysctl_header);
+ kfree(t);
+ }
+}
+
+#endif /* CONFIG_SYSCTL */
diff --git a/pfinet/linux-src/net/core/profile.c b/pfinet/linux-src/net/core/profile.c
new file mode 100644
index 00000000..fc7464b7
--- /dev/null
+++ b/pfinet/linux-src/net/core/profile.c
@@ -0,0 +1,305 @@
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/inet.h>
+#include <net/checksum.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <net/profile.h>
+
+#ifdef CONFIG_NET_PROFILE
+
+atomic_t net_profile_active;
+struct timeval net_profile_adjust;
+
+NET_PROFILE_DEFINE(total);
+
+struct net_profile_slot *net_profile_chain = &net_prof_total;
+
+#ifdef __alpha__
+__u32 alpha_lo;
+long alpha_hi;
+
+static void alpha_tick(unsigned long);
+
+static struct timer_list alpha_timer =
+ { NULL, NULL, 0, 0L, alpha_tick };
+
+void alpha_tick(unsigned long dummy)
+{
+ struct timeval dummy_stamp;
+ net_profile_stamp(&dummy_stamp);
+ alpha_timer.expires = jiffies + 4*HZ;
+ add_timer(&alpha_timer);
+}
+
+#endif
+
+void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved)
+{
+ struct net_profile_slot *s;
+
+ net_profile_sub(entered, leaved);
+ for (s = net_profile_chain; s; s = s->next) {
+ if (s->active)
+ net_profile_add(leaved, &s->irq);
+ }
+}
+
+
+#ifdef CONFIG_PROC_FS
+static int profile_read_proc(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+{
+ off_t pos=0;
+ off_t begin=0;
+ int len=0;
+ struct net_profile_slot *s;
+
+ len+= sprintf(buffer, "Slot Hits Hi Lo OnIrqHi OnIrqLo Ufl\n");
+
+ if (offset == 0) {
+ cli();
+ net_prof_total.active = 1;
+ atomic_inc(&net_profile_active);
+ NET_PROFILE_LEAVE(total);
+ sti();
+ }
+ for (s = net_profile_chain; s; s = s->next) {
+ struct net_profile_slot tmp;
+
+ cli();
+ tmp = *s;
+
+ /* Wrong, but pretty close to truth */
+
+ s->accumulator.tv_sec = 0;
+ s->accumulator.tv_usec = 0;
+ s->irq.tv_sec = 0;
+ s->irq.tv_usec = 0;
+ s->hits = 0;
+ s->underflow = 0;
+ /* Repair active count, it is possible, only if code has a bug */
+ if (s->active) {
+ s->active = 0;
+ atomic_dec(&net_profile_active);
+ }
+ sti();
+
+ net_profile_sub(&tmp.irq, &tmp.accumulator);
+
+ len += sprintf(buffer+len,"%-15s %-10d %-10ld %-10lu %-10lu %-10lu %d/%d",
+ tmp.id,
+ tmp.hits,
+ tmp.accumulator.tv_sec,
+ tmp.accumulator.tv_usec,
+ tmp.irq.tv_sec,
+ tmp.irq.tv_usec,
+ tmp.underflow, tmp.active);
+
+ buffer[len++]='\n';
+
+ pos=begin+len;
+ if(pos<offset) {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ goto done;
+ }
+ *eof = 1;
+
+done:
+ *start=buffer+(offset-begin);
+ len-=(offset-begin);
+ if(len>length)
+ len=length;
+ if (len < 0) {
+ len = 0;
+ printk(KERN_CRIT "Yep, guys... our template for proc_*_read is crappy :-)\n");
+ }
+ if (offset == 0) {
+ cli();
+ net_prof_total.active = 0;
+ net_prof_total.hits = 0;
+ net_profile_stamp(&net_prof_total.entered);
+ sti();
+ }
+ return len;
+}
+#endif
+
+struct iphdr whitehole_iph;
+int whitehole_count;
+
+static int whitehole_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct net_device_stats *stats;
+ dev_kfree_skb(skb);
+ stats = (struct net_device_stats *)dev->priv;
+ stats->tx_packets++;
+ stats->tx_bytes+=skb->len;
+
+ return 0;
+}
+
+static void whitehole_inject(unsigned long);
+int whitehole_init(struct device *dev);
+
+static struct timer_list whitehole_timer =
+ { NULL, NULL, 0, 0L, whitehole_inject };
+
+static struct device whitehole_dev = {
+ "whitehole", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, whitehole_init, };
+
+static int whitehole_open(struct device *dev)
+{
+ whitehole_count = 100000;
+ whitehole_timer.expires = jiffies + 5*HZ;
+ add_timer(&whitehole_timer);
+ return 0;
+}
+
+static int whitehole_close(struct device *dev)
+{
+ del_timer(&whitehole_timer);
+ return 0;
+}
+
+static void whitehole_inject(unsigned long dummy)
+{
+ struct net_device_stats *stats = (struct net_device_stats *)whitehole_dev.priv;
+ extern int netdev_dropping;
+
+ do {
+ struct iphdr *iph;
+ struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
+ if (!skb)
+ break;
+ skb_reserve(skb, 32);
+ iph = (struct iphdr*)skb_put(skb, sizeof(*iph));
+ skb->mac.raw = ((u8*)iph) - 14;
+ memcpy(iph, &whitehole_iph, sizeof(*iph));
+ skb->protocol = __constant_htons(ETH_P_IP);
+ skb->dev = &whitehole_dev;
+ skb->pkt_type = PACKET_HOST;
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ netif_rx(skb);
+ whitehole_count--;
+ } while (netdev_dropping == 0 && whitehole_count>0);
+ if (whitehole_count > 0) {
+ whitehole_timer.expires = jiffies + 1;
+ add_timer(&whitehole_timer);
+ }
+}
+
+static struct net_device_stats *whitehole_get_stats(struct device *dev)
+{
+ struct net_device_stats *stats = (struct net_device_stats *) dev->priv;
+ return stats;
+}
+
+__initfunc(int whitehole_init(struct device *dev))
+{
+ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
+ if (dev->priv == NULL)
+ return -ENOBUFS;
+ memset(dev->priv, 0, sizeof(struct net_device_stats));
+ dev->get_stats = whitehole_get_stats;
+ dev->hard_start_xmit = whitehole_xmit;
+ dev->open = whitehole_open;
+ dev->stop = whitehole_close;
+ ether_setup(dev);
+ dev->tx_queue_len = 0;
+ dev->flags |= IFF_NOARP;
+ dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST);
+ dev->iflink = 0;
+ whitehole_iph.ihl = 5;
+ whitehole_iph.version = 4;
+ whitehole_iph.ttl = 2;
+ whitehole_iph.saddr = in_aton("193.233.7.21");
+ whitehole_iph.daddr = in_aton("193.233.7.10");
+ whitehole_iph.tot_len = htons(20);
+ whitehole_iph.check = ip_compute_csum((void *)&whitehole_iph, 20);
+ return 0;
+}
+
+int net_profile_register(struct net_profile_slot *slot)
+{
+ cli();
+ slot->next = net_profile_chain;
+ net_profile_chain = slot;
+ sti();
+ return 0;
+}
+
+int net_profile_unregister(struct net_profile_slot *slot)
+{
+ struct net_profile_slot **sp, *s;
+
+ for (sp = &net_profile_chain; (s = *sp) != NULL; sp = &s->next) {
+ if (s == slot) {
+ cli();
+ *sp = s->next;
+ sti();
+ return 0;
+ }
+ }
+ return -ESRCH;
+}
+
+
+__initfunc(int net_profile_init(void))
+{
+ int i;
+
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *ent;
+
+ ent = create_proc_entry("net/profile", 0, 0);
+ ent->read_proc = profile_read_proc;
+#endif
+
+ register_netdevice(&whitehole_dev);
+
+ printk("Evaluating net profiler cost ...");
+#if CPU == 586 || CPU == 686
+ if (!(boot_cpu_data.x86_capability & X86_FEATURE_TSC)) {
+ printk(KERN_ERR "Sorry, your CPU does not support TSC. Net profiler disabled.\n");
+ return -1;
+ }
+#endif
+ start_bh_atomic();
+#ifdef __alpha__
+ alpha_tick(0);
+#endif
+ for (i=0; i<1024; i++) {
+ NET_PROFILE_ENTER(total);
+ NET_PROFILE_LEAVE(total);
+ }
+ if (net_prof_total.accumulator.tv_sec) {
+ printk(" too high!\n");
+ } else {
+ net_profile_adjust.tv_usec = net_prof_total.accumulator.tv_usec>>10;
+ printk("%ld units\n", net_profile_adjust.tv_usec);
+ }
+ net_prof_total.hits = 0;
+ net_profile_stamp(&net_prof_total.entered);
+ end_bh_atomic();
+ return 0;
+}
+
+#endif
diff --git a/pfinet/linux-src/net/core/rtnetlink.c b/pfinet/linux-src/net/core/rtnetlink.c
new file mode 100644
index 00000000..7f89e54a
--- /dev/null
+++ b/pfinet/linux-src/net/core/rtnetlink.c
@@ -0,0 +1,512 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Routing netlink socket interface: protocol independent part.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ * Vitaly E. Lavrov RTA_OK arithmetics was wrong.
+ * Alexey Zhuravlev ifi_change does something useful
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/sockios.h>
+#include <linux/net.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/capability.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/string.h>
+
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/arp.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+atomic_t rtnl_rlockct;
+struct wait_queue *rtnl_wait;
+
+
+void rtnl_lock()
+{
+ rtnl_shlock();
+ rtnl_exlock();
+}
+
+void rtnl_unlock()
+{
+ rtnl_exunlock();
+ rtnl_shunlock();
+}
+
+int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
+{
+ memset(tb, 0, sizeof(struct rtattr*)*maxattr);
+
+ while (RTA_OK(rta, len)) {
+ unsigned flavor = rta->rta_type;
+ if (flavor && flavor <= maxattr)
+ tb[flavor-1] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_RTNETLINK
+struct sock *rtnl;
+
+unsigned long rtnl_wlockct;
+
+struct rtnetlink_link * rtnetlink_links[NPROTO];
+
+#define _S 1 /* superuser privileges required */
+#define _X 2 /* exclusive access to tables required */
+#define _G 4 /* GET request */
+
+static const int rtm_min[(RTM_MAX+1-RTM_BASE)/4] =
+{
+ NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+ NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
+ NLMSG_LENGTH(sizeof(struct rtmsg)),
+ NLMSG_LENGTH(sizeof(struct ndmsg)),
+ NLMSG_LENGTH(sizeof(struct rtmsg)),
+ NLMSG_LENGTH(sizeof(struct tcmsg)),
+ NLMSG_LENGTH(sizeof(struct tcmsg)),
+ NLMSG_LENGTH(sizeof(struct tcmsg))
+};
+
+static const int rta_max[(RTM_MAX+1-RTM_BASE)/4] =
+{
+ IFLA_MAX,
+ IFA_MAX,
+ RTA_MAX,
+ NDA_MAX,
+ RTA_MAX,
+ TCA_MAX,
+ TCA_MAX,
+ TCA_MAX
+};
+
+void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
+{
+ struct rtattr *rta;
+ int size = RTA_LENGTH(attrlen);
+
+ rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size));
+ rta->rta_type = attrtype;
+ rta->rta_len = size;
+ memcpy(RTA_DATA(rta), data, attrlen);
+}
+
+int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
+{
+ int err = 0;
+
+ NETLINK_CB(skb).dst_groups = group;
+ if (echo)
+ atomic_inc(&skb->users);
+ netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL);
+ if (echo)
+ err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
+ return err;
+}
+
+static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct device *dev,
+ int type, u32 pid, u32 seq, u32 change)
+{
+ struct ifinfomsg *r;
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
+ if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ r = NLMSG_DATA(nlh);
+ r->ifi_family = AF_UNSPEC;
+ r->ifi_type = dev->type;
+ r->ifi_index = dev->ifindex;
+ r->ifi_flags = dev->flags;
+ r->ifi_change = change;
+
+ RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+ if (dev->addr_len) {
+ RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
+ RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
+ }
+ if (1) {
+ unsigned mtu = dev->mtu;
+ RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
+ }
+ if (dev->ifindex != dev->iflink)
+ RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
+ if (dev->qdisc_sleeping)
+ RTA_PUT(skb, IFLA_QDISC,
+ strlen(dev->qdisc_sleeping->ops->id) + 1,
+ dev->qdisc_sleeping->ops->id);
+ if (dev->get_stats) {
+ struct net_device_stats *stats = dev->get_stats(dev);
+ if (stats)
+ RTA_PUT(skb, IFLA_STATS, sizeof(*stats), stats);
+ }
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx;
+ int s_idx = cb->args[0];
+ struct device *dev;
+
+ for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+ if (idx < s_idx)
+ continue;
+ if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
+ break;
+ }
+ cb->args[0] = idx;
+
+ return skb->len;
+}
+
+int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx;
+ int s_idx = cb->family;
+
+ if (s_idx == 0)
+ s_idx = 1;
+ for (idx=1; idx<NPROTO; idx++) {
+ int type = cb->nlh->nlmsg_type-RTM_BASE;
+ if (idx < s_idx || idx == PF_PACKET)
+ continue;
+ if (rtnetlink_links[idx] == NULL ||
+ rtnetlink_links[idx][type].dumpit == NULL)
+ continue;
+ if (idx > s_idx)
+ memset(&cb->args[0], 0, sizeof(cb->args));
+ if (rtnetlink_links[idx][type].dumpit(skb, cb) == 0)
+ continue;
+ if (skb_tailroom(skb) < 256)
+ break;
+ }
+ cb->family = idx;
+
+ return skb->len;
+}
+
+void rtmsg_ifinfo(int type, struct device *dev)
+{
+ struct sk_buff *skb;
+ int size = NLMSG_GOODSIZE;
+
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb)
+ return;
+
+ if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, ~0U) < 0) {
+ kfree_skb(skb);
+ return;
+ }
+ NETLINK_CB(skb).dst_groups = RTMGRP_LINK;
+ netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_KERNEL);
+}
+
+static int rtnetlink_done(struct netlink_callback *cb)
+{
+ if (cap_raised(NETLINK_CB(cb->skb).eff_cap, CAP_NET_ADMIN) && cb->nlh->nlmsg_flags&NLM_F_ATOMIC)
+ rtnl_shunlock();
+ return 0;
+}
+
+/* Process one rtnetlink message. */
+
+extern __inline__ int
+rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
+{
+ struct rtnetlink_link *link;
+ struct rtnetlink_link *link_tab;
+ struct rtattr *rta[RTATTR_MAX];
+
+ int exclusive = 0;
+ int sz_idx, kind;
+ int min_len;
+ int family;
+ int type;
+ int err;
+
+ /* Only requests are handled by kernel now */
+ if (!(nlh->nlmsg_flags&NLM_F_REQUEST))
+ return 0;
+
+ type = nlh->nlmsg_type;
+
+ /* A control message: ignore them */
+ if (type < RTM_BASE)
+ return 0;
+
+ /* Unknown message: reply with EINVAL */
+ if (type > RTM_MAX)
+ goto err_inval;
+
+ type -= RTM_BASE;
+
+ /* All the messages must have at least 1 byte length */
+ if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg)))
+ return 0;
+
+ family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family;
+ if (family > NPROTO) {
+ *errp = -EAFNOSUPPORT;
+ return -1;
+ }
+
+ link_tab = rtnetlink_links[family];
+ if (link_tab == NULL)
+ link_tab = rtnetlink_links[PF_UNSPEC];
+ link = &link_tab[type];
+
+ sz_idx = type>>2;
+ kind = type&3;
+
+ if (kind != 2 && !cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) {
+ *errp = -EPERM;
+ return -1;
+ }
+
+ if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
+ u32 rlen;
+
+ if (link->dumpit == NULL)
+ link = &(rtnetlink_links[PF_UNSPEC][type]);
+
+ if (link->dumpit == NULL)
+ goto err_inval;
+
+ /* Super-user locks all the tables to get atomic snapshot */
+ if (cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)
+ && nlh->nlmsg_flags&NLM_F_ATOMIC)
+ atomic_inc(&rtnl_rlockct);
+ if ((*errp = netlink_dump_start(rtnl, skb, nlh,
+ link->dumpit,
+ rtnetlink_done)) != 0) {
+ if (cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN) && nlh->nlmsg_flags&NLM_F_ATOMIC)
+ atomic_dec(&rtnl_rlockct);
+ return -1;
+ }
+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (rlen > skb->len)
+ rlen = skb->len;
+ skb_pull(skb, rlen);
+ return -1;
+ }
+
+ if (kind != 2) {
+ if (rtnl_exlock_nowait()) {
+ *errp = 0;
+ return -1;
+ }
+ exclusive = 1;
+ }
+
+ memset(&rta, 0, sizeof(rta));
+
+ min_len = rtm_min[sz_idx];
+ if (nlh->nlmsg_len < min_len)
+ goto err_inval;
+
+ if (nlh->nlmsg_len > min_len) {
+ int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
+ struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len);
+
+ while (RTA_OK(attr, attrlen)) {
+ unsigned flavor = attr->rta_type;
+ if (flavor) {
+ if (flavor > rta_max[sz_idx])
+ goto err_inval;
+ rta[flavor-1] = attr;
+ }
+ attr = RTA_NEXT(attr, attrlen);
+ }
+ }
+
+ if (link->doit == NULL)
+ link = &(rtnetlink_links[PF_UNSPEC][type]);
+ if (link->doit == NULL)
+ goto err_inval;
+ err = link->doit(skb, nlh, (void *)&rta);
+
+ if (exclusive)
+ rtnl_exunlock();
+ *errp = err;
+ return err;
+
+err_inval:
+ if (exclusive)
+ rtnl_exunlock();
+ *errp = -EINVAL;
+ return -1;
+}
+
+/*
+ * Process one packet of messages.
+ * Malformed skbs with wrong lengths of messages are discarded silently.
+ */
+
+extern __inline__ int rtnetlink_rcv_skb(struct sk_buff *skb)
+{
+ int err;
+ struct nlmsghdr * nlh;
+
+ while (skb->len >= NLMSG_SPACE(0)) {
+ u32 rlen;
+
+ nlh = (struct nlmsghdr *)skb->data;
+ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+ return 0;
+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (rlen > skb->len)
+ rlen = skb->len;
+ if (rtnetlink_rcv_msg(skb, nlh, &err)) {
+ /* Not error, but we must interrupt processing here:
+ * Note, that in this case we do not pull message
+ * from skb, it will be processed later.
+ */
+ if (err == 0)
+ return -1;
+ netlink_ack(skb, nlh, err);
+ } else if (nlh->nlmsg_flags&NLM_F_ACK)
+ netlink_ack(skb, nlh, 0);
+ skb_pull(skb, rlen);
+ }
+
+ return 0;
+}
+
+/*
+ * rtnetlink input queue processing routine:
+ * - try to acquire shared lock. If it is failed, defer processing.
+ * - feed skbs to rtnetlink_rcv_skb, until it refuse a message,
+ * that will occur, when a dump started and/or acquisition of
+ * exclusive lock failed.
+ */
+
+static void rtnetlink_rcv(struct sock *sk, int len)
+{
+ struct sk_buff *skb;
+
+ if (rtnl_shlock_nowait())
+ return;
+
+ while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
+ if (rtnetlink_rcv_skb(skb)) {
+ if (skb->len)
+ skb_queue_head(&sk->receive_queue, skb);
+ else
+ kfree_skb(skb);
+ break;
+ }
+ kfree_skb(skb);
+ }
+
+ rtnl_shunlock();
+}
+
+static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
+{
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, rtnetlink_dump_ifinfo, },
+ { NULL, NULL, },
+
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, rtnetlink_dump_all, },
+ { NULL, NULL, },
+
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, rtnetlink_dump_all, },
+ { NULL, NULL, },
+
+ { neigh_add, NULL, },
+ { neigh_delete, NULL, },
+ { NULL, neigh_dump_info, },
+ { NULL, NULL, },
+
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+};
+
+
+static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct device *dev = ptr;
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ rtmsg_ifinfo(RTM_DELLINK, dev);
+ break;
+ default:
+ rtmsg_ifinfo(RTM_NEWLINK, dev);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+struct notifier_block rtnetlink_dev_notifier = {
+ rtnetlink_event,
+ NULL,
+ 0
+};
+
+
+__initfunc(void rtnetlink_init(void))
+{
+#ifdef RTNL_DEBUG
+ printk("Initializing RT netlink socket\n");
+#endif
+ rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv);
+ if (rtnl == NULL)
+ panic("rtnetlink_init: cannot initialize rtnetlink\n");
+ register_netdevice_notifier(&rtnetlink_dev_notifier);
+ rtnetlink_links[PF_UNSPEC] = link_rtnetlink_table;
+ rtnetlink_links[PF_PACKET] = link_rtnetlink_table;
+}
+
+
+
+#endif
diff --git a/pfinet/linux-src/net/core/scm.c b/pfinet/linux-src/net/core/scm.c
new file mode 100644
index 00000000..cdb5f3d0
--- /dev/null
+++ b/pfinet/linux-src/net/core/scm.c
@@ -0,0 +1,280 @@
+/* scm.c - Socket level control messages processing.
+ *
+ * Author: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ * Alignment and value checking mods by Craig Metz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/net.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <linux/inet.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/rarp.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/scm.h>
+
+
+/*
+ * Only allow a user to send credentials, that they could set with
+ * setu(g)id.
+ */
+
+static __inline__ int scm_check_creds(struct ucred *creds)
+{
+ if ((creds->pid == current->pid || capable(CAP_SYS_ADMIN)) &&
+ ((creds->uid == current->uid || creds->uid == current->euid ||
+ creds->uid == current->suid) || capable(CAP_SETUID)) &&
+ ((creds->gid == current->gid || creds->gid == current->egid ||
+ creds->gid == current->sgid) || capable(CAP_SETGID))) {
+ return 0;
+ }
+ return -EPERM;
+}
+
+static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
+{
+ int *fdp = (int*)CMSG_DATA(cmsg);
+ struct scm_fp_list *fpl = *fplp;
+ struct file **fpp;
+ int i, num;
+
+ num = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)))/sizeof(int);
+
+ if (num <= 0)
+ return 0;
+
+ if (num > SCM_MAX_FD)
+ return -EINVAL;
+
+ if (!fpl)
+ {
+ fpl = kmalloc(sizeof(struct scm_fp_list), GFP_KERNEL);
+ if (!fpl)
+ return -ENOMEM;
+ *fplp = fpl;
+ fpl->count = 0;
+ }
+ fpp = &fpl->fp[fpl->count];
+
+ if (fpl->count + num > SCM_MAX_FD)
+ return -EINVAL;
+
+ /*
+ * Verify the descriptors and increment the usage count.
+ */
+
+ for (i=0; i< num; i++)
+ {
+ int fd = fdp[i];
+ struct file *file;
+
+ if (fd < 0 || !(file = fget(fd)))
+ return -EBADF;
+ *fpp++ = file;
+ fpl->count++;
+ }
+ return num;
+}
+
+void __scm_destroy(struct scm_cookie *scm)
+{
+ struct scm_fp_list *fpl = scm->fp;
+ int i;
+
+ if (fpl) {
+ scm->fp = NULL;
+ for (i=fpl->count-1; i>=0; i--)
+ fput(fpl->fp[i]);
+ kfree(fpl);
+ }
+}
+
+int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
+{
+ struct cmsghdr *cmsg;
+ int err;
+
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg))
+ {
+ err = -EINVAL;
+
+ /* Verify that cmsg_len is at least sizeof(struct cmsghdr) */
+ /* The first check was omitted in <= 2.2.5. The reasoning was
+ that parser checks cmsg_len in any case, so that
+ additional check would be work duplication.
+ But if cmsg_level is not SOL_SOCKET, we do not check
+ for too short ancillary data object at all! Oops.
+ OK, let's add it...
+ */
+ if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
+ (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ + cmsg->cmsg_len) > msg->msg_controllen)
+ goto error;
+
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ continue;
+
+ switch (cmsg->cmsg_type)
+ {
+ case SCM_RIGHTS:
+ err=scm_fp_copy(cmsg, &p->fp);
+ if (err<0)
+ goto error;
+ break;
+ case SCM_CREDENTIALS:
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
+ goto error;
+ memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred));
+ err = scm_check_creds(&p->creds);
+ if (err)
+ goto error;
+ break;
+ default:
+ goto error;
+ }
+ }
+
+ if (p->fp && !p->fp->count)
+ {
+ kfree(p->fp);
+ p->fp = NULL;
+ }
+
+ err = -EINVAL;
+ if (msg->msg_flags & MSG_CTLFLAGS)
+ goto error;
+
+ return 0;
+
+error:
+ scm_destroy(p);
+ return err;
+}
+
+int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
+{
+ struct cmsghdr *cm = (struct cmsghdr*)msg->msg_control;
+ struct cmsghdr cmhdr;
+ int cmlen = CMSG_LEN(len);
+ int err;
+
+ if (cm==NULL || msg->msg_controllen < sizeof(*cm)) {
+ msg->msg_flags |= MSG_CTRUNC;
+ return 0; /* XXX: return error? check spec. */
+ }
+ if (msg->msg_controllen < cmlen) {
+ msg->msg_flags |= MSG_CTRUNC;
+ cmlen = msg->msg_controllen;
+ }
+ cmhdr.cmsg_level = level;
+ cmhdr.cmsg_type = type;
+ cmhdr.cmsg_len = cmlen;
+
+ err = -EFAULT;
+ if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
+ goto out;
+ if (copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr)))
+ goto out;
+ cmlen = CMSG_SPACE(len);
+ msg->msg_control += cmlen;
+ msg->msg_controllen -= cmlen;
+ err = 0;
+out:
+ return err;
+}
+
+void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
+{
+ struct cmsghdr *cm = (struct cmsghdr*)msg->msg_control;
+
+ int fdmax = (msg->msg_controllen - sizeof(struct cmsghdr))/sizeof(int);
+ int fdnum = scm->fp->count;
+ struct file **fp = scm->fp->fp;
+ int *cmfptr;
+ int err = 0, i;
+
+ if (fdnum < fdmax)
+ fdmax = fdnum;
+
+ for (i=0, cmfptr=(int*)CMSG_DATA(cm); i<fdmax; i++, cmfptr++)
+ {
+ int new_fd;
+ err = get_unused_fd();
+ if (err < 0)
+ break;
+ new_fd = err;
+ err = put_user(new_fd, cmfptr);
+ if (err) {
+ put_unused_fd(new_fd);
+ break;
+ }
+ /* Bump the usage count and install the file. */
+ fp[i]->f_count++;
+ current->files->fd[new_fd] = fp[i];
+ }
+
+ if (i > 0)
+ {
+ int cmlen = CMSG_LEN(i*sizeof(int));
+ if (!err)
+ err = put_user(SOL_SOCKET, &cm->cmsg_level);
+ if (!err)
+ err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+ if (!err)
+ err = put_user(cmlen, &cm->cmsg_len);
+ if (!err) {
+ cmlen = CMSG_SPACE(i*sizeof(int));
+ msg->msg_control += cmlen;
+ msg->msg_controllen -= cmlen;
+ }
+ }
+ if (i < fdnum)
+ msg->msg_flags |= MSG_CTRUNC;
+
+ /*
+ * All of the files that fit in the message have had their
+ * usage counts incremented, so we just free the list.
+ */
+ __scm_destroy(scm);
+}
+
+struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
+{
+ struct scm_fp_list *new_fpl;
+ int i;
+
+ if (!fpl)
+ return NULL;
+
+ new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
+ if (new_fpl) {
+ memcpy(new_fpl, fpl, sizeof(*fpl));
+
+ for (i=fpl->count-1; i>=0; i--)
+ fpl->fp[i]->f_count++;
+ }
+ return new_fpl;
+}
diff --git a/pfinet/linux-src/net/core/skbuff.c b/pfinet/linux-src/net/core/skbuff.c
new file mode 100644
index 00000000..b7636437
--- /dev/null
+++ b/pfinet/linux-src/net/core/skbuff.c
@@ -0,0 +1,385 @@
+/*
+ * Routines having to do with the 'struct sk_buff' memory handlers.
+ *
+ * Authors: Alan Cox <iiitac@pyr.swan.ac.uk>
+ * Florian La Roche <rzsfl@rz.uni-sb.de>
+ *
+ * Version: $Id: skbuff.c,v 1.55 1999/02/23 08:12:27 davem Exp $
+ *
+ * Fixes:
+ * Alan Cox : Fixed the worst of the load balancer bugs.
+ * Dave Platt : Interrupt stacking fix.
+ * Richard Kooijman : Timestamp fixes.
+ * Alan Cox : Changed buffer format.
+ * Alan Cox : destructor hook for AF_UNIX etc.
+ * Linus Torvalds : Better skb_clone.
+ * Alan Cox : Added skb_copy.
+ * Alan Cox : Added all the changed routines Linus
+ * only put in the headers
+ * Ray VanTassle : Fixed --skb->lock in free
+ * Alan Cox : skb_copy copy arp field
+ * Andi Kleen : slabified it.
+ *
+ * NOTE:
+ * The __skb_ routines should be called with interrupts
+ * disabled, or you better be *real* sure that the operation is atomic
+ * with respect to whatever list is being frobbed (e.g. via lock_sock()
+ * or via disabling bottom half handlers, etc).
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * The functions in this file will not compile correctly with gcc 2.4.x
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/malloc.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/dst.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/sock.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+/*
+ * Skb list spinlock
+ */
+spinlock_t skb_queue_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Resource tracking variables
+ */
+
+static atomic_t net_skbcount = ATOMIC_INIT(0);
+static atomic_t net_allocs = ATOMIC_INIT(0);
+static atomic_t net_fails = ATOMIC_INIT(0);
+
+extern atomic_t ip_frag_mem;
+
+static kmem_cache_t *skbuff_head_cache;
+
+/*
+ * Keep out-of-line to prevent kernel bloat.
+ * __builtin_return_address is not used because it is not always
+ * reliable.
+ */
+
+void skb_over_panic(struct sk_buff *skb, int sz, void *here)
+{
+ panic("skput:over: %p:%d put:%d dev:%s",
+ here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
+}
+
+void skb_under_panic(struct sk_buff *skb, int sz, void *here)
+{
+ panic("skput:under: %p:%d put:%d dev:%s",
+ here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
+}
+
+void show_net_buffers(void)
+{
+ printk("Networking buffers in use : %u\n",
+ atomic_read(&net_skbcount));
+ printk("Total network buffer allocations : %u\n",
+ atomic_read(&net_allocs));
+ printk("Total failed network buffer allocs : %u\n",
+ atomic_read(&net_fails));
+#ifdef CONFIG_INET
+ printk("IP fragment buffer size : %u\n",
+ atomic_read(&ip_frag_mem));
+#endif
+}
+
+/* Allocate a new skbuff. We do this ourselves so we can fill in a few
+ * 'private' fields and also do memory statistics to find all the
+ * [BEEP] leaks.
+ *
+ */
+
+struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
+{
+ struct sk_buff *skb;
+ u8 *data;
+
+ if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
+ static int count = 0;
+ if (++count < 5) {
+ printk(KERN_ERR "alloc_skb called nonatomically "
+ "from interrupt %p\n", __builtin_return_address(0));
+ }
+ gfp_mask &= ~__GFP_WAIT;
+ }
+
+ /* Get the HEAD */
+ skb = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
+ if (skb == NULL)
+ goto nohead;
+
+ /* Get the DATA. Size must match skb_add_mtu(). */
+ size = ((size + 15) & ~15);
+ data = kmalloc(size + sizeof(atomic_t), gfp_mask);
+ if (data == NULL)
+ goto nodata;
+
+ /* Note that this counter is useless now - you can just look in the
+ * skbuff_head entry in /proc/slabinfo. We keep it only for emergency
+ * cases.
+ */
+ atomic_inc(&net_allocs);
+
+ skb->truesize = size;
+
+ atomic_inc(&net_skbcount);
+
+ /* Load the data pointers. */
+ skb->head = data;
+ skb->data = data;
+ skb->tail = data;
+ skb->end = data + size;
+
+ /* Set up other state */
+ skb->len = 0;
+ skb->is_clone = 0;
+ skb->cloned = 0;
+
+ atomic_set(&skb->users, 1);
+ atomic_set(skb_datarefp(skb), 1);
+ return skb;
+
+nodata:
+ kmem_cache_free(skbuff_head_cache, skb);
+nohead:
+ atomic_inc(&net_fails);
+ return NULL;
+}
+
+
+/*
+ * Slab constructor for a skb head.
+ */
+static inline void skb_headerinit(void *p, kmem_cache_t *cache,
+ unsigned long flags)
+{
+ struct sk_buff *skb = p;
+
+ skb->destructor = NULL;
+ skb->pkt_type = PACKET_HOST; /* Default type */
+ skb->pkt_bridged = 0; /* Not bridged */
+ skb->prev = skb->next = NULL;
+ skb->list = NULL;
+ skb->sk = NULL;
+ skb->stamp.tv_sec=0; /* No idea about time */
+ skb->ip_summed = 0;
+ skb->security = 0; /* By default packets are insecure */
+ skb->dst = NULL;
+#ifdef CONFIG_IP_FIREWALL
+ skb->fwmark = 0;
+#endif
+ memset(skb->cb, 0, sizeof(skb->cb));
+ skb->priority = 0;
+}
+
+/*
+ * Free an skbuff by memory without cleaning the state.
+ */
+void kfree_skbmem(struct sk_buff *skb)
+{
+ if (!skb->cloned || atomic_dec_and_test(skb_datarefp(skb)))
+ kfree(skb->head);
+
+ kmem_cache_free(skbuff_head_cache, skb);
+ atomic_dec(&net_skbcount);
+}
+
+/*
+ * Free an sk_buff. Release anything attached to the buffer. Clean the state.
+ */
+
+void __kfree_skb(struct sk_buff *skb)
+{
+ if (skb->list)
+ printk(KERN_WARNING "Warning: kfree_skb passed an skb still "
+ "on a list (from %p).\n", __builtin_return_address(0));
+
+ dst_release(skb->dst);
+ if(skb->destructor)
+ skb->destructor(skb);
+ skb_headerinit(skb, NULL, 0); /* clean state */
+ kfree_skbmem(skb);
+}
+
+/*
+ * Duplicate an sk_buff. The new one is not owned by a socket.
+ */
+
+struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
+{
+ struct sk_buff *n;
+
+ n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
+ if (!n)
+ return NULL;
+
+ memcpy(n, skb, sizeof(*n));
+ atomic_inc(skb_datarefp(skb));
+ skb->cloned = 1;
+
+ atomic_inc(&net_allocs);
+ atomic_inc(&net_skbcount);
+ dst_clone(n->dst);
+ n->cloned = 1;
+ n->next = n->prev = NULL;
+ n->list = NULL;
+ n->sk = NULL;
+ n->is_clone = 1;
+ atomic_set(&n->users, 1);
+ n->destructor = NULL;
+ return n;
+}
+
+/*
+ * This is slower, and copies the whole data area
+ */
+
+struct sk_buff *skb_copy(struct sk_buff *skb, int gfp_mask)
+{
+ struct sk_buff *n;
+ unsigned long offset;
+
+ /*
+ * Allocate the copy buffer
+ */
+
+ n=alloc_skb(skb->end - skb->head, gfp_mask);
+ if(n==NULL)
+ return NULL;
+
+ /*
+ * Shift between the two data areas in bytes
+ */
+
+ offset=n->head-skb->head;
+
+ /* Set the data pointer */
+ skb_reserve(n,skb->data-skb->head);
+ /* Set the tail pointer and length */
+ skb_put(n,skb->len);
+ /* Copy the bytes */
+ memcpy(n->head,skb->head,skb->end-skb->head);
+ n->csum = skb->csum;
+ n->list=NULL;
+ n->sk=NULL;
+ n->dev=skb->dev;
+ n->priority=skb->priority;
+ n->protocol=skb->protocol;
+ n->dst=dst_clone(skb->dst);
+ n->h.raw=skb->h.raw+offset;
+ n->nh.raw=skb->nh.raw+offset;
+ n->mac.raw=skb->mac.raw+offset;
+ memcpy(n->cb, skb->cb, sizeof(skb->cb));
+ n->used=skb->used;
+ n->is_clone=0;
+ atomic_set(&n->users, 1);
+ n->pkt_type=skb->pkt_type;
+ n->stamp=skb->stamp;
+ n->destructor = NULL;
+ n->security=skb->security;
+#ifdef CONFIG_IP_FIREWALL
+ n->fwmark = skb->fwmark;
+#endif
+ return n;
+}
+
+struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, int newheadroom)
+{
+ struct sk_buff *n;
+ unsigned long offset;
+ int headroom = skb_headroom(skb);
+
+ /*
+ * Allocate the copy buffer
+ */
+
+ n=alloc_skb(skb->truesize+newheadroom-headroom, GFP_ATOMIC);
+ if(n==NULL)
+ return NULL;
+
+ skb_reserve(n,newheadroom);
+
+ /*
+ * Shift between the two data areas in bytes
+ */
+
+ offset=n->data-skb->data;
+
+ /* Set the tail pointer and length */
+ skb_put(n,skb->len);
+ /* Copy the bytes */
+ memcpy(n->data,skb->data,skb->len);
+ n->list=NULL;
+ n->sk=NULL;
+ n->priority=skb->priority;
+ n->protocol=skb->protocol;
+ n->dev=skb->dev;
+ n->dst=dst_clone(skb->dst);
+ n->h.raw=skb->h.raw+offset;
+ n->nh.raw=skb->nh.raw+offset;
+ n->mac.raw=skb->mac.raw+offset;
+ memcpy(n->cb, skb->cb, sizeof(skb->cb));
+ n->used=skb->used;
+ n->is_clone=0;
+ atomic_set(&n->users, 1);
+ n->pkt_type=skb->pkt_type;
+ n->stamp=skb->stamp;
+ n->destructor = NULL;
+ n->security=skb->security;
+#ifdef CONFIG_IP_FIREWALL
+ n->fwmark = skb->fwmark;
+#endif
+
+ return n;
+}
+
+#if 0
+/*
+ * Tune the memory allocator for a new MTU size.
+ */
+void skb_add_mtu(int mtu)
+{
+ /* Must match allocation in alloc_skb */
+ mtu = ((mtu + 15) & ~15) + sizeof(atomic_t);
+
+ kmem_add_cache_size(mtu);
+}
+#endif
+
+void __init skb_init(void)
+{
+ skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
+ sizeof(struct sk_buff),
+ 0,
+ SLAB_HWCACHE_ALIGN,
+ skb_headerinit, NULL);
+ if (!skbuff_head_cache)
+ panic("cannot create skbuff cache");
+}
diff --git a/pfinet/linux-src/net/core/sock.c b/pfinet/linux-src/net/core/sock.c
new file mode 100644
index 00000000..e0eb41a0
--- /dev/null
+++ b/pfinet/linux-src/net/core/sock.c
@@ -0,0 +1,1051 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Generic socket support routines. Memory allocators, socket lock/release
+ * handler for protocols to use and generic option handler.
+ *
+ *
+ * Version: $Id: sock.c,v 1.80 1999/05/08 03:04:34 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Alan Cox, <A.Cox@swansea.ac.uk>
+ *
+ * Fixes:
+ * Alan Cox : Numerous verify_area() problems
+ * Alan Cox : Connecting on a connecting socket
+ * now returns an error for tcp.
+ * Alan Cox : sock->protocol is set correctly.
+ * and is not sometimes left as 0.
+ * Alan Cox : connect handles icmp errors on a
+ * connect properly. Unfortunately there
+ * is a restart syscall nasty there. I
+ * can't match BSD without hacking the C
+ * library. Ideas urgently sought!
+ * Alan Cox : Disallow bind() to addresses that are
+ * not ours - especially broadcast ones!!
+ * Alan Cox : Socket 1024 _IS_ ok for users. (fencepost)
+ * Alan Cox : sock_wfree/sock_rfree don't destroy sockets,
+ * instead they leave that for the DESTROY timer.
+ * Alan Cox : Clean up error flag in accept
+ * Alan Cox : TCP ack handling is buggy, the DESTROY timer
+ * was buggy. Put a remove_sock() in the handler
+ * for memory when we hit 0. Also altered the timer
+ * code. The ACK stuff can wait and needs major
+ * TCP layer surgery.
+ * Alan Cox : Fixed TCP ack bug, removed remove sock
+ * and fixed timer/inet_bh race.
+ * Alan Cox : Added zapped flag for TCP
+ * Alan Cox : Move kfree_skb into skbuff.c and tidied up surplus code
+ * Alan Cox : for new sk_buff allocations wmalloc/rmalloc now call alloc_skb
+ * Alan Cox : kfree_s calls now are kfree_skbmem so we can track skb resources
+ * Alan Cox : Supports socket option broadcast now as does udp. Packet and raw need fixing.
+ * Alan Cox : Added RCVBUF,SNDBUF size setting. It suddenly occurred to me how easy it was so...
+ * Rick Sladkey : Relaxed UDP rules for matching packets.
+ * C.E.Hawkins : IFF_PROMISC/SIOCGHWADDR support
+ * Pauline Middelink : identd support
+ * Alan Cox : Fixed connect() taking signals I think.
+ * Alan Cox : SO_LINGER supported
+ * Alan Cox : Error reporting fixes
+ * Anonymous : inet_create tidied up (sk->reuse setting)
+ * Alan Cox : inet sockets don't set sk->type!
+ * Alan Cox : Split socket option code
+ * Alan Cox : Callbacks
+ * Alan Cox : Nagle flag for Charles & Johannes stuff
+ * Alex : Removed restriction on inet fioctl
+ * Alan Cox : Splitting INET from NET core
+ * Alan Cox : Fixed bogus SO_TYPE handling in getsockopt()
+ * Adam Caldwell : Missing return in SO_DONTROUTE/SO_DEBUG code
+ * Alan Cox : Split IP from generic code
+ * Alan Cox : New kfree_skbmem()
+ * Alan Cox : Make SO_DEBUG superuser only.
+ * Alan Cox : Allow anyone to clear SO_DEBUG
+ * (compatibility fix)
+ * Alan Cox : Added optimistic memory grabbing for AF_UNIX throughput.
+ * Alan Cox : Allocator for a socket is settable.
+ * Alan Cox : SO_ERROR includes soft errors.
+ * Alan Cox : Allow NULL arguments on some SO_ opts
+ * Alan Cox : Generic socket allocation to make hooks
+ * easier (suggested by Craig Metz).
+ * Michael Pall : SO_ERROR returns positive errno again
+ * Steve Whitehouse: Added default destructor to free
+ * protocol private data.
+ * Steve Whitehouse: Added various other default routines
+ * common to several socket families.
+ * Chris Evans : Call suser() check last on F_SETOWN
+ * Jay Schulist : Added SO_ATTACH_FILTER and SO_DETACH_FILTER.
+ * Andi Kleen : Add sock_kmalloc()/sock_kfree_s()
+ * Andi Kleen : Fix write_space callback
+ *
+ * To Fix:
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/sockios.h>
+#include <linux/net.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/arp.h>
+#include <net/rarp.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/raw.h>
+#include <net/icmp.h>
+#include <linux/ipsec.h>
+
+#ifdef CONFIG_FILTER
+#include <linux/filter.h>
+#endif
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+/* Run time adjustable parameters. */
+__u32 sysctl_wmem_max = SK_WMEM_MAX;
+__u32 sysctl_rmem_max = SK_RMEM_MAX;
+__u32 sysctl_wmem_default = SK_WMEM_MAX;
+__u32 sysctl_rmem_default = SK_RMEM_MAX;
+
+/* Maximal space eaten by iovec or ancilliary data plus some space */
+int sysctl_optmem_max = sizeof(unsigned long)*(2*UIO_MAXIOV + 512);
+
+/*
+ * This is meant for all protocols to use and covers goings on
+ * at the socket level. Everything here is generic.
+ */
+
+int sock_setsockopt(struct socket *sock, int level, int optname,
+ char *optval, int optlen)
+{
+ struct sock *sk=sock->sk;
+#ifdef CONFIG_FILTER
+ struct sk_filter *filter;
+#endif
+ int val;
+ int valbool;
+ int err;
+ struct linger ling;
+ int ret = 0;
+
+ /*
+ * Options without arguments
+ */
+
+#ifdef SO_DONTLINGER /* Compatibility item... */
+ switch(optname)
+ {
+ case SO_DONTLINGER:
+ sk->linger=0;
+ return 0;
+ }
+#endif
+
+ if(optlen<sizeof(int))
+ return(-EINVAL);
+
+ err = get_user(val, (int *)optval);
+ if (err)
+ return err;
+
+ valbool = val?1:0;
+
+ switch(optname)
+ {
+ case SO_DEBUG:
+ if(val && !capable(CAP_NET_ADMIN))
+ {
+ ret = -EACCES;
+ }
+ else
+ sk->debug=valbool;
+ break;
+ case SO_REUSEADDR:
+ sk->reuse = valbool;
+ break;
+ case SO_TYPE:
+ case SO_ERROR:
+ ret = -ENOPROTOOPT;
+ break;
+ case SO_DONTROUTE:
+ sk->localroute=valbool;
+ break;
+ case SO_BROADCAST:
+ sk->broadcast=valbool;
+ break;
+ case SO_SNDBUF:
+ /* Don't error on this BSD doesn't and if you think
+ about it this is right. Otherwise apps have to
+ play 'guess the biggest size' games. RCVBUF/SNDBUF
+ are treated in BSD as hints */
+
+ if (val > sysctl_wmem_max)
+ val = sysctl_wmem_max;
+
+ sk->sndbuf = max(val*2,2048);
+
+ /*
+ * Wake up sending tasks if we
+ * upped the value.
+ */
+ sk->write_space(sk);
+ break;
+
+ case SO_RCVBUF:
+ /* Don't error on this BSD doesn't and if you think
+ about it this is right. Otherwise apps have to
+ play 'guess the biggest size' games. RCVBUF/SNDBUF
+ are treated in BSD as hints */
+
+ if (val > sysctl_rmem_max)
+ val = sysctl_rmem_max;
+
+ /* FIXME: is this lower bound the right one? */
+ sk->rcvbuf = max(val*2,256);
+ break;
+
+ case SO_KEEPALIVE:
+#ifdef CONFIG_INET
+ if (sk->protocol == IPPROTO_TCP)
+ {
+ tcp_set_keepalive(sk, valbool);
+ }
+#endif
+ sk->keepopen = valbool;
+ break;
+
+ case SO_OOBINLINE:
+ sk->urginline = valbool;
+ break;
+
+ case SO_NO_CHECK:
+ sk->no_check = valbool;
+ break;
+
+ case SO_PRIORITY:
+ if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN))
+ sk->priority = val;
+ else
+ return(-EPERM);
+ break;
+
+ case SO_LINGER:
+ if(optlen<sizeof(ling))
+ return -EINVAL; /* 1003.1g */
+ err = copy_from_user(&ling,optval,sizeof(ling));
+ if (err)
+ {
+ ret = -EFAULT;
+ break;
+ }
+ if(ling.l_onoff==0)
+ sk->linger=0;
+ else
+ {
+ sk->lingertime=ling.l_linger;
+ sk->linger=1;
+ }
+ break;
+
+ case SO_BSDCOMPAT:
+ sk->bsdism = valbool;
+ break;
+
+ case SO_PASSCRED:
+ sock->passcred = valbool;
+ break;
+
+
+#ifdef CONFIG_NETDEVICES
+ case SO_BINDTODEVICE:
+ {
+ char devname[IFNAMSIZ];
+
+ /* Sorry... */
+ if (!capable(CAP_NET_RAW))
+ return -EPERM;
+
+ /* Bind this socket to a particular device like "eth0",
+ * as specified in the passed interface name. If the
+ * name is "" or the option length is zero the socket
+ * is not bound.
+ */
+
+ if (!valbool) {
+ sk->bound_dev_if = 0;
+ } else {
+ if (optlen > IFNAMSIZ)
+ optlen = IFNAMSIZ;
+ if (copy_from_user(devname, optval, optlen))
+ return -EFAULT;
+
+ /* Remove any cached route for this socket. */
+ lock_sock(sk);
+ dst_release(xchg(&sk->dst_cache, NULL));
+ release_sock(sk);
+
+ if (devname[0] == '\0') {
+ sk->bound_dev_if = 0;
+ } else {
+ struct device *dev = dev_get(devname);
+ if (!dev)
+ return -EINVAL;
+ sk->bound_dev_if = dev->ifindex;
+ }
+ return 0;
+ }
+ }
+#endif
+
+
+#ifdef CONFIG_FILTER
+ case SO_ATTACH_FILTER:
+ ret = -EINVAL;
+ if (optlen == sizeof(struct sock_fprog)) {
+ struct sock_fprog fprog;
+
+ ret = -EFAULT;
+ if (copy_from_user(&fprog, optval, sizeof(fprog)))
+ break;
+
+ ret = sk_attach_filter(&fprog, sk);
+ }
+ break;
+
+ case SO_DETACH_FILTER:
+ filter = sk->filter;
+ if(filter) {
+ sk->filter = NULL;
+ synchronize_bh();
+ sk_filter_release(sk, filter);
+ return 0;
+ }
+ return -ENOENT;
+#endif
+ /* We implement the SO_SNDLOWAT etc to
+ not be settable (1003.1g 5.3) */
+ default:
+ return(-ENOPROTOOPT);
+ }
+ return ret;
+}
+
+
+int sock_getsockopt(struct socket *sock, int level, int optname,
+ char *optval, int *optlen)
+{
+ struct sock *sk = sock->sk;
+
+ union
+ {
+ int val;
+ struct linger ling;
+ struct timeval tm;
+ } v;
+
+ int lv=sizeof(int),len;
+
+ if(get_user(len,optlen))
+ return -EFAULT;
+
+ switch(optname)
+ {
+ case SO_DEBUG:
+ v.val = sk->debug;
+ break;
+
+ case SO_DONTROUTE:
+ v.val = sk->localroute;
+ break;
+
+ case SO_BROADCAST:
+ v.val= sk->broadcast;
+ break;
+
+ case SO_SNDBUF:
+ v.val=sk->sndbuf;
+ break;
+
+ case SO_RCVBUF:
+ v.val =sk->rcvbuf;
+ break;
+
+ case SO_REUSEADDR:
+ v.val = sk->reuse;
+ break;
+
+ case SO_KEEPALIVE:
+ v.val = sk->keepopen;
+ break;
+
+ case SO_TYPE:
+ v.val = sk->type;
+ break;
+
+ case SO_ERROR:
+ v.val = -sock_error(sk);
+ if(v.val==0)
+ v.val=xchg(&sk->err_soft,0);
+ break;
+
+ case SO_OOBINLINE:
+ v.val = sk->urginline;
+ break;
+
+ case SO_NO_CHECK:
+ v.val = sk->no_check;
+ break;
+
+ case SO_PRIORITY:
+ v.val = sk->priority;
+ break;
+
+ case SO_LINGER:
+ lv=sizeof(v.ling);
+ v.ling.l_onoff=sk->linger;
+ v.ling.l_linger=sk->lingertime;
+ break;
+
+ case SO_BSDCOMPAT:
+ v.val = sk->bsdism;
+ break;
+
+ case SO_RCVTIMEO:
+ case SO_SNDTIMEO:
+ lv=sizeof(struct timeval);
+ v.tm.tv_sec=0;
+ v.tm.tv_usec=0;
+ break;
+
+ case SO_RCVLOWAT:
+ case SO_SNDLOWAT:
+ v.val=1;
+ break;
+
+ case SO_PASSCRED:
+ v.val = sock->passcred;
+ break;
+
+ case SO_PEERCRED:
+ lv=sizeof(sk->peercred);
+ len=min(len, lv);
+ if(copy_to_user((void*)optval, &sk->peercred, len))
+ return -EFAULT;
+ goto lenout;
+
+ default:
+ return(-ENOPROTOOPT);
+ }
+ len=min(len,lv);
+ if(copy_to_user(optval,&v,len))
+ return -EFAULT;
+lenout:
+ if(put_user(len, optlen))
+ return -EFAULT;
+ return 0;
+}
+
+static kmem_cache_t *sk_cachep;
+
+/*
+ * All socket objects are allocated here. This is for future
+ * usage.
+ */
+
+struct sock *sk_alloc(int family, int priority, int zero_it)
+{
+ struct sock *sk = kmem_cache_alloc(sk_cachep, priority);
+
+ if(sk) {
+ if (zero_it)
+ memset(sk, 0, sizeof(struct sock));
+ sk->family = family;
+ }
+
+ return sk;
+}
+
+void sk_free(struct sock *sk)
+{
+#ifdef CONFIG_FILTER
+ struct sk_filter *filter;
+#endif
+ if (sk->destruct)
+ sk->destruct(sk);
+
+#ifdef CONFIG_FILTER
+ filter = sk->filter;
+ if (filter) {
+ sk_filter_release(sk, filter);
+ sk->filter = NULL;
+ }
+#endif
+
+ if (atomic_read(&sk->omem_alloc))
+ printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
+
+ kmem_cache_free(sk_cachep, sk);
+}
+
+void __init sk_init(void)
+{
+ sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0,
+ SLAB_HWCACHE_ALIGN, 0, 0);
+
+}
+
+/*
+ * Simple resource managers for sockets.
+ */
+
+
+/*
+ * Write buffer destructor automatically called from kfree_skb.
+ */
+void sock_wfree(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+
+ /* In case it might be waiting for more memory. */
+ atomic_sub(skb->truesize, &sk->wmem_alloc);
+ sk->write_space(sk);
+}
+
+/*
+ * Read buffer destructor automatically called from kfree_skb.
+ */
+void sock_rfree(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+
+ atomic_sub(skb->truesize, &sk->rmem_alloc);
+}
+
+
+/*
+ * Allocate a skb from the socket's send buffer.
+ */
+struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
+{
+ if (force || atomic_read(&sk->wmem_alloc) < sk->sndbuf) {
+ struct sk_buff * skb = alloc_skb(size, priority);
+ if (skb) {
+ atomic_add(skb->truesize, &sk->wmem_alloc);
+ skb->destructor = sock_wfree;
+ skb->sk = sk;
+ return skb;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Allocate a skb from the socket's receive buffer.
+ */
+struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
+{
+ if (force || atomic_read(&sk->rmem_alloc) < sk->rcvbuf) {
+ struct sk_buff *skb = alloc_skb(size, priority);
+ if (skb) {
+ atomic_add(skb->truesize, &sk->rmem_alloc);
+ skb->destructor = sock_rfree;
+ skb->sk = sk;
+ return skb;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Allocate a memory block from the socket's option memory buffer.
+ */
+void *sock_kmalloc(struct sock *sk, int size, int priority)
+{
+ if (atomic_read(&sk->omem_alloc)+size < sysctl_optmem_max) {
+ void *mem;
+ /* First do the add, to avoid the race if kmalloc
+ * might sleep.
+ */
+ atomic_add(size, &sk->omem_alloc);
+ mem = kmalloc(size, priority);
+ if (mem)
+ return mem;
+ atomic_sub(size, &sk->omem_alloc);
+ }
+ return NULL;
+}
+
+/*
+ * Free an option memory block.
+ */
+void sock_kfree_s(struct sock *sk, void *mem, int size)
+{
+ kfree_s(mem, size);
+ atomic_sub(size, &sk->omem_alloc);
+}
+
+/* FIXME: this is insane. We are trying suppose to be controlling how
+ * how much space we have for data bytes, not packet headers.
+ * This really points out that we need a better system for doing the
+ * receive buffer. -- erics
+ * WARNING: This is currently ONLY used in tcp. If you need it else where
+ * this will probably not be what you want. Possibly these two routines
+ * should move over to the ipv4 directory.
+ */
+unsigned long sock_rspace(struct sock *sk)
+{
+ int amt = 0;
+
+ if (sk != NULL) {
+ /* This used to have some bizarre complications that
+ * to attempt to reserve some amount of space. This doesn't
+ * make sense, since the number returned here does not
+ * actually reflect allocated space, but rather the amount
+ * of space we committed to. We gamble that we won't
+ * run out of memory, and returning a smaller number does
+ * not change the gamble. If we lose the gamble tcp still
+ * works, it may just slow down for retransmissions.
+ */
+ amt = sk->rcvbuf - atomic_read(&sk->rmem_alloc);
+ if (amt < 0)
+ amt = 0;
+ }
+ return amt;
+}
+
+
+/* It is almost wait_for_tcp_memory minus release_sock/lock_sock.
+ I think, these locks should be removed for datagram sockets.
+ */
+static void sock_wait_for_wmem(struct sock * sk)
+{
+ struct wait_queue wait = { current, NULL };
+
+ sk->socket->flags &= ~SO_NOSPACE;
+ add_wait_queue(sk->sleep, &wait);
+ for (;;) {
+ if (signal_pending(current))
+ break;
+ current->state = TASK_INTERRUPTIBLE;
+ if (atomic_read(&sk->wmem_alloc) < sk->sndbuf)
+ break;
+ if (sk->shutdown & SEND_SHUTDOWN)
+ break;
+ if (sk->err)
+ break;
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+}
+
+
+/*
+ * Generic send/receive buffer handlers
+ */
+
+struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
+ unsigned long fallback, int noblock, int *errcode)
+{
+ int err;
+ struct sk_buff *skb;
+
+ while (1) {
+ unsigned long try_size = size;
+
+ err = sock_error(sk);
+ if (err != 0)
+ goto failure;
+
+ /*
+ * We should send SIGPIPE in these cases according to
+ * 1003.1g draft 6.4. If we (the user) did a shutdown()
+ * call however we should not.
+ *
+ * Note: This routine isnt just used for datagrams and
+ * anyway some datagram protocols have a notion of
+ * close down.
+ */
+
+ err = -EPIPE;
+ if (sk->shutdown&SEND_SHUTDOWN)
+ goto failure;
+
+ if (fallback) {
+ /* The buffer get won't block, or use the atomic queue.
+ * It does produce annoying no free page messages still.
+ */
+ skb = sock_wmalloc(sk, size, 0, GFP_BUFFER);
+ if (skb)
+ break;
+ try_size = fallback;
+ }
+ skb = sock_wmalloc(sk, try_size, 0, sk->allocation);
+ if (skb)
+ break;
+
+ /*
+ * This means we have too many buffers for this socket already.
+ */
+
+ sk->socket->flags |= SO_NOSPACE;
+ err = -EAGAIN;
+ if (noblock)
+ goto failure;
+ err = -ERESTARTSYS;
+ if (signal_pending(current))
+ goto failure;
+ sock_wait_for_wmem(sk);
+ }
+
+ return skb;
+
+failure:
+ *errcode = err;
+ return NULL;
+}
+
+
+void __release_sock(struct sock *sk)
+{
+#ifdef CONFIG_INET
+ if (!sk->prot || !sk->backlog_rcv)
+ return;
+
+ /* See if we have any packets built up. */
+ start_bh_atomic();
+ while (!skb_queue_empty(&sk->back_log)) {
+ struct sk_buff * skb = sk->back_log.next;
+ __skb_unlink(skb, &sk->back_log);
+ sk->backlog_rcv(sk, skb);
+ }
+ end_bh_atomic();
+#endif
+}
+
+
+/*
+ * Generic socket manager library. Most simpler socket families
+ * use this to manage their socket lists. At some point we should
+ * hash these. By making this generic we get the lot hashed for free.
+ */
+
+void sklist_remove_socket(struct sock **list, struct sock *sk)
+{
+ struct sock *s;
+
+ start_bh_atomic();
+
+ s= *list;
+ if(s==sk)
+ {
+ *list = s->next;
+ end_bh_atomic();
+ return;
+ }
+ while(s && s->next)
+ {
+ if(s->next==sk)
+ {
+ s->next=sk->next;
+ break;
+ }
+ s=s->next;
+ }
+ end_bh_atomic();
+}
+
+void sklist_insert_socket(struct sock **list, struct sock *sk)
+{
+ start_bh_atomic();
+ sk->next= *list;
+ *list=sk;
+ end_bh_atomic();
+}
+
+/*
+ * This is only called from user mode. Thus it protects itself against
+ * interrupt users but doesn't worry about being called during work.
+ * Once it is removed from the queue no interrupt or bottom half will
+ * touch it and we are (fairly 8-) ) safe.
+ */
+
+void sklist_destroy_socket(struct sock **list, struct sock *sk);
+
+/*
+ * Handler for deferred kills.
+ */
+
+static void sklist_destroy_timer(unsigned long data)
+{
+ struct sock *sk=(struct sock *)data;
+ sklist_destroy_socket(NULL,sk);
+}
+
+/*
+ * Destroy a socket. We pass NULL for a list if we know the
+ * socket is not on a list.
+ */
+
+void sklist_destroy_socket(struct sock **list,struct sock *sk)
+{
+ struct sk_buff *skb;
+ if(list)
+ sklist_remove_socket(list, sk);
+
+ while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
+ {
+ kfree_skb(skb);
+ }
+
+ if(atomic_read(&sk->wmem_alloc) == 0 &&
+ atomic_read(&sk->rmem_alloc) == 0 &&
+ sk->dead)
+ {
+ sk_free(sk);
+ }
+ else
+ {
+ /*
+ * Someone is using our buffers still.. defer
+ */
+ init_timer(&sk->timer);
+ sk->timer.expires=jiffies+SOCK_DESTROY_TIME;
+ sk->timer.function=sklist_destroy_timer;
+ sk->timer.data = (unsigned long)sk;
+ add_timer(&sk->timer);
+ }
+}
+
+/*
+ * Set of default routines for initialising struct proto_ops when
+ * the protocol does not support a particular function. In certain
+ * cases where it makes no sense for a protocol to have a "do nothing"
+ * function, some default processing is provided.
+ */
+
+int sock_no_dup(struct socket *newsock, struct socket *oldsock)
+{
+ struct sock *sk = oldsock->sk;
+
+ return net_families[sk->family]->create(newsock, sk->protocol);
+}
+
+int sock_no_release(struct socket *sock, struct socket *peersock)
+{
+ return 0;
+}
+
+int sock_no_bind(struct socket *sock, struct sockaddr *saddr, int len)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_connect(struct socket *sock, struct sockaddr *saddr,
+ int len, int flags)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_socketpair(struct socket *sock1, struct socket *sock2)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_getname(struct socket *sock, struct sockaddr *saddr,
+ int *len, int peer)
+{
+ return -EOPNOTSUPP;
+}
+
+unsigned int sock_no_poll(struct file * file, struct socket *sock, poll_table *pt)
+{
+ return 0;
+}
+
+int sock_no_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_listen(struct socket *sock, int backlog)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_shutdown(struct socket *sock, int how)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_setsockopt(struct socket *sock, int level, int optname,
+ char *optval, int optlen)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_getsockopt(struct socket *sock, int level, int optname,
+ char *optval, int *optlen)
+{
+ return -EOPNOTSUPP;
+}
+
+/*
+ * Note: if you add something that sleeps here then change sock_fcntl()
+ * to do proper fd locking.
+ */
+int sock_no_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ struct sock *sk = sock->sk;
+
+ switch(cmd)
+ {
+ case F_SETOWN:
+ /*
+ * This is a little restrictive, but it's the only
+ * way to make sure that you can't send a sigurg to
+ * another process.
+ */
+ if (current->pgrp != -arg &&
+ current->pid != arg &&
+ !capable(CAP_KILL)) return(-EPERM);
+ sk->proc = arg;
+ return(0);
+ case F_GETOWN:
+ return(sk->proc);
+ default:
+ return(-EINVAL);
+ }
+}
+
+int sock_no_sendmsg(struct socket *sock, struct msghdr *m, int flags,
+ struct scm_cookie *scm)
+{
+ return -EOPNOTSUPP;
+}
+
+int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int flags,
+ struct scm_cookie *scm)
+{
+ return -EOPNOTSUPP;
+}
+
+
+
+/*
+ * Default Socket Callbacks
+ */
+
+void sock_def_wakeup(struct sock *sk)
+{
+ if(!sk->dead)
+ wake_up_interruptible(sk->sleep);
+}
+
+void sock_def_error_report(struct sock *sk)
+{
+ if (!sk->dead) {
+ wake_up_interruptible(sk->sleep);
+ sock_wake_async(sk->socket,0);
+ }
+}
+
+void sock_def_readable(struct sock *sk, int len)
+{
+ if(!sk->dead) {
+ wake_up_interruptible(sk->sleep);
+ sock_wake_async(sk->socket,1);
+ }
+}
+
+void sock_def_write_space(struct sock *sk)
+{
+ /* Do not wake up a writer until he can make "significant"
+ * progress. --DaveM
+ */
+ if(!sk->dead &&
+ ((atomic_read(&sk->wmem_alloc) << 1) <= sk->sndbuf)) {
+ wake_up_interruptible(sk->sleep);
+
+ /* Should agree with poll, otherwise some programs break */
+ if (sock_writeable(sk))
+ sock_wake_async(sk->socket, 2);
+ }
+}
+
+void sock_def_destruct(struct sock *sk)
+{
+ if (sk->protinfo.destruct_hook)
+ kfree(sk->protinfo.destruct_hook);
+}
+
+void sock_init_data(struct socket *sock, struct sock *sk)
+{
+ skb_queue_head_init(&sk->receive_queue);
+ skb_queue_head_init(&sk->write_queue);
+ skb_queue_head_init(&sk->back_log);
+ skb_queue_head_init(&sk->error_queue);
+
+ init_timer(&sk->timer);
+
+ sk->allocation = GFP_KERNEL;
+ sk->rcvbuf = sysctl_rmem_default;
+ sk->sndbuf = sysctl_wmem_default;
+ sk->state = TCP_CLOSE;
+ sk->zapped = 1;
+ sk->socket = sock;
+
+ if(sock)
+ {
+ sk->type = sock->type;
+ sk->sleep = &sock->wait;
+ sock->sk = sk;
+ }
+
+ sk->state_change = sock_def_wakeup;
+ sk->data_ready = sock_def_readable;
+ sk->write_space = sock_def_write_space;
+ sk->error_report = sock_def_error_report;
+ sk->destruct = sock_def_destruct;
+
+ sk->peercred.pid = 0;
+ sk->peercred.uid = -1;
+ sk->peercred.gid = -1;
+
+}
diff --git a/pfinet/linux-src/net/core/sysctl_net_core.c b/pfinet/linux-src/net/core/sysctl_net_core.c
new file mode 100644
index 00000000..446ca145
--- /dev/null
+++ b/pfinet/linux-src/net/core/sysctl_net_core.c
@@ -0,0 +1,61 @@
+/* -*- linux-c -*-
+ * sysctl_net_core.c: sysctl interface to net core subsystem.
+ *
+ * Begun April 1, 1996, Mike Shaver.
+ * Added /proc/sys/net/core directory entry (empty =) ). [MS]
+ */
+
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <linux/config.h>
+
+#ifdef CONFIG_SYSCTL
+
+extern int netdev_max_backlog;
+extern int netdev_fastroute;
+extern int net_msg_cost;
+extern int net_msg_burst;
+
+extern __u32 sysctl_wmem_max;
+extern __u32 sysctl_rmem_max;
+extern __u32 sysctl_wmem_default;
+extern __u32 sysctl_rmem_default;
+
+extern int sysctl_core_destroy_delay;
+extern int sysctl_optmem_max;
+
+ctl_table core_table[] = {
+#ifdef CONFIG_NET
+ {NET_CORE_WMEM_MAX, "wmem_max",
+ &sysctl_wmem_max, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_CORE_RMEM_MAX, "rmem_max",
+ &sysctl_rmem_max, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_CORE_WMEM_DEFAULT, "wmem_default",
+ &sysctl_wmem_default, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_CORE_RMEM_DEFAULT, "rmem_default",
+ &sysctl_rmem_default, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_CORE_MAX_BACKLOG, "netdev_max_backlog",
+ &netdev_max_backlog, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+#ifdef CONFIG_NET_FASTROUTE
+ {NET_CORE_FASTROUTE, "netdev_fastroute",
+ &netdev_fastroute, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+#endif
+ {NET_CORE_MSG_COST, "message_cost",
+ &net_msg_cost, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies},
+ {NET_CORE_MSG_BURST, "message_burst",
+ &net_msg_burst, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies},
+ {NET_CORE_OPTMEM_MAX, "optmem_max",
+ &sysctl_optmem_max, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+#endif /* CONFIG_NET */
+ { 0 }
+};
+#endif
diff --git a/pfinet/linux-src/net/core/utils.c b/pfinet/linux-src/net/core/utils.c
new file mode 100644
index 00000000..415926b8
--- /dev/null
+++ b/pfinet/linux-src/net/core/utils.c
@@ -0,0 +1,66 @@
+/*
+ * Generic address resultion entity
+ *
+ * Authors:
+ * net_random Alan Cox
+ * net_ratelimit Andy Kleen
+ *
+ * Created by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+
+static unsigned long net_rand_seed = 152L;
+
+unsigned long net_random(void)
+{
+ net_rand_seed=net_rand_seed*69069L+1;
+ return net_rand_seed^jiffies;
+}
+
+void net_srandom(unsigned long entropy)
+{
+ net_rand_seed ^= entropy;
+ net_random();
+}
+
+int net_msg_cost = 5*HZ;
+int net_msg_burst = 10*5*HZ;
+
+/*
+ * This enforces a rate limit: not more than one kernel message
+ * every 5secs to make a denial-of-service attack impossible.
+ *
+ * All warning printk()s should be guarded by this function.
+ */
+int net_ratelimit(void)
+{
+ static unsigned long toks = 10*5*HZ;
+ static unsigned long last_msg;
+ static int missed;
+ unsigned long now = jiffies;
+
+ toks += now - xchg(&last_msg, now);
+ if (toks > net_msg_burst)
+ toks = net_msg_burst;
+ if (toks >= net_msg_cost) {
+ toks -= net_msg_cost;
+ if (missed)
+ printk(KERN_WARNING "NET: %d messages suppressed.\n", missed);
+ missed = 0;
+ return 1;
+ }
+ missed++;
+ return 0;
+}
diff --git a/pfinet/linux-src/net/ethernet/Makefile b/pfinet/linux-src/net/ethernet/Makefile
new file mode 100644
index 00000000..193d6af8
--- /dev/null
+++ b/pfinet/linux-src/net/ethernet/Makefile
@@ -0,0 +1,33 @@
+#
+# Makefile for the Linux Ethernet layer.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := ethernet.o
+
+OBJS := eth.o
+
+ifeq ($(CONFIG_SYSCTL),y)
+OBJS += sysctl_net_ether.o
+endif
+
+ifdef CONFIG_IPX
+OBJ2 := pe2.o
+endif
+
+ifdef CONFIG_ATALK
+OBJ2 := pe2.o
+endif
+
+ifdef CONFIG_NET
+O_OBJS := $(OBJS) $(OBJ2)
+endif
+
+include $(TOPDIR)/Rules.make
+
+tar:
+ tar -cvf /dev/f1 .
diff --git a/pfinet/linux-src/net/ethernet/eth.c b/pfinet/linux-src/net/ethernet/eth.c
new file mode 100644
index 00000000..bce35d48
--- /dev/null
+++ b/pfinet/linux-src/net/ethernet/eth.c
@@ -0,0 +1,298 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Ethernet-type device handling.
+ *
+ * Version: @(#)eth.c 1.0.7 05/25/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Florian La Roche, <rzsfl@rz.uni-sb.de>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *
+ * Fixes:
+ * Mr Linux : Arp problems
+ * Alan Cox : Generic queue tidyup (very tiny here)
+ * Alan Cox : eth_header ntohs should be htons
+ * Alan Cox : eth_rebuild_header missing an htons and
+ * minor other things.
+ * Tegge : Arp bug fixes.
+ * Florian : Removed many unnecessary functions, code cleanup
+ * and changes for new arp and skbuff.
+ * Alan Cox : Redid header building to reflect new format.
+ * Alan Cox : ARP only when compiled with CONFIG_INET
+ * Greg Page : 802.2 and SNAP stuff.
+ * Alan Cox : MAC layer pointers/new format.
+ * Paul Gortmaker : eth_copy_and_sum shouldn't csum padding.
+ * Alan Cox : Protect against forwarding explosions with
+ * older network drivers and IFF_ALLMULTI.
+ * Christer Weinigel : Better rebuild header message.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/ip.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <net/dst.h>
+#include <net/arp.h>
+#include <net/sock.h>
+#include <net/ipv6.h>
+#include <net/ip.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/checksum.h>
+
+
+__initfunc(void eth_setup(char *str, int *ints))
+{
+ struct device *d = dev_base;
+
+ if (!str || !*str)
+ return;
+ while (d)
+ {
+ if (!strcmp(str,d->name))
+ {
+ if (ints[0] > 0)
+ d->irq=ints[1];
+ if (ints[0] > 1)
+ d->base_addr=ints[2];
+ if (ints[0] > 2)
+ d->mem_start=ints[3];
+ if (ints[0] > 3)
+ d->mem_end=ints[4];
+ break;
+ }
+ d=d->next;
+ }
+}
+
+
+/*
+ * Create the Ethernet MAC header for an arbitrary protocol layer
+ *
+ * saddr=NULL means use device source address
+ * daddr=NULL means leave destination address (eg unresolved arp)
+ */
+
+int eth_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+ void *daddr, void *saddr, unsigned len)
+{
+ struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
+
+ /*
+ * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
+ * in here instead. It is up to the 802.2 layer to carry protocol information.
+ */
+
+ if(type!=ETH_P_802_3)
+ eth->h_proto = htons(type);
+ else
+ eth->h_proto = htons(len);
+
+ /*
+ * Set the source hardware address.
+ */
+
+ if(saddr)
+ memcpy(eth->h_source,saddr,dev->addr_len);
+ else
+ memcpy(eth->h_source,dev->dev_addr,dev->addr_len);
+
+ /*
+ * Anyway, the loopback-device should never use this function...
+ */
+
+ if (dev->flags & (IFF_LOOPBACK|IFF_NOARP))
+ {
+ memset(eth->h_dest, 0, dev->addr_len);
+ return(dev->hard_header_len);
+ }
+
+ if(daddr)
+ {
+ memcpy(eth->h_dest,daddr,dev->addr_len);
+ return dev->hard_header_len;
+ }
+
+ return -dev->hard_header_len;
+}
+
+
+/*
+ * Rebuild the Ethernet MAC header. This is called after an ARP
+ * (or in future other address resolution) has completed on this
+ * sk_buff. We now let ARP fill in the other fields.
+ *
+ * This routine CANNOT use cached dst->neigh!
+ * Really, it is used only when dst->neigh is wrong.
+ */
+
+int eth_rebuild_header(struct sk_buff *skb)
+{
+ struct ethhdr *eth = (struct ethhdr *)skb->data;
+ struct device *dev = skb->dev;
+
+ switch (eth->h_proto)
+ {
+#ifdef CONFIG_INET
+ case __constant_htons(ETH_P_IP):
+ return arp_find(eth->h_dest, skb);
+#endif
+ default:
+ printk(KERN_DEBUG
+ "%s: unable to resolve type %X addresses.\n",
+ dev->name, (int)eth->h_proto);
+
+ memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+ break;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Determine the packet's protocol ID. The rule here is that we
+ * assume 802.3 if the type field is short enough to be a length.
+ * This is normal practice and works for any 'now in use' protocol.
+ */
+
+unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
+{
+ struct ethhdr *eth;
+ unsigned char *rawp;
+
+ skb->mac.raw=skb->data;
+ skb_pull(skb,dev->hard_header_len);
+ eth= skb->mac.ethernet;
+
+ if(*eth->h_dest&1)
+ {
+ if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
+ skb->pkt_type=PACKET_BROADCAST;
+ else
+ skb->pkt_type=PACKET_MULTICAST;
+ }
+
+ /*
+ * This ALLMULTI check should be redundant by 1.4
+ * so don't forget to remove it.
+ *
+ * Seems, you forgot to remove it. All silly devices
+ * seems to set IFF_PROMISC.
+ */
+
+ else if(dev->flags&(IFF_PROMISC/*|IFF_ALLMULTI*/))
+ {
+ if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
+ skb->pkt_type=PACKET_OTHERHOST;
+ }
+
+ if (ntohs(eth->h_proto) >= 1536)
+ return eth->h_proto;
+
+ rawp = skb->data;
+
+ /*
+ * This is a magic hack to spot IPX packets. Older Novell breaks
+ * the protocol design and runs IPX over 802.3 without an 802.2 LLC
+ * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+ * won't work for fault tolerant netware but does for the rest.
+ */
+ if (*(unsigned short *)rawp == 0xFFFF)
+ return htons(ETH_P_802_3);
+
+ /*
+ * Real 802.2 LLC
+ */
+ return htons(ETH_P_802_2);
+}
+
+int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+ struct ethhdr *eth = skb->mac.ethernet;
+ memcpy(haddr, eth->h_source, ETH_ALEN);
+ return ETH_ALEN;
+}
+
+int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
+{
+ unsigned short type = hh->hh_type;
+ struct ethhdr *eth = (struct ethhdr*)(((u8*)hh->hh_data) + 2);
+ struct device *dev = neigh->dev;
+
+ if (type == __constant_htons(ETH_P_802_3))
+ return -1;
+
+ eth->h_proto = type;
+ memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+ memcpy(eth->h_dest, neigh->ha, dev->addr_len);
+ return 0;
+}
+
+/*
+ * Called by Address Resolution module to notify changes in address.
+ */
+
+void eth_header_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr)
+{
+ memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);
+}
+
+#ifndef CONFIG_IP_ROUTER
+
+/*
+ * Copy from an ethernet device memory space to an sk_buff while checksumming if IP
+ */
+
+void eth_copy_and_sum(struct sk_buff *dest, unsigned char *src, int length, int base)
+{
+ struct ethhdr *eth;
+ struct iphdr *iph;
+ int ip_length;
+
+ eth=(struct ethhdr *)src;
+ if(eth->h_proto!=htons(ETH_P_IP))
+ {
+ memcpy(dest->data,src,length);
+ return;
+ }
+ /*
+ * We have to watch for padded packets. The csum doesn't include the
+ * padding, and there is no point in copying the padding anyway.
+ * We have to use the smaller of length and ip_length because it
+ * can happen that ip_length > length.
+ */
+ memcpy(dest->data,src,sizeof(struct iphdr)+ETH_HLEN); /* ethernet is always >= 34 */
+ length -= sizeof(struct iphdr) + ETH_HLEN;
+ iph=(struct iphdr*)(src+ETH_HLEN);
+ ip_length = ntohs(iph->tot_len) - sizeof(struct iphdr);
+
+ /* Also watch out for bogons - min IP size is 8 (rfc-1042) */
+ if ((ip_length <= length) && (ip_length > 7))
+ length=ip_length;
+
+ dest->csum=csum_partial_copy(src+sizeof(struct iphdr)+ETH_HLEN,dest->data+sizeof(struct iphdr)+ETH_HLEN,length,base);
+ dest->ip_summed=1;
+}
+
+#endif /* !(CONFIG_IP_ROUTER) */
diff --git a/pfinet/linux-src/net/ethernet/pe2.c b/pfinet/linux-src/net/ethernet/pe2.c
new file mode 100644
index 00000000..4915f070
--- /dev/null
+++ b/pfinet/linux-src/net/ethernet/pe2.c
@@ -0,0 +1,38 @@
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/datalink.h>
+#include <linux/mm.h>
+#include <linux/in.h>
+
+static void
+pEII_datalink_header(struct datalink_proto *dl,
+ struct sk_buff *skb, unsigned char *dest_node)
+{
+ struct device *dev = skb->dev;
+
+ skb->protocol = htons (ETH_P_IPX);
+ if(dev->hard_header)
+ dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
+}
+
+struct datalink_proto *
+make_EII_client(void)
+{
+ struct datalink_proto *proto;
+
+ proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
+ if (proto != NULL) {
+ proto->type_len = 0;
+ proto->header_length = 0;
+ proto->datalink_header = pEII_datalink_header;
+ proto->string_name = "EtherII";
+ }
+
+ return proto;
+}
+
+void destroy_EII_client(struct datalink_proto *dl)
+{
+ if (dl)
+ kfree_s(dl, sizeof(struct datalink_proto));
+}
diff --git a/pfinet/linux-src/net/ethernet/sysctl_net_ether.c b/pfinet/linux-src/net/ethernet/sysctl_net_ether.c
new file mode 100644
index 00000000..b81a6d53
--- /dev/null
+++ b/pfinet/linux-src/net/ethernet/sysctl_net_ether.c
@@ -0,0 +1,13 @@
+/* -*- linux-c -*-
+ * sysctl_net_ether.c: sysctl interface to net Ethernet subsystem.
+ *
+ * Begun April 1, 1996, Mike Shaver.
+ * Added /proc/sys/net/ether directory entry (empty =) ). [MS]
+ */
+
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+
+ctl_table ether_table[] = {
+ {0}
+};
diff --git a/pfinet/linux-src/net/ipv4/Config.in b/pfinet/linux-src/net/ipv4/Config.in
new file mode 100644
index 00000000..29786da5
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/Config.in
@@ -0,0 +1,88 @@
+#
+# IP configuration
+#
+bool 'IP: multicasting' CONFIG_IP_MULTICAST
+bool 'IP: advanced router' CONFIG_IP_ADVANCED_ROUTER
+if [ "$CONFIG_IP_ADVANCED_ROUTER" = "y" ]; then
+ define_bool CONFIG_RTNETLINK y
+ define_bool CONFIG_NETLINK y
+ bool 'IP: policy routing' CONFIG_IP_MULTIPLE_TABLES
+ bool 'IP: equal cost multipath' CONFIG_IP_ROUTE_MULTIPATH
+ bool 'IP: use TOS value as routing key' CONFIG_IP_ROUTE_TOS
+ bool 'IP: verbose route monitoring' CONFIG_IP_ROUTE_VERBOSE
+ bool 'IP: large routing tables' CONFIG_IP_ROUTE_LARGE_TABLES
+ if [ "$CONFIG_IP_MULTIPLE_TABLES" = "y" ]; then
+ bool 'IP: fast network address translation' CONFIG_IP_ROUTE_NAT
+ fi
+fi
+bool 'IP: kernel level autoconfiguration' CONFIG_IP_PNP
+if [ "$CONFIG_IP_PNP" = "y" ]; then
+ bool ' BOOTP support' CONFIG_IP_PNP_BOOTP
+ bool ' RARP support' CONFIG_IP_PNP_RARP
+# not yet ready..
+# bool ' ARP support' CONFIG_IP_PNP_ARP
+fi
+if [ "$CONFIG_FIREWALL" = "y" ]; then
+ bool 'IP: firewalling' CONFIG_IP_FIREWALL
+ if [ "$CONFIG_IP_FIREWALL" = "y" ]; then
+ if [ "$CONFIG_NETLINK" = "y" ]; then
+ bool 'IP: firewall packet netlink device' CONFIG_IP_FIREWALL_NETLINK
+ if [ "$CONFIG_IP_FIREWALL_NETLINK" = "y" ]; then
+ define_bool CONFIG_NETLINK_DEV y
+ fi
+ fi
+ bool 'IP: always defragment (required for masquerading)' CONFIG_IP_ALWAYS_DEFRAG
+ if [ "$CONFIG_IP_MULTIPLE_TABLES" = "y" ]; then
+ bool 'IP: use FWMARK value as routing key' CONFIG_IP_ROUTE_FWMARK
+ fi
+ fi
+fi
+if [ "$CONFIG_IP_FIREWALL" = "y" ]; then
+ if [ "$CONFIG_IP_ALWAYS_DEFRAG" != "n" ]; then
+ bool 'IP: transparent proxy support' CONFIG_IP_TRANSPARENT_PROXY
+ bool 'IP: masquerading' CONFIG_IP_MASQUERADE
+ if [ "$CONFIG_IP_MASQUERADE" != "n" ]; then
+ comment 'Protocol-specific masquerading support will be built as modules.'
+ bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP
+ comment 'Protocol-specific masquerading support will be built as modules.'
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'IP: masquerading special modules support' CONFIG_IP_MASQUERADE_MOD
+ if [ "$CONFIG_IP_MASQUERADE_MOD" = "y" ]; then
+ tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW
+ tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW
+ tristate 'IP: ip fwmark masq-forwarding support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_MFW
+ fi
+ fi
+ fi
+ fi
+fi
+bool 'IP: optimize as router not host' CONFIG_IP_ROUTER
+tristate 'IP: tunneling' CONFIG_NET_IPIP
+tristate 'IP: GRE tunnels over IP' CONFIG_NET_IPGRE
+if [ "$CONFIG_IP_MULTICAST" = "y" ]; then
+ if [ "$CONFIG_NET_IPGRE" != "n" ]; then
+ bool 'IP: broadcast GRE over IP' CONFIG_NET_IPGRE_BROADCAST
+ fi
+ bool 'IP: multicast routing' CONFIG_IP_MROUTE
+ if [ "$CONFIG_IP_MROUTE" = "y" ]; then
+ bool 'IP: PIM-SM version 1 support' CONFIG_IP_PIMSM_V1
+ bool 'IP: PIM-SM version 2 support' CONFIG_IP_PIMSM_V2
+ fi
+fi
+bool 'IP: aliasing support' CONFIG_IP_ALIAS
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ if [ "$CONFIG_RTNETLINK" = "y" ]; then
+ bool 'IP: ARP daemon support (EXPERIMENTAL)' CONFIG_ARPD
+ fi
+fi
+bool 'IP: TCP syncookie support (not enabled per default)' CONFIG_SYN_COOKIES
+comment '(it is safe to leave these untouched)'
+#bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP
+tristate 'IP: Reverse ARP' CONFIG_INET_RARP
+#bool 'IP: Path MTU Discovery (normally enabled)' CONFIG_PATH_MTU_DISCOVERY
+#bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF
+bool 'IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE
+#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+#bool 'IP: support experimental checksum copy to user for UDP' CONFIG_UDP_DELAY_CSUM
+#fi
+
diff --git a/pfinet/linux-src/net/ipv4/Makefile b/pfinet/linux-src/net/ipv4/Makefile
new file mode 100644
index 00000000..8ab280de
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/Makefile
@@ -0,0 +1,116 @@
+#
+# Makefile for the Linux TCP/IP (INET) layer.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := ipv4.o
+IPV4_OBJS := utils.o route.o proc.o timer.o protocol.o \
+ ip_input.o ip_fragment.o ip_forward.o ip_options.o \
+ ip_output.o ip_sockglue.o \
+ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o\
+ raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \
+ sysctl_net_ipv4.o fib_frontend.o fib_semantics.o fib_hash.o
+IPV4X_OBJS :=
+
+MOD_LIST_NAME := IPV4_MODULES
+M_OBJS :=
+
+ifeq ($(CONFIG_IP_FIREWALL),y)
+IPV4_OBJS += ip_fw.o
+endif
+
+ifeq ($(CONFIG_IP_MULTIPLE_TABLES),y)
+IPV4_OBJS += fib_rules.o
+endif
+
+ifeq ($(CONFIG_IP_ROUTE_NAT),y)
+IPV4_OBJS += ip_nat_dumb.o
+endif
+
+ifeq ($(CONFIG_IP_MROUTE),y)
+IPV4_OBJS += ipmr.o
+endif
+
+ifeq ($(CONFIG_INET_RARP),y)
+IPV4_OBJS += rarp.o
+else
+ ifeq ($(CONFIG_INET_RARP),m)
+ M_OBJS += rarp.o
+ endif
+endif
+
+ifeq ($(CONFIG_NET_IPIP),y)
+IPV4X_OBJS += ipip.o
+else
+ ifeq ($(CONFIG_NET_IPIP),m)
+ MX_OBJS += ipip.o
+ endif
+endif
+
+ifeq ($(CONFIG_NET_IPGRE),y)
+IPV4X_OBJS += ip_gre.o
+else
+ ifeq ($(CONFIG_NET_IPGRE),m)
+ MX_OBJS += ip_gre.o
+ endif
+endif
+
+ifeq ($(CONFIG_IP_MASQUERADE),y)
+IPV4X_OBJS += ip_masq.o ip_masq_app.o
+
+ifeq ($(CONFIG_IP_MASQUERADE_MOD),y)
+ IPV4X_OBJS += ip_masq_mod.o
+
+ ifeq ($(CONFIG_IP_MASQUERADE_IPAUTOFW),y)
+ IPV4_OBJS += ip_masq_autofw.o
+ else
+ ifeq ($(CONFIG_IP_MASQUERADE_IPAUTOFW),m)
+ M_OBJS += ip_masq_autofw.o
+ endif
+ endif
+
+ ifeq ($(CONFIG_IP_MASQUERADE_IPPORTFW),y)
+ IPV4_OBJS += ip_masq_portfw.o
+ else
+ ifeq ($(CONFIG_IP_MASQUERADE_IPPORTFW),m)
+ M_OBJS += ip_masq_portfw.o
+ endif
+ endif
+
+ ifeq ($(CONFIG_IP_MASQUERADE_MFW),y)
+ IPV4_OBJS += ip_masq_mfw.o
+ else
+ ifeq ($(CONFIG_IP_MASQUERADE_MFW),m)
+ M_OBJS += ip_masq_mfw.o
+ endif
+ endif
+
+endif
+
+M_OBJS += ip_masq_user.o
+M_OBJS += ip_masq_ftp.o ip_masq_irc.o ip_masq_raudio.o ip_masq_quake.o
+M_OBJS += ip_masq_vdolive.o ip_masq_cuseeme.o
+endif
+
+ifeq ($(CONFIG_SYN_COOKIES),y)
+IPV4_OBJS += syncookies.o
+# module not supported, because it would be too messy.
+endif
+
+ifeq ($(CONFIG_IP_PNP),y)
+IPV4_OBJS += ipconfig.o
+endif
+
+ifdef CONFIG_INET
+O_OBJS := $(IPV4_OBJS)
+OX_OBJS := $(IPV4X_OBJS)
+endif
+
+include $(TOPDIR)/Rules.make
+
+tar:
+ tar -cvf /dev/f1 .
diff --git a/pfinet/linux-src/net/ipv4/af_inet.c b/pfinet/linux-src/net/ipv4/af_inet.c
new file mode 100644
index 00000000..e37eb6bd
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/af_inet.c
@@ -0,0 +1,1161 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * PF_INET protocol family socket handler.
+ *
+ * Version: $Id: af_inet.c,v 1.87.2.5 1999/08/08 08:43:10 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Alan Cox, <A.Cox@swansea.ac.uk>
+ *
+ * Changes (see also sock.c)
+ *
+ * A.N.Kuznetsov : Socket death error in accept().
+ * John Richardson : Fix non blocking error in connect()
+ * so sockets that fail to connect
+ * don't return -EINPROGRESS.
+ * Alan Cox : Asynchronous I/O support
+ * Alan Cox : Keep correct socket pointer on sock structures
+ * when accept() ed
+ * Alan Cox : Semantics of SO_LINGER aren't state moved
+ * to close when you look carefully. With
+ * this fixed and the accept bug fixed
+ * some RPC stuff seems happier.
+ * Niibe Yutaka : 4.4BSD style write async I/O
+ * Alan Cox,
+ * Tony Gale : Fixed reuse semantics.
+ * Alan Cox : bind() shouldn't abort existing but dead
+ * sockets. Stops FTP netin:.. I hope.
+ * Alan Cox : bind() works correctly for RAW sockets. Note
+ * that FreeBSD at least was broken in this respect
+ * so be careful with compatibility tests...
+ * Alan Cox : routing cache support
+ * Alan Cox : memzero the socket structure for compactness.
+ * Matt Day : nonblock connect error handler
+ * Alan Cox : Allow large numbers of pending sockets
+ * (eg for big web sites), but only if
+ * specifically application requested.
+ * Alan Cox : New buffering throughout IP. Used dumbly.
+ * Alan Cox : New buffering now used smartly.
+ * Alan Cox : BSD rather than common sense interpretation of
+ * listen.
+ * Germano Caronni : Assorted small races.
+ * Alan Cox : sendmsg/recvmsg basic support.
+ * Alan Cox : Only sendmsg/recvmsg now supported.
+ * Alan Cox : Locked down bind (see security list).
+ * Alan Cox : Loosened bind a little.
+ * Mike McLagan : ADD/DEL DLCI Ioctls
+ * Willy Konynenberg : Transparent proxying support.
+ * David S. Miller : New socket lookup architecture.
+ * Some other random speedups.
+ * Cyrus Durgin : Cleaned up file for kmod hacks.
+ * Andi Kleen : Fix inet_stream_connect TCP race.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/sockios.h>
+#include <linux/net.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/arp.h>
+#include <net/rarp.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/raw.h>
+#include <net/icmp.h>
+#include <net/ipip.h>
+#include <net/inet_common.h>
+#include <linux/ip_fw.h>
+#ifdef CONFIG_IP_MROUTE
+#include <linux/mroute.h>
+#endif
+#ifdef CONFIG_IP_MASQUERADE
+#include <net/ip_masq.h>
+#endif
+#ifdef CONFIG_BRIDGE
+#include <net/br.h>
+#endif
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+#ifdef CONFIG_NET_RADIO
+#include <linux/wireless.h>
+#endif /* CONFIG_NET_RADIO */
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+struct linux_mib net_statistics;
+
+extern int raw_get_info(char *, char **, off_t, int, int);
+extern int snmp_get_info(char *, char **, off_t, int, int);
+extern int netstat_get_info(char *, char **, off_t, int, int);
+extern int afinet_get_info(char *, char **, off_t, int, int);
+extern int tcp_get_info(char *, char **, off_t, int, int);
+extern int udp_get_info(char *, char **, off_t, int, int);
+extern void ip_mc_drop_socket(struct sock *sk);
+
+#ifdef CONFIG_DLCI
+extern int dlci_ioctl(unsigned int, void*);
+#endif
+
+#ifdef CONFIG_DLCI_MODULE
+int (*dlci_ioctl_hook)(unsigned int, void *) = NULL;
+#endif
+
+int (*rarp_ioctl_hook)(unsigned int,void*) = NULL;
+
+/*
+ * Destroy an AF_INET socket
+ */
+
+static __inline__ void kill_sk_queues(struct sock *sk)
+{
+ struct sk_buff *skb;
+
+ /* First the read buffer. */
+ while((skb = skb_dequeue(&sk->receive_queue)) != NULL)
+ kfree_skb(skb);
+
+ /* Next, the error queue. */
+ while((skb = skb_dequeue(&sk->error_queue)) != NULL)
+ kfree_skb(skb);
+
+ /* Now the backlog. */
+ while((skb=skb_dequeue(&sk->back_log)) != NULL)
+ kfree_skb(skb);
+}
+
+static __inline__ void kill_sk_now(struct sock *sk)
+{
+ /* No longer exists. */
+ del_from_prot_sklist(sk);
+
+ /* Remove from protocol hash chains. */
+ sk->prot->unhash(sk);
+
+ if(sk->opt)
+ kfree(sk->opt);
+ dst_release(sk->dst_cache);
+ sk_free(sk);
+}
+
+static __inline__ void kill_sk_later(struct sock *sk)
+{
+ /* this should never happen. */
+ /* actually it can if an ack has just been sent. */
+ /*
+ * It's more normal than that...
+ * It can happen because a skb is still in the device queues
+ * [PR]
+ */
+
+ NETDEBUG(printk(KERN_DEBUG "Socket destroy delayed (r=%d w=%d)\n",
+ atomic_read(&sk->rmem_alloc),
+ atomic_read(&sk->wmem_alloc)));
+
+ sk->ack_backlog = 0;
+ release_sock(sk);
+ net_reset_timer(sk, TIME_DESTROY, SOCK_DESTROY_TIME);
+}
+
+void destroy_sock(struct sock *sk)
+{
+ lock_sock(sk); /* just to be safe. */
+
+ /* Now we can no longer get new packets or once the
+ * timers are killed, send them.
+ */
+ net_delete_timer(sk);
+
+ if (sk->prot->destroy && !sk->destroy)
+ sk->prot->destroy(sk);
+
+ sk->destroy = 1;
+
+ kill_sk_queues(sk);
+
+ /* Now if everything is gone we can free the socket
+ * structure, otherwise we need to keep it around until
+ * everything is gone.
+ */
+ if (atomic_read(&sk->rmem_alloc) == 0 && atomic_read(&sk->wmem_alloc) == 0)
+ kill_sk_now(sk);
+ else
+ kill_sk_later(sk);
+}
+
+/*
+ * The routines beyond this point handle the behaviour of an AF_INET
+ * socket object. Mostly it punts to the subprotocols of IP to do
+ * the work.
+ */
+
+
+/*
+ * Set socket options on an inet socket.
+ */
+
+int inet_setsockopt(struct socket *sock, int level, int optname,
+ char *optval, int optlen)
+{
+ struct sock *sk=sock->sk;
+ if (sk->prot->setsockopt==NULL)
+ return(-EOPNOTSUPP);
+ return sk->prot->setsockopt(sk,level,optname,optval,optlen);
+}
+
+/*
+ * Get a socket option on an AF_INET socket.
+ *
+ * FIX: POSIX 1003.1g is very ambiguous here. It states that
+ * asynchronous errors should be reported by getsockopt. We assume
+ * this means if you specify SO_ERROR (otherwise whats the point of it).
+ */
+
+int inet_getsockopt(struct socket *sock, int level, int optname,
+ char *optval, int *optlen)
+{
+ struct sock *sk=sock->sk;
+ if (sk->prot->getsockopt==NULL)
+ return(-EOPNOTSUPP);
+ return sk->prot->getsockopt(sk,level,optname,optval,optlen);
+}
+
+/*
+ * Automatically bind an unbound socket.
+ */
+
+static int inet_autobind(struct sock *sk)
+{
+ /* We may need to bind the socket. */
+ if (sk->num == 0) {
+ if (sk->prot->get_port(sk, 0) != 0)
+ return(-EAGAIN);
+ sk->sport = htons(sk->num);
+ sk->prot->hash(sk);
+ add_to_prot_sklist(sk);
+ }
+ return 0;
+}
+
+/*
+ * Move a socket into listening state.
+ */
+
+int inet_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+ unsigned char old_state;
+
+ if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
+ return(-EINVAL);
+
+ if ((unsigned) backlog == 0) /* BSDism */
+ backlog = 1;
+ if ((unsigned) backlog > SOMAXCONN)
+ backlog = SOMAXCONN;
+ sk->max_ack_backlog = backlog;
+
+ /* Really, if the socket is already in listen state
+ * we can only allow the backlog to be adjusted.
+ */
+ old_state = sk->state;
+ if (old_state != TCP_LISTEN) {
+ sk->state = TCP_LISTEN;
+ sk->ack_backlog = 0;
+ if (sk->num == 0) {
+ if (sk->prot->get_port(sk, 0) != 0) {
+ sk->state = old_state;
+ return -EAGAIN;
+ }
+ sk->sport = htons(sk->num);
+ add_to_prot_sklist(sk);
+ } else {
+ if (sk->prev)
+ ((struct tcp_bind_bucket*)sk->prev)->fastreuse = 0;
+ }
+
+ dst_release(xchg(&sk->dst_cache, NULL));
+ sk->prot->hash(sk);
+ sk->socket->flags |= SO_ACCEPTCON;
+ }
+ return 0;
+}
+
+/*
+ * Create an inet socket.
+ *
+ * FIXME: Gcc would generate much better code if we set the parameters
+ * up in in-memory structure order. Gcc68K even more so
+ */
+
+static int inet_create(struct socket *sock, int protocol)
+{
+ struct sock *sk;
+ struct proto *prot;
+
+ /* Compatibility */
+ if (sock->type == SOCK_PACKET) {
+ static int warned;
+ if (net_families[PF_PACKET]==NULL)
+ {
+#if defined(CONFIG_KMOD) && defined(CONFIG_PACKET_MODULE)
+ char module_name[30];
+ sprintf(module_name,"net-pf-%d", PF_PACKET);
+ request_module(module_name);
+ if (net_families[PF_PACKET] == NULL)
+#endif
+ return -ESOCKTNOSUPPORT;
+ }
+ if (!warned++)
+ printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);
+ return net_families[PF_PACKET]->create(sock, protocol);
+ }
+
+ sock->state = SS_UNCONNECTED;
+ sk = sk_alloc(PF_INET, GFP_KERNEL, 1);
+ if (sk == NULL)
+ goto do_oom;
+
+ switch (sock->type) {
+ case SOCK_STREAM:
+ if (protocol && protocol != IPPROTO_TCP)
+ goto free_and_noproto;
+ protocol = IPPROTO_TCP;
+ if (ipv4_config.no_pmtu_disc)
+ sk->ip_pmtudisc = IP_PMTUDISC_DONT;
+ else
+ sk->ip_pmtudisc = IP_PMTUDISC_WANT;
+ prot = &tcp_prot;
+ sock->ops = &inet_stream_ops;
+ break;
+ case SOCK_SEQPACKET:
+ goto free_and_badtype;
+ case SOCK_DGRAM:
+ if (protocol && protocol != IPPROTO_UDP)
+ goto free_and_noproto;
+ protocol = IPPROTO_UDP;
+ sk->no_check = UDP_NO_CHECK;
+ sk->ip_pmtudisc = IP_PMTUDISC_DONT;
+ prot=&udp_prot;
+ sock->ops = &inet_dgram_ops;
+ break;
+ case SOCK_RAW:
+ if (!capable(CAP_NET_RAW))
+ goto free_and_badperm;
+ if (!protocol)
+ goto free_and_noproto;
+ prot = &raw_prot;
+ sk->reuse = 1;
+ sk->ip_pmtudisc = IP_PMTUDISC_DONT;
+ sk->num = protocol;
+ sock->ops = &inet_dgram_ops;
+ if (protocol == IPPROTO_RAW)
+ sk->ip_hdrincl = 1;
+ break;
+ default:
+ goto free_and_badtype;
+ }
+
+ sock_init_data(sock,sk);
+
+ sk->destruct = NULL;
+
+ sk->zapped=0;
+#ifdef CONFIG_TCP_NAGLE_OFF
+ sk->nonagle = 1;
+#endif
+ sk->family = PF_INET;
+ sk->protocol = protocol;
+
+ sk->prot = prot;
+ sk->backlog_rcv = prot->backlog_rcv;
+
+ sk->timer.data = (unsigned long)sk;
+ sk->timer.function = &net_timer;
+
+ sk->ip_ttl=ip_statistics.IpDefaultTTL;
+
+ sk->ip_mc_loop=1;
+ sk->ip_mc_ttl=1;
+ sk->ip_mc_index=0;
+ sk->ip_mc_list=NULL;
+
+ if (sk->num) {
+ /* It assumes that any protocol which allows
+ * the user to assign a number at socket
+ * creation time automatically
+ * shares.
+ */
+ sk->sport = htons(sk->num);
+
+ /* Add to protocol hash chains. */
+ sk->prot->hash(sk);
+ add_to_prot_sklist(sk);
+ }
+
+ if (sk->prot->init) {
+ int err = sk->prot->init(sk);
+ if (err != 0) {
+ destroy_sock(sk);
+ return(err);
+ }
+ }
+ return(0);
+
+free_and_badtype:
+ sk_free(sk);
+ return -ESOCKTNOSUPPORT;
+
+free_and_badperm:
+ sk_free(sk);
+ return -EPERM;
+
+free_and_noproto:
+ sk_free(sk);
+ return -EPROTONOSUPPORT;
+
+do_oom:
+ return -ENOBUFS;
+}
+
+
+/*
+ * The peer socket should always be NULL (or else). When we call this
+ * function we are destroying the object and from then on nobody
+ * should refer to it.
+ */
+
+int inet_release(struct socket *sock, struct socket *peersock)
+{
+ struct sock *sk = sock->sk;
+
+ if (sk) {
+ long timeout;
+
+ /* Begin closedown and wake up sleepers. */
+ if (sock->state != SS_UNCONNECTED)
+ sock->state = SS_DISCONNECTING;
+ sk->state_change(sk);
+
+ /* Applications forget to leave groups before exiting */
+ ip_mc_drop_socket(sk);
+
+ /* If linger is set, we don't return until the close
+ * is complete. Otherwise we return immediately. The
+ * actually closing is done the same either way.
+ *
+ * If the close is due to the process exiting, we never
+ * linger..
+ */
+ timeout = 0;
+ if (sk->linger && !(current->flags & PF_EXITING)) {
+ timeout = HZ * sk->lingertime;
+ if (!timeout)
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ }
+ sock->sk = NULL;
+ sk->socket = NULL;
+ sk->prot->close(sk, timeout);
+ }
+ return(0);
+}
+
+static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+ struct sockaddr_in *addr=(struct sockaddr_in *)uaddr;
+ struct sock *sk=sock->sk;
+ unsigned short snum;
+ int chk_addr_ret;
+
+ /* If the socket has its own bind function then use it. (RAW) */
+ if(sk->prot->bind)
+ return sk->prot->bind(sk, uaddr, addr_len);
+
+ /* Check these errors (active socket, bad address length, double bind). */
+ if ((sk->state != TCP_CLOSE) ||
+ (addr_len < sizeof(struct sockaddr_in)) ||
+ (sk->num != 0))
+ return -EINVAL;
+
+ chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
+ if (addr->sin_addr.s_addr != 0 && chk_addr_ret != RTN_LOCAL &&
+ chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) {
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ /* Superuser may bind to any address to allow transparent proxying. */
+ if(chk_addr_ret != RTN_UNICAST || !capable(CAP_NET_ADMIN))
+#endif
+ return -EADDRNOTAVAIL; /* Source address MUST be ours! */
+ }
+
+ /* We keep a pair of addresses. rcv_saddr is the one
+ * used by hash lookups, and saddr is used for transmit.
+ *
+ * In the BSD API these are the same except where it
+ * would be illegal to use them (multicast/broadcast) in
+ * which case the sending device address is used.
+ */
+ sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr;
+ if(chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
+ sk->saddr = 0; /* Use device */
+
+ snum = ntohs(addr->sin_port);
+#ifdef CONFIG_IP_MASQUERADE
+ /* The kernel masquerader needs some ports. */
+ if((snum >= PORT_MASQ_BEGIN) && (snum <= PORT_MASQ_END))
+ return -EADDRINUSE;
+#endif
+ if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+ return(-EACCES);
+
+ /* Make sure we are allowed to bind here. */
+ if (sk->prot->get_port(sk, snum) != 0)
+ return -EADDRINUSE;
+
+ sk->sport = htons(sk->num);
+ sk->daddr = 0;
+ sk->dport = 0;
+ sk->prot->hash(sk);
+ add_to_prot_sklist(sk);
+ dst_release(sk->dst_cache);
+ sk->dst_cache=NULL;
+ return(0);
+}
+
+int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,
+ int addr_len, int flags)
+{
+ struct sock *sk=sock->sk;
+ int err;
+
+ if (inet_autobind(sk) != 0)
+ return(-EAGAIN);
+ if (sk->prot->connect == NULL)
+ return(-EOPNOTSUPP);
+ err = sk->prot->connect(sk, (struct sockaddr *)uaddr, addr_len);
+ if (err < 0)
+ return(err);
+ return(0);
+}
+
+static void inet_wait_for_connect(struct sock *sk)
+{
+ struct wait_queue wait = { current, NULL };
+
+ add_wait_queue(sk->sleep, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+ while (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {
+ if (signal_pending(current))
+ break;
+ if (sk->err)
+ break;
+ schedule();
+ current->state = TASK_INTERRUPTIBLE;
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+}
+
+/*
+ * Connect to a remote host. There is regrettably still a little
+ * TCP 'magic' in here.
+ */
+
+int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,
+ int addr_len, int flags)
+{
+ struct sock *sk=sock->sk;
+ int err;
+
+ if(sock->state != SS_UNCONNECTED && sock->state != SS_CONNECTING) {
+ if(sock->state == SS_CONNECTED)
+ return -EISCONN;
+ return -EINVAL;
+ }
+
+ if(sock->state == SS_CONNECTING) {
+ /* Note: tcp_connected contains SYN_RECV, which may cause
+ bogus results here. -AK */
+ if(tcp_connected(sk->state)) {
+ sock->state = SS_CONNECTED;
+ return 0;
+ }
+ if (sk->zapped || sk->err)
+ goto sock_error;
+ if (flags & O_NONBLOCK)
+ return -EALREADY;
+ } else {
+ if (sk->prot->connect == NULL)
+ return(-EOPNOTSUPP);
+
+ /* We may need to bind the socket. */
+ if (inet_autobind(sk) != 0)
+ return(-EAGAIN);
+
+ err = sk->prot->connect(sk, uaddr, addr_len);
+ /* Note: there is a theoretical race here when an wake up
+ occurred before inet_wait_for_connect is entered. In 2.3
+ the wait queue setup should be moved before the low level
+ connect call. -AK*/
+ if (err < 0)
+ return(err);
+ sock->state = SS_CONNECTING;
+ }
+
+ if (sk->state > TCP_FIN_WAIT2 && sock->state == SS_CONNECTING)
+ goto sock_error;
+
+ if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
+ return (-EINPROGRESS);
+
+ if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {
+ inet_wait_for_connect(sk);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+
+ sock->state = SS_CONNECTED;
+ if ((sk->state != TCP_ESTABLISHED) && sk->err)
+ goto sock_error;
+ return(0);
+
+sock_error:
+ /* This is ugly but needed to fix a race in the ICMP error handler */
+ if (sk->zapped && sk->state != TCP_CLOSE) {
+ lock_sock(sk);
+ tcp_set_state(sk, TCP_CLOSE);
+ release_sock(sk);
+ sk->zapped = 0;
+ }
+ sock->state = SS_UNCONNECTED;
+ return sock_error(sk);
+}
+
+/*
+ * Accept a pending connection. The TCP layer now gives BSD semantics.
+ */
+
+int inet_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+ struct sock *sk1 = sock->sk, *sk2;
+ struct sock *newsk = newsock->sk;
+ int err = -EINVAL;
+
+ if (sock->state != SS_UNCONNECTED || !(sock->flags & SO_ACCEPTCON))
+ goto do_err;
+
+ err = -EOPNOTSUPP;
+ if (sk1->prot->accept == NULL)
+ goto do_err;
+
+ if((sk2 = sk1->prot->accept(sk1,flags)) == NULL)
+ goto do_sk1_err;
+
+ /*
+ * We've been passed an extra socket.
+ * We need to free it up because the tcp module creates
+ * its own when it accepts one.
+ */
+ sk2->sleep = newsk->sleep;
+
+ newsock->sk = sk2;
+ sk2->socket = newsock;
+ newsk->socket = NULL;
+
+ if (flags & O_NONBLOCK)
+ goto do_half_success;
+
+ if(sk2->state == TCP_ESTABLISHED)
+ goto do_full_success;
+ if(sk2->err > 0)
+ goto do_connect_err;
+ err = -ECONNABORTED;
+ if (sk2->state == TCP_CLOSE)
+ goto do_bad_connection;
+do_full_success:
+ destroy_sock(newsk);
+ newsock->state = SS_CONNECTED;
+ return 0;
+
+do_half_success:
+ destroy_sock(newsk);
+ return(0);
+
+do_connect_err:
+ err = sock_error(sk2);
+do_bad_connection:
+ sk2->sleep = NULL;
+ sk2->socket = NULL;
+ destroy_sock(sk2);
+ newsock->sk = newsk;
+ newsk->socket = newsock;
+ return err;
+
+do_sk1_err:
+ err = sock_error(sk1);
+do_err:
+ return err;
+}
+
+
+/*
+ * This does both peername and sockname.
+ */
+
+static int inet_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *uaddr_len, int peer)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
+
+ sin->sin_family = AF_INET;
+ if (peer) {
+ if (!tcp_connected(sk->state))
+ return(-ENOTCONN);
+ sin->sin_port = sk->dport;
+ sin->sin_addr.s_addr = sk->daddr;
+ } else {
+ __u32 addr = sk->rcv_saddr;
+ if (!addr)
+ addr = sk->saddr;
+ sin->sin_port = sk->sport;
+ sin->sin_addr.s_addr = addr;
+ }
+ *uaddr_len = sizeof(*sin);
+ return(0);
+}
+
+
+
+int inet_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+ int flags, struct scm_cookie *scm)
+{
+ struct sock *sk = sock->sk;
+ int addr_len = 0;
+ int err;
+
+ if (sock->flags & SO_ACCEPTCON)
+ return(-EINVAL);
+ if (sk->prot->recvmsg == NULL)
+ return(-EOPNOTSUPP);
+ /* We may need to bind the socket. */
+ if (inet_autobind(sk) != 0)
+ return(-EAGAIN);
+ err = sk->prot->recvmsg(sk, msg, size, flags&MSG_DONTWAIT,
+ flags&~MSG_DONTWAIT, &addr_len);
+ if (err >= 0)
+ msg->msg_namelen = addr_len;
+ return err;
+}
+
+
+int inet_sendmsg(struct socket *sock, struct msghdr *msg, int size,
+ struct scm_cookie *scm)
+{
+ struct sock *sk = sock->sk;
+
+ if (sk->shutdown & SEND_SHUTDOWN) {
+ if (!(msg->msg_flags&MSG_NOSIGNAL))
+ send_sig(SIGPIPE, current, 1);
+ return(-EPIPE);
+ }
+ if (sk->prot->sendmsg == NULL)
+ return(-EOPNOTSUPP);
+ if(sk->err)
+ return sock_error(sk);
+
+ /* We may need to bind the socket. */
+ if (inet_autobind(sk) != 0)
+ return -EAGAIN;
+
+ return sk->prot->sendmsg(sk, msg, size);
+}
+
+
+int inet_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+
+ /* This should really check to make sure
+ * the socket is a TCP socket. (WHY AC...)
+ */
+ how++; /* maps 0->1 has the advantage of making bit 1 rcvs and
+ 1->2 bit 2 snds.
+ 2->3 */
+ if ((how & ~SHUTDOWN_MASK) || how==0) /* MAXINT->0 */
+ return(-EINVAL);
+ if (!sk)
+ return(-ENOTCONN);
+ if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)
+ sock->state = SS_CONNECTED;
+ if (!tcp_connected(sk->state))
+ return(-ENOTCONN);
+ sk->shutdown |= how;
+ if (sk->prot->shutdown)
+ sk->prot->shutdown(sk, how);
+ /* Wake up anyone sleeping in poll. */
+ sk->state_change(sk);
+ return(0);
+}
+
+
+unsigned int inet_poll(struct file * file, struct socket *sock, poll_table *wait)
+{
+ struct sock *sk = sock->sk;
+
+ if (sk->prot->poll == NULL)
+ return(0);
+ return sk->prot->poll(file, sock, wait);
+}
+
+/*
+ * ioctl() calls you can issue on an INET socket. Most of these are
+ * device configuration and stuff and very rarely used. Some ioctls
+ * pass on to the socket itself.
+ *
+ * NOTE: I like the idea of a module for the config stuff. ie ifconfig
+ * loads the devconfigure module does its configuring and unloads it.
+ * There's a good 20K of config code hanging around the kernel.
+ */
+
+static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ struct sock *sk = sock->sk;
+ int err;
+ int pid;
+
+ switch(cmd)
+ {
+ case FIOSETOWN:
+ case SIOCSPGRP:
+ err = get_user(pid, (int *) arg);
+ if (err)
+ return err;
+ if (current->pid != pid && current->pgrp != -pid &&
+ !capable(CAP_NET_ADMIN))
+ return -EPERM;
+ sk->proc = pid;
+ return(0);
+ case FIOGETOWN:
+ case SIOCGPGRP:
+ return put_user(sk->proc, (int *)arg);
+ case SIOCGSTAMP:
+ if(sk->stamp.tv_sec==0)
+ return -ENOENT;
+ err = copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
+ if (err)
+ err = -EFAULT;
+ return err;
+ case SIOCADDRT:
+ case SIOCDELRT:
+ case SIOCRTMSG:
+ return(ip_rt_ioctl(cmd,(void *) arg));
+ case SIOCDARP:
+ case SIOCGARP:
+ case SIOCSARP:
+ return(arp_ioctl(cmd,(void *) arg));
+ case SIOCDRARP:
+ case SIOCGRARP:
+ case SIOCSRARP:
+#ifdef CONFIG_KMOD
+ if (rarp_ioctl_hook == NULL)
+ request_module("rarp");
+#endif
+ if (rarp_ioctl_hook != NULL)
+ return(rarp_ioctl_hook(cmd,(void *) arg));
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ case SIOCGIFBRDADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCGIFNETMASK:
+ case SIOCSIFNETMASK:
+ case SIOCGIFDSTADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFPFLAGS:
+ case SIOCGIFPFLAGS:
+ case SIOCSIFFLAGS:
+ return(devinet_ioctl(cmd,(void *) arg));
+ case SIOCGIFBR:
+ case SIOCSIFBR:
+#ifdef CONFIG_BRIDGE
+ return(br_ioctl(cmd,(void *) arg));
+#else
+ return -ENOPKG;
+#endif
+
+ case SIOCADDDLCI:
+ case SIOCDELDLCI:
+#ifdef CONFIG_DLCI
+ return(dlci_ioctl(cmd, (void *) arg));
+#endif
+
+#ifdef CONFIG_DLCI_MODULE
+
+#ifdef CONFIG_KMOD
+ if (dlci_ioctl_hook == NULL)
+ request_module("dlci");
+#endif
+
+ if (dlci_ioctl_hook)
+ return((*dlci_ioctl_hook)(cmd, (void *) arg));
+#endif
+ return -ENOPKG;
+
+ default:
+ if ((cmd >= SIOCDEVPRIVATE) &&
+ (cmd <= (SIOCDEVPRIVATE + 15)))
+ return(dev_ioctl(cmd,(void *) arg));
+
+#ifdef CONFIG_NET_RADIO
+ if((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST))
+ return(dev_ioctl(cmd,(void *) arg));
+#endif
+
+ if (sk->prot->ioctl==NULL || (err=sk->prot->ioctl(sk, cmd, arg))==-ENOIOCTLCMD)
+ return(dev_ioctl(cmd,(void *) arg));
+ return err;
+ }
+ /*NOTREACHED*/
+ return(0);
+}
+
+struct proto_ops inet_stream_ops = {
+ PF_INET,
+
+ sock_no_dup,
+ inet_release,
+ inet_bind,
+ inet_stream_connect,
+ sock_no_socketpair,
+ inet_accept,
+ inet_getname,
+ inet_poll,
+ inet_ioctl,
+ inet_listen,
+ inet_shutdown,
+ inet_setsockopt,
+ inet_getsockopt,
+ sock_no_fcntl,
+ inet_sendmsg,
+ inet_recvmsg
+};
+
+struct proto_ops inet_dgram_ops = {
+ PF_INET,
+
+ sock_no_dup,
+ inet_release,
+ inet_bind,
+ inet_dgram_connect,
+ sock_no_socketpair,
+ sock_no_accept,
+ inet_getname,
+ datagram_poll,
+ inet_ioctl,
+ sock_no_listen,
+ inet_shutdown,
+ inet_setsockopt,
+ inet_getsockopt,
+ sock_no_fcntl,
+ inet_sendmsg,
+ inet_recvmsg
+};
+
+struct net_proto_family inet_family_ops = {
+ PF_INET,
+ inet_create
+};
+
+
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_INET_RARP
+static struct proc_dir_entry proc_net_rarp = {
+ PROC_NET_RARP, 4, "rarp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ rarp_get_info
+};
+#endif /* RARP */
+static struct proc_dir_entry proc_net_raw = {
+ PROC_NET_RAW, 3, "raw",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ raw_get_info
+};
+static struct proc_dir_entry proc_net_netstat = {
+ PROC_NET_NETSTAT, 7, "netstat",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ netstat_get_info
+};
+static struct proc_dir_entry proc_net_snmp = {
+ PROC_NET_SNMP, 4, "snmp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ snmp_get_info
+};
+static struct proc_dir_entry proc_net_sockstat = {
+ PROC_NET_SOCKSTAT, 8, "sockstat",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ afinet_get_info
+};
+static struct proc_dir_entry proc_net_tcp = {
+ PROC_NET_TCP, 3, "tcp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ tcp_get_info
+};
+static struct proc_dir_entry proc_net_udp = {
+ PROC_NET_UDP, 3, "udp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ udp_get_info
+};
+#endif /* CONFIG_PROC_FS */
+
+extern void tcp_init(void);
+extern void tcp_v4_init(struct net_proto_family *);
+
+
+/*
+ * Called by socket.c on kernel startup.
+ */
+
+__initfunc(void inet_proto_init(struct net_proto *pro))
+{
+ struct sk_buff *dummy_skb;
+ struct inet_protocol *p;
+
+ printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n");
+
+ if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb))
+ {
+ printk(KERN_CRIT "inet_proto_init: panic\n");
+ return;
+ }
+
+ /*
+ * Tell SOCKET that we are alive...
+ */
+
+ (void) sock_register(&inet_family_ops);
+
+ /*
+ * Add all the protocols.
+ */
+
+ printk(KERN_INFO "IP Protocols: ");
+ for(p = inet_protocol_base; p != NULL;)
+ {
+ struct inet_protocol *tmp = (struct inet_protocol *) p->next;
+ inet_add_protocol(p);
+ printk("%s%s",p->name,tmp?", ":"\n");
+ p = tmp;
+ }
+
+ /*
+ * Set the ARP module up
+ */
+
+ arp_init();
+
+ /*
+ * Set the IP module up
+ */
+
+ ip_init();
+
+ tcp_v4_init(&inet_family_ops);
+
+ /* Setup TCP slab cache for open requests. */
+ tcp_init();
+
+
+ /*
+ * Set the ICMP layer up
+ */
+
+ icmp_init(&inet_family_ops);
+
+ /* I wish inet_add_protocol had no constructor hook...
+ I had to move IPIP from net/ipv4/protocol.c :-( --ANK
+ */
+#ifdef CONFIG_NET_IPIP
+ ipip_init();
+#endif
+#ifdef CONFIG_NET_IPGRE
+ ipgre_init();
+#endif
+
+ /*
+ * Set the firewalling up
+ */
+#if defined(CONFIG_IP_FIREWALL)
+ ip_fw_init();
+#endif
+
+#ifdef CONFIG_IP_MASQUERADE
+ ip_masq_init();
+#endif
+
+ /*
+ * Initialise the multicast router
+ */
+#if defined(CONFIG_IP_MROUTE)
+ ip_mr_init();
+#endif
+
+#ifdef CONFIG_INET_RARP
+ rarp_ioctl_hook = rarp_ioctl;
+#endif
+ /*
+ * Create all the /proc entries.
+ */
+
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_INET_RARP
+ proc_net_register(&proc_net_rarp);
+#endif /* RARP */
+ proc_net_register(&proc_net_raw);
+ proc_net_register(&proc_net_snmp);
+ proc_net_register(&proc_net_netstat);
+ proc_net_register(&proc_net_sockstat);
+ proc_net_register(&proc_net_tcp);
+ proc_net_register(&proc_net_udp);
+#endif /* CONFIG_PROC_FS */
+}
diff --git a/pfinet/linux-src/net/ipv4/arp.c b/pfinet/linux-src/net/ipv4/arp.c
new file mode 100644
index 00000000..27d2f802
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/arp.c
@@ -0,0 +1,1154 @@
+/* linux/net/inet/arp.c
+ *
+ * Version: $Id: arp.c,v 1.77.2.1 1999/06/28 10:39:23 davem Exp $
+ *
+ * Copyright (C) 1994 by Florian La Roche
+ *
+ * This module implements the Address Resolution Protocol ARP (RFC 826),
+ * which is used to convert IP addresses (or in the future maybe other
+ * high-level addresses) into a low-level hardware address (like an Ethernet
+ * address).
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ * Alan Cox : Removed the Ethernet assumptions in
+ * Florian's code
+ * Alan Cox : Fixed some small errors in the ARP
+ * logic
+ * Alan Cox : Allow >4K in /proc
+ * Alan Cox : Make ARP add its own protocol entry
+ * Ross Martin : Rewrote arp_rcv() and arp_get_info()
+ * Stephen Henson : Add AX25 support to arp_get_info()
+ * Alan Cox : Drop data when a device is downed.
+ * Alan Cox : Use init_timer().
+ * Alan Cox : Double lock fixes.
+ * Martin Seine : Move the arphdr structure
+ * to if_arp.h for compatibility.
+ * with BSD based programs.
+ * Andrew Tridgell : Added ARP netmask code and
+ * re-arranged proxy handling.
+ * Alan Cox : Changed to use notifiers.
+ * Niibe Yutaka : Reply for this device or proxies only.
+ * Alan Cox : Don't proxy across hardware types!
+ * Jonathan Naylor : Added support for NET/ROM.
+ * Mike Shaver : RFC1122 checks.
+ * Jonathan Naylor : Only lookup the hardware address for
+ * the correct hardware type.
+ * Germano Caronni : Assorted subtle races.
+ * Craig Schlenter : Don't modify permanent entry
+ * during arp_rcv.
+ * Russ Nelson : Tidied up a few bits.
+ * Alexey Kuznetsov: Major changes to caching and behaviour,
+ * eg intelligent arp probing and
+ * generation
+ * of host down events.
+ * Alan Cox : Missing unlock in device events.
+ * Eckes : ARP ioctl control errors.
+ * Alexey Kuznetsov: Arp free fix.
+ * Manuel Rodriguez: Gratuitous ARP.
+ * Jonathan Layes : Added arpd support through kerneld
+ * message queue (960314)
+ * Mike Shaver : /proc/sys/net/ipv4/arp_* support
+ * Mike McLagan : Routing by source
+ * Stuart Cheshire : Metricom and grat arp fixes
+ * *** FOR 2.1 clean this up ***
+ * Lawrence V. Stefani: (08/12/96) Added FDDI support.
+ * Alan Cox : Took the AP1000 nasty FDDI hack and
+ * folded into the mainstream FDDI code.
+ * Ack spit, Linus how did you allow that
+ * one in...
+ * Jes Sorensen : Make FDDI work again in 2.1.x and
+ * clean up the APFDDI & gen. FDDI bits.
+ * Alexey Kuznetsov: new arp state machine;
+ * now it is in net/core/neighbour.c.
+ */
+
+/* RFC1122 Status:
+ 2.3.2.1 (ARP Cache Validation):
+ MUST provide mechanism to flush stale cache entries (OK)
+ SHOULD be able to configure cache timeout (OK)
+ MUST throttle ARP retransmits (OK)
+ 2.3.2.2 (ARP Packet Queue):
+ SHOULD save at least one packet from each "conversation" with an
+ unresolved IP address. (OK)
+ 950727 -- MS
+*/
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/config.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/mm.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/fddidevice.h>
+#include <linux/if_arp.h>
+#include <linux/trdevice.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+#endif
+
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/route.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <net/arp.h>
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+#include <net/ax25.h>
+#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+#include <net/netrom.h>
+#endif
+#endif
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+/*
+ * Interface to generic neighbour cache.
+ */
+static int arp_constructor(struct neighbour *neigh);
+static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
+static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
+static void parp_redo(struct sk_buff *skb);
+
+static struct neigh_ops arp_generic_ops =
+{
+ AF_INET,
+ NULL,
+ arp_solicit,
+ arp_error_report,
+ neigh_resolve_output,
+ neigh_connected_output,
+ dev_queue_xmit,
+ dev_queue_xmit
+};
+
+static struct neigh_ops arp_hh_ops =
+{
+ AF_INET,
+ NULL,
+ arp_solicit,
+ arp_error_report,
+ neigh_resolve_output,
+ neigh_resolve_output,
+ dev_queue_xmit,
+ dev_queue_xmit
+};
+
+static struct neigh_ops arp_direct_ops =
+{
+ AF_INET,
+ NULL,
+ NULL,
+ NULL,
+ dev_queue_xmit,
+ dev_queue_xmit,
+ dev_queue_xmit,
+ dev_queue_xmit
+};
+
+struct neigh_ops arp_broken_ops =
+{
+ AF_INET,
+ NULL,
+ arp_solicit,
+ arp_error_report,
+ neigh_compat_output,
+ neigh_compat_output,
+ dev_queue_xmit,
+ dev_queue_xmit,
+};
+
+struct neigh_table arp_tbl =
+{
+ NULL,
+ AF_INET,
+ sizeof(struct neighbour) + 4,
+ 4,
+ arp_constructor,
+ NULL,
+ NULL,
+ parp_redo,
+ { NULL, NULL, &arp_tbl, 0, NULL, NULL,
+ 30*HZ, 1*HZ, 60*HZ, 30*HZ, 5*HZ, 3, 3, 0, 3, 1*HZ, (8*HZ)/10, 64, 1*HZ },
+ 30*HZ, 128, 512, 1024,
+};
+
+int arp_mc_map(u32 addr, u8 *haddr, struct device *dev, int dir)
+{
+ switch (dev->type) {
+ case ARPHRD_ETHER:
+ case ARPHRD_IEEE802:
+ case ARPHRD_FDDI:
+ ip_eth_mc_map(addr, haddr);
+ return 0;
+ default:
+ if (dir) {
+ memcpy(haddr, dev->broadcast, dev->addr_len);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+
+
+static int arp_constructor(struct neighbour *neigh)
+{
+ u32 addr = *(u32*)neigh->primary_key;
+ struct device *dev = neigh->dev;
+ struct in_device *in_dev = dev->ip_ptr;
+
+ if (in_dev == NULL)
+ return -EINVAL;
+
+ neigh->type = inet_addr_type(addr);
+ if (in_dev->arp_parms)
+ neigh->parms = in_dev->arp_parms;
+
+ if (dev->hard_header == NULL) {
+ neigh->nud_state = NUD_NOARP;
+ neigh->ops = &arp_direct_ops;
+ neigh->output = neigh->ops->queue_xmit;
+ } else {
+ /* Good devices (checked by reading texts, but only Ethernet is
+ tested)
+
+ ARPHRD_ETHER: (ethernet, apfddi)
+ ARPHRD_FDDI: (fddi)
+ ARPHRD_IEEE802: (tr)
+ ARPHRD_METRICOM: (strip)
+ ARPHRD_ARCNET:
+ etc. etc. etc.
+
+ ARPHRD_IPDDP will also work, if author repairs it.
+ I did not it, because this driver does not work even
+ in old paradigm.
+ */
+
+#if 1
+ /* So... these "amateur" devices are hopeless.
+ The only thing, that I can say now:
+ It is very sad that we need to keep ugly obsolete
+ code to make them happy.
+
+ They should be moved to more reasonable state, now
+ they use rebuild_header INSTEAD OF hard_start_xmit!!!
+ Besides that, they are sort of out of date
+ (a lot of redundant clones/copies, useless in 2.1),
+ I wonder why people believe that they work.
+ */
+ switch (dev->type) {
+ default:
+ break;
+ case ARPHRD_ROSE:
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ case ARPHRD_AX25:
+#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+ case ARPHRD_NETROM:
+#endif
+ neigh->ops = &arp_broken_ops;
+ neigh->output = neigh->ops->output;
+ return 0;
+#endif
+ }
+#endif
+ if (neigh->type == RTN_MULTICAST) {
+ neigh->nud_state = NUD_NOARP;
+ arp_mc_map(addr, neigh->ha, dev, 1);
+ } else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
+ neigh->nud_state = NUD_NOARP;
+ memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
+ } else if (neigh->type == RTN_BROADCAST || dev->flags&IFF_POINTOPOINT) {
+ neigh->nud_state = NUD_NOARP;
+ memcpy(neigh->ha, dev->broadcast, dev->addr_len);
+ }
+ if (dev->hard_header_cache)
+ neigh->ops = &arp_hh_ops;
+ else
+ neigh->ops = &arp_generic_ops;
+ if (neigh->nud_state&NUD_VALID)
+ neigh->output = neigh->ops->connected_output;
+ else
+ neigh->output = neigh->ops->output;
+ }
+
+ return 0;
+}
+
+static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb)
+{
+ dst_link_failure(skb);
+ kfree_skb(skb);
+}
+
+static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
+{
+ u32 saddr;
+ u8 *dst_ha = NULL;
+ struct device *dev = neigh->dev;
+ u32 target = *(u32*)neigh->primary_key;
+ int probes = neigh->probes;
+
+ if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+ saddr = skb->nh.iph->saddr;
+ else
+ saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
+
+ if ((probes -= neigh->parms->ucast_probes) < 0) {
+ if (!(neigh->nud_state&NUD_VALID))
+ printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n");
+ dst_ha = neigh->ha;
+ } else if ((probes -= neigh->parms->app_probes) < 0) {
+#ifdef CONFIG_ARPD
+ neigh_app_ns(neigh);
+#endif
+ return;
+ }
+
+ arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
+ dst_ha, dev->dev_addr, NULL);
+}
+
+/* OBSOLETE FUNCTIONS */
+
+/*
+ * Find an arp mapping in the cache. If not found, post a request.
+ *
+ * It is very UGLY routine: it DOES NOT use skb->dst->neighbour,
+ * even if it exists. It is supposed that skb->dev was mangled
+ * by a virtual device (eql, shaper). Nobody but broken devices
+ * is allowed to use this function, it is scheduled to be removed. --ANK
+ */
+
+static int arp_set_predefined(int addr_hint, unsigned char * haddr, u32 paddr, struct device * dev)
+{
+ switch (addr_hint) {
+ case RTN_LOCAL:
+ printk(KERN_DEBUG "ARP: arp called for own IP address\n");
+ memcpy(haddr, dev->dev_addr, dev->addr_len);
+ return 1;
+ case RTN_MULTICAST:
+ arp_mc_map(paddr, haddr, dev, 1);
+ return 1;
+ case RTN_BROADCAST:
+ memcpy(haddr, dev->broadcast, dev->addr_len);
+ return 1;
+ }
+ return 0;
+}
+
+
+int arp_find(unsigned char *haddr, struct sk_buff *skb)
+{
+ struct device *dev = skb->dev;
+ u32 paddr;
+ struct neighbour *n;
+
+ if (!skb->dst) {
+ printk(KERN_DEBUG "arp_find is called with dst==NULL\n");
+ kfree_skb(skb);
+ return 1;
+ }
+
+ paddr = ((struct rtable*)skb->dst)->rt_gateway;
+
+ if (arp_set_predefined(inet_addr_type(paddr), haddr, paddr, dev))
+ return 0;
+
+ start_bh_atomic();
+ n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
+
+ if (n) {
+ n->used = jiffies;
+ if (n->nud_state&NUD_VALID || neigh_event_send(n, skb) == 0) {
+ memcpy(haddr, n->ha, dev->addr_len);
+ neigh_release(n);
+ end_bh_atomic();
+ return 0;
+ }
+ neigh_release(n);
+ } else
+ kfree_skb(skb);
+ end_bh_atomic();
+ return 1;
+}
+
+/* END OF OBSOLETE FUNCTIONS */
+
+/*
+ * Note: requires bh_atomic locking.
+ */
+int arp_bind_neighbour(struct dst_entry *dst)
+{
+ struct device *dev = dst->dev;
+
+ if (dev == NULL)
+ return 0;
+ if (dst->neighbour == NULL) {
+ u32 nexthop = ((struct rtable*)dst)->rt_gateway;
+ if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
+ nexthop = 0;
+ dst->neighbour = __neigh_lookup(&arp_tbl, &nexthop, dev, 1);
+ }
+ return (dst->neighbour != NULL);
+}
+
+/*
+ * Interface to link layer: send routine and receive handler.
+ */
+
+/*
+ * Create and send an arp packet. If (dest_hw == NULL), we create a broadcast
+ * message.
+ */
+
+void arp_send(int type, int ptype, u32 dest_ip,
+ struct device *dev, u32 src_ip,
+ unsigned char *dest_hw, unsigned char *src_hw,
+ unsigned char *target_hw)
+{
+ struct sk_buff *skb;
+ struct arphdr *arp;
+ unsigned char *arp_ptr;
+
+ /*
+ * No arp on this interface.
+ */
+
+ if (dev->flags&IFF_NOARP)
+ return;
+
+ /*
+ * Allocate a buffer
+ */
+
+ skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
+ + dev->hard_header_len + 15, GFP_ATOMIC);
+ if (skb == NULL)
+ return;
+
+ skb_reserve(skb, (dev->hard_header_len+15)&~15);
+ skb->nh.raw = skb->data;
+ arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));
+ skb->dev = dev;
+ skb->protocol = __constant_htons (ETH_P_ARP);
+ if (src_hw == NULL)
+ src_hw = dev->dev_addr;
+ if (dest_hw == NULL)
+ dest_hw = dev->broadcast;
+
+ /*
+ * Fill the device header for the ARP frame
+ */
+ dev->hard_header(skb,dev,ptype,dest_hw,src_hw,skb->len);
+
+ /*
+ * Fill out the arp protocol part.
+ *
+ * The arp hardware type should match the device type, except for FDDI,
+ * which (according to RFC 1390) should always equal 1 (Ethernet).
+ */
+ /*
+ * Exceptions everywhere. AX.25 uses the AX.25 PID value not the
+ * DIX code for the protocol. Make these device structure fields.
+ */
+ switch (dev->type) {
+ default:
+ arp->ar_hrd = htons(dev->type);
+ arp->ar_pro = __constant_htons(ETH_P_IP);
+ break;
+
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ case ARPHRD_AX25:
+ arp->ar_hrd = __constant_htons(ARPHRD_AX25);
+ arp->ar_pro = __constant_htons(AX25_P_IP);
+ break;
+
+#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+ case ARPHRD_NETROM:
+ arp->ar_hrd = __constant_htons(ARPHRD_NETROM);
+ arp->ar_pro = __constant_htons(AX25_P_IP);
+ break;
+#endif
+#endif
+
+#ifdef CONFIG_FDDI
+ case ARPHRD_FDDI:
+ arp->ar_hrd = __constant_htons(ARPHRD_ETHER);
+ arp->ar_pro = __constant_htons(ETH_P_IP);
+ break;
+#endif
+ }
+
+ arp->ar_hln = dev->addr_len;
+ arp->ar_pln = 4;
+ arp->ar_op = htons(type);
+
+ arp_ptr=(unsigned char *)(arp+1);
+
+ memcpy(arp_ptr, src_hw, dev->addr_len);
+ arp_ptr+=dev->addr_len;
+ memcpy(arp_ptr, &src_ip,4);
+ arp_ptr+=4;
+ if (target_hw != NULL)
+ memcpy(arp_ptr, target_hw, dev->addr_len);
+ else
+ memset(arp_ptr, 0, dev->addr_len);
+ arp_ptr+=dev->addr_len;
+ memcpy(arp_ptr, &dest_ip, 4);
+ skb->dev = dev;
+
+ dev_queue_xmit(skb);
+}
+
+static void parp_redo(struct sk_buff *skb)
+{
+ arp_rcv(skb, skb->dev, NULL);
+}
+
+/*
+ * Receive an arp request by the device layer.
+ */
+
+int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+{
+ struct arphdr *arp = skb->nh.arph;
+ unsigned char *arp_ptr= (unsigned char *)(arp+1);
+ struct rtable *rt;
+ unsigned char *sha, *tha;
+ u32 sip, tip;
+ u16 dev_type = dev->type;
+ int addr_type;
+ struct in_device *in_dev = dev->ip_ptr;
+ struct neighbour *n;
+
+/*
+ * The hardware length of the packet should match the hardware length
+ * of the device. Similarly, the hardware types should match. The
+ * device should be ARP-able. Also, if pln is not 4, then the lookup
+ * is not from an IP number. We can't currently handle this, so toss
+ * it.
+ */
+ if (in_dev == NULL ||
+ arp->ar_hln != dev->addr_len ||
+ dev->flags & IFF_NOARP ||
+ skb->pkt_type == PACKET_OTHERHOST ||
+ skb->pkt_type == PACKET_LOOPBACK ||
+ arp->ar_pln != 4)
+ goto out;
+
+ switch (dev_type) {
+ default:
+ if (arp->ar_pro != __constant_htons(ETH_P_IP))
+ goto out;
+ if (htons(dev_type) != arp->ar_hrd)
+ goto out;
+ break;
+#ifdef CONFIG_NET_ETHERNET
+ case ARPHRD_ETHER:
+ /*
+ * ETHERNET devices will accept ARP hardware types of either
+ * 1 (Ethernet) or 6 (IEEE 802.2).
+ */
+ if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&
+ arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))
+ goto out;
+ if (arp->ar_pro != __constant_htons(ETH_P_IP))
+ goto out;
+ break;
+#endif
+#ifdef CONFIG_FDDI
+ case ARPHRD_FDDI:
+ /*
+ * According to RFC 1390, FDDI devices should accept ARP hardware types
+ * of 1 (Ethernet). However, to be more robust, we'll accept hardware
+ * types of either 1 (Ethernet) or 6 (IEEE 802.2).
+ */
+ if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&
+ arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))
+ goto out;
+ if (arp->ar_pro != __constant_htons(ETH_P_IP))
+ goto out;
+ break;
+#endif
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ case ARPHRD_AX25:
+ if (arp->ar_pro != __constant_htons(AX25_P_IP))
+ goto out;
+ if (arp->ar_hrd != __constant_htons(ARPHRD_AX25))
+ goto out;
+ break;
+#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+ case ARPHRD_NETROM:
+ if (arp->ar_pro != __constant_htons(AX25_P_IP))
+ goto out;
+ if (arp->ar_hrd != __constant_htons(ARPHRD_NETROM))
+ goto out;
+ break;
+#endif
+#endif
+ }
+
+ /* Undertsand only these message types */
+
+ if (arp->ar_op != __constant_htons(ARPOP_REPLY) &&
+ arp->ar_op != __constant_htons(ARPOP_REQUEST))
+ goto out;
+
+/*
+ * Extract fields
+ */
+ sha=arp_ptr;
+ arp_ptr += dev->addr_len;
+ memcpy(&sip, arp_ptr, 4);
+ arp_ptr += 4;
+ tha=arp_ptr;
+ arp_ptr += dev->addr_len;
+ memcpy(&tip, arp_ptr, 4);
+/*
+ * Check for bad requests for 127.x.x.x and requests for multicast
+ * addresses. If this is one such, delete it.
+ */
+ if (LOOPBACK(tip) || MULTICAST(tip))
+ goto out;
+
+/*
+ * Process entry. The idea here is we want to send a reply if it is a
+ * request for us or if it is a request for someone else that we hold
+ * a proxy for. We want to add an entry to our cache if it is a reply
+ * to us or if it is a request for our address.
+ * (The assumption for this last is that if someone is requesting our
+ * address, they are probably intending to talk to us, so it saves time
+ * if we cache their address. Their address is also probably not in
+ * our cache, since ours is not in their cache.)
+ *
+ * Putting this another way, we only care about replies if they are to
+ * us, in which case we add them to the cache. For requests, we care
+ * about those for us and those for our proxies. We reply to both,
+ * and in the case of requests for us we add the requester to the arp
+ * cache.
+ */
+
+ /* Special case: IPv4 duplicate address detection packet (RFC2131) */
+ if (sip == 0) {
+ if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
+ inet_addr_type(tip) == RTN_LOCAL)
+ arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
+ goto out;
+ }
+
+ if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
+ ip_route_input(skb, tip, sip, 0, dev) == 0) {
+
+ rt = (struct rtable*)skb->dst;
+ addr_type = rt->rt_type;
+
+ if (addr_type == RTN_LOCAL) {
+ n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
+ if (n) {
+ arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+ neigh_release(n);
+ }
+ goto out;
+ } else if (IN_DEV_FORWARD(in_dev)) {
+ if ((rt->rt_flags&RTCF_DNAT) ||
+ (addr_type == RTN_UNICAST && rt->u.dst.dev != dev &&
+ (IN_DEV_PROXY_ARP(in_dev) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) {
+ n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
+ neigh_release(n);
+
+ if (skb->stamp.tv_sec == 0 ||
+ skb->pkt_type == PACKET_HOST ||
+ in_dev->arp_parms->proxy_delay == 0) {
+ arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+ } else {
+ pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb);
+ return 0;
+ }
+ goto out;
+ }
+ }
+ }
+
+ /* Update our ARP tables */
+
+ n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
+
+#ifdef CONFIG_IP_ACCEPT_UNSOLICITED_ARP
+ /* Unsolicited ARP is not accepted by default.
+ It is possible, that this option should be enabled for some
+ devices (strip is candidate)
+ */
+ if (n == NULL &&
+ arp->ar_op == __constant_htons(ARPOP_REPLY) &&
+ inet_addr_type(sip) == RTN_UNICAST)
+ n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
+#endif
+
+ if (n) {
+ int state = NUD_REACHABLE;
+ int override = 0;
+
+ /* If several different ARP replies follows back-to-back,
+ use the FIRST one. It is possible, if several proxy
+ agents are active. Taking the first reply prevents
+ arp trashing and chooses the fastest router.
+ */
+ if (jiffies - n->updated >= n->parms->locktime)
+ override = 1;
+
+ /* Broadcast replies and request packets
+ do not assert neighbour reachability.
+ */
+ if (arp->ar_op != __constant_htons(ARPOP_REPLY) ||
+ skb->pkt_type != PACKET_HOST)
+ state = NUD_STALE;
+ neigh_update(n, sha, state, override, 1);
+ neigh_release(n);
+ }
+
+out:
+ kfree_skb(skb);
+ return 0;
+}
+
+
+
+/*
+ * User level interface (ioctl, /proc)
+ */
+
+/*
+ * Set (create) an ARP cache entry.
+ */
+
+int arp_req_set(struct arpreq *r, struct device * dev)
+{
+ u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+ struct neighbour *neigh;
+ int err;
+
+ if (r->arp_flags&ATF_PUBL) {
+ u32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;
+ if (mask && mask != 0xFFFFFFFF)
+ return -EINVAL;
+ if (!dev && (r->arp_flags & ATF_COM)) {
+ dev = dev_getbyhwaddr(r->arp_ha.sa_family, r->arp_ha.sa_data);
+ if (!dev)
+ return -ENODEV;
+ }
+ if (mask) {
+ if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL)
+ return -ENOBUFS;
+ return 0;
+ }
+ if (dev == NULL) {
+ ipv4_devconf.proxy_arp = 1;
+ return 0;
+ }
+ if (dev->ip_ptr) {
+ ((struct in_device*)dev->ip_ptr)->cnf.proxy_arp = 1;
+ return 0;
+ }
+ return -ENXIO;
+ }
+
+ if (r->arp_flags & ATF_PERM)
+ r->arp_flags |= ATF_COM;
+ if (dev == NULL) {
+ struct rtable * rt;
+ if ((err = ip_route_output(&rt, ip, 0, RTO_ONLINK, 0)) != 0)
+ return err;
+ dev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ if (!dev)
+ return -EINVAL;
+ }
+ if (r->arp_ha.sa_family != dev->type)
+ return -EINVAL;
+
+ err = -ENOBUFS;
+ start_bh_atomic();
+ neigh = __neigh_lookup(&arp_tbl, &ip, dev, 1);
+ if (neigh) {
+ unsigned state = NUD_STALE;
+ if (r->arp_flags & ATF_PERM)
+ state = NUD_PERMANENT;
+ err = neigh_update(neigh, (r->arp_flags&ATF_COM) ?
+ r->arp_ha.sa_data : NULL, state, 1, 0);
+ neigh_release(neigh);
+ }
+ end_bh_atomic();
+ return err;
+}
+
+static unsigned arp_state_to_flags(struct neighbour *neigh)
+{
+ unsigned flags = 0;
+ if (neigh->nud_state&NUD_PERMANENT)
+ flags = ATF_PERM|ATF_COM;
+ else if (neigh->nud_state&NUD_VALID)
+ flags = ATF_COM;
+ return flags;
+}
+
+/*
+ * Get an ARP cache entry.
+ */
+
+static int arp_req_get(struct arpreq *r, struct device *dev)
+{
+ u32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr;
+ struct neighbour *neigh;
+ int err = -ENXIO;
+
+ start_bh_atomic();
+ neigh = __neigh_lookup(&arp_tbl, &ip, dev, 0);
+ if (neigh) {
+ memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
+ r->arp_ha.sa_family = dev->type;
+ strncpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
+ r->arp_flags = arp_state_to_flags(neigh);
+ neigh_release(neigh);
+ err = 0;
+ }
+ end_bh_atomic();
+ return err;
+}
+
+int arp_req_delete(struct arpreq *r, struct device * dev)
+{
+ int err;
+ u32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
+ struct neighbour *neigh;
+
+ if (r->arp_flags & ATF_PUBL) {
+ u32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr;
+ if (mask == 0xFFFFFFFF)
+ return pneigh_delete(&arp_tbl, &ip, dev);
+ if (mask == 0) {
+ if (dev == NULL) {
+ ipv4_devconf.proxy_arp = 0;
+ return 0;
+ }
+ if (dev->ip_ptr) {
+ ((struct in_device*)dev->ip_ptr)->cnf.proxy_arp = 0;
+ return 0;
+ }
+ return -ENXIO;
+ }
+ return -EINVAL;
+ }
+
+ if (dev == NULL) {
+ struct rtable * rt;
+ if ((err = ip_route_output(&rt, ip, 0, RTO_ONLINK, 0)) != 0)
+ return err;
+ dev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ if (!dev)
+ return -EINVAL;
+ }
+ err = -ENXIO;
+ start_bh_atomic();
+ neigh = __neigh_lookup(&arp_tbl, &ip, dev, 0);
+ if (neigh) {
+ if (neigh->nud_state&~NUD_NOARP)
+ err = neigh_update(neigh, NULL, NUD_FAILED, 1, 0);
+ neigh_release(neigh);
+ }
+ end_bh_atomic();
+ return err;
+}
+
+/*
+ * Handle an ARP layer I/O control request.
+ */
+
+int arp_ioctl(unsigned int cmd, void *arg)
+{
+ int err;
+ struct arpreq r;
+ struct device * dev = NULL;
+
+ switch(cmd) {
+ case SIOCDARP:
+ case SIOCSARP:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ case SIOCGARP:
+ err = copy_from_user(&r, arg, sizeof(struct arpreq));
+ if (err)
+ return -EFAULT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (r.arp_pa.sa_family != AF_INET)
+ return -EPFNOSUPPORT;
+
+ if (!(r.arp_flags & ATF_PUBL) &&
+ (r.arp_flags & (ATF_NETMASK|ATF_DONTPUB)))
+ return -EINVAL;
+ if (!(r.arp_flags & ATF_NETMASK))
+ ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr=__constant_htonl(0xFFFFFFFFUL);
+
+ rtnl_lock();
+ if (r.arp_dev[0]) {
+ err = -ENODEV;
+ if ((dev = dev_get(r.arp_dev)) == NULL)
+ goto out;
+
+ /* Mmmm... It is wrong... ARPHRD_NETROM==0 */
+ if (!r.arp_ha.sa_family)
+ r.arp_ha.sa_family = dev->type;
+ err = -EINVAL;
+ if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type)
+ goto out;
+ } else if (cmd == SIOCGARP) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ switch(cmd) {
+ case SIOCDARP:
+ err = arp_req_delete(&r, dev);
+ break;
+ case SIOCSARP:
+ err = arp_req_set(&r, dev);
+ break;
+ case SIOCGARP:
+ err = arp_req_get(&r, dev);
+ if (!err && copy_to_user(arg, &r, sizeof(r)))
+ err = -EFAULT;
+ break;
+ }
+out:
+ rtnl_unlock();
+ return err;
+}
+
+/*
+ * Write the contents of the ARP cache to a PROCfs file.
+ */
+#ifdef CONFIG_PROC_FS
+
+#define HBUFFERLEN 30
+
+int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len=0;
+ off_t pos=0;
+ int size;
+ char hbuffer[HBUFFERLEN];
+ int i,j,k;
+ const char hexbuf[] = "0123456789ABCDEF";
+
+ size = sprintf(buffer,"IP address HW type Flags HW address Mask Device\n");
+
+ pos+=size;
+ len+=size;
+
+ neigh_table_lock(&arp_tbl);
+
+ for(i=0; i<=NEIGH_HASHMASK; i++) {
+ struct neighbour *n;
+ for (n=arp_tbl.hash_buckets[i]; n; n=n->next) {
+ struct device *dev = n->dev;
+ int hatype = dev->type;
+
+ /* Do not confuse users "arp -a" with magic entries */
+ if (!(n->nud_state&~NUD_NOARP))
+ continue;
+
+ /* I'd get great pleasure deleting
+ this ugly code. Let's output it in hexadecimal format.
+ "arp" utility will eventually repaired --ANK
+ */
+#if 1 /* UGLY CODE */
+/*
+ * Convert hardware address to XX:XX:XX:XX ... form.
+ */
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
+ strcpy(hbuffer,ax2asc((ax25_address *)n->ha));
+ else {
+#endif
+ for (k=0,j=0;k<HBUFFERLEN-3 && j<dev->addr_len;j++) {
+ hbuffer[k++]=hexbuf[(n->ha[j]>>4)&15 ];
+ hbuffer[k++]=hexbuf[n->ha[j]&15 ];
+ hbuffer[k++]=':';
+ }
+ hbuffer[--k]=0;
+
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ }
+#endif
+#else
+ if ((neigh->nud_state&NUD_VALID) && dev->addr_len) {
+ int j;
+ for (j=0; j < dev->addr_len; j++)
+ sprintf(hbuffer+2*j, "%02x", neigh->ha[j]);
+ } else
+ sprintf(hbuffer, "0");
+#endif
+
+ size = sprintf(buffer+len,
+ "%-17s0x%-10x0x%-10x%s",
+ in_ntoa(*(u32*)n->primary_key),
+ hatype,
+ arp_state_to_flags(n),
+ hbuffer);
+ size += sprintf(buffer+len+size,
+ " %-17s %s\n",
+ "*", dev->name);
+
+ len += size;
+ pos += size;
+
+ if (pos <= offset)
+ len=0;
+ if (pos >= offset+length)
+ goto done;
+ }
+ }
+
+ for (i=0; i<=PNEIGH_HASHMASK; i++) {
+ struct pneigh_entry *n;
+ for (n=arp_tbl.phash_buckets[i]; n; n=n->next) {
+ struct device *dev = n->dev;
+ int hatype = dev ? dev->type : 0;
+
+ size = sprintf(buffer+len,
+ "%-17s0x%-10x0x%-10x%s",
+ in_ntoa(*(u32*)n->key),
+ hatype,
+ ATF_PUBL|ATF_PERM,
+ "00:00:00:00:00:00");
+ size += sprintf(buffer+len+size,
+ " %-17s %s\n",
+ "*", dev ? dev->name : "*");
+
+ len += size;
+ pos += size;
+
+ if (pos <= offset)
+ len=0;
+ if (pos >= offset+length)
+ goto done;
+ }
+ }
+
+done:
+ neigh_table_unlock(&arp_tbl);
+
+ *start = buffer+len-(pos-offset); /* Start of wanted data */
+ len = pos-offset; /* Start slop */
+ if (len>length)
+ len = length; /* Ending slop */
+ if (len<0)
+ len = 0;
+ return len;
+}
+#endif
+
+/* Note, that it is not on notifier chain.
+ It is necessary, that this routine was called after route cache will be
+ flushed.
+ */
+void arp_ifdown(struct device *dev)
+{
+ neigh_ifdown(&arp_tbl, dev);
+}
+
+
+/*
+ * Called once on startup.
+ */
+
+static struct packet_type arp_packet_type =
+{
+ __constant_htons(ETH_P_ARP),
+ NULL, /* All devices */
+ arp_rcv,
+ NULL,
+ NULL
+};
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_arp = {
+ PROC_NET_ARP, 3, "arp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ arp_get_info
+};
+#endif
+
+__initfunc(void arp_init (void))
+{
+ neigh_table_init(&arp_tbl);
+
+ dev_add_pack(&arp_packet_type);
+
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&proc_net_arp);
+#endif
+#ifdef CONFIG_SYSCTL
+ neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
+#endif
+}
+
+
+#ifdef CONFIG_AX25_MODULE
+
+/*
+ * ax25 -> ASCII conversion
+ */
+char *ax2asc(ax25_address *a)
+{
+ static char buf[11];
+ char c, *s;
+ int n;
+
+ for (n = 0, s = buf; n < 6; n++) {
+ c = (a->ax25_call[n] >> 1) & 0x7F;
+
+ if (c != ' ') *s++ = c;
+ }
+
+ *s++ = '-';
+
+ if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
+ *s++ = '1';
+ n -= 10;
+ }
+
+ *s++ = n + '0';
+ *s++ = '\0';
+
+ if (*buf == '\0' || *buf == '-')
+ return "*";
+
+ return buf;
+
+}
+
+#endif
diff --git a/pfinet/linux-src/net/ipv4/devinet.c b/pfinet/linux-src/net/ipv4/devinet.c
new file mode 100644
index 00000000..a50ee3bd
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/devinet.c
@@ -0,0 +1,1034 @@
+/*
+ * NET3 IP device support routines.
+ *
+ * Version: $Id: devinet.c,v 1.28.2.2 1999/08/07 10:56:18 davem Exp $
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Derived from the IP parts of dev.c 1.0.19
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ *
+ * Additional Authors:
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes:
+ * Alexey Kuznetsov: pa_* fields are replaced with ifaddr lists.
+ * Cyrus Durgin: updated for kmod
+ */
+
+#include <linux/config.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+#endif
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/ip_fib.h>
+
+struct ipv4_devconf ipv4_devconf = { 1, 1, 1, 1, 0, };
+static struct ipv4_devconf ipv4_devconf_dflt = { 1, 1, 1, 1, 1, };
+
+#ifdef CONFIG_RTNETLINK
+static void rtmsg_ifa(int event, struct in_ifaddr *);
+#else
+#define rtmsg_ifa(a,b) do { } while(0)
+#endif
+
+static struct notifier_block *inetaddr_chain;
+static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy);
+#ifdef CONFIG_SYSCTL
+static void devinet_sysctl_register(struct in_device *in_dev, struct ipv4_devconf *p);
+static void devinet_sysctl_unregister(struct ipv4_devconf *p);
+#endif
+
+int inet_ifa_count;
+int inet_dev_count;
+
+static struct in_ifaddr * inet_alloc_ifa(void)
+{
+ struct in_ifaddr *ifa;
+
+ ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
+ if (ifa) {
+ memset(ifa, 0, sizeof(*ifa));
+ inet_ifa_count++;
+ }
+
+ return ifa;
+}
+
+static __inline__ void inet_free_ifa(struct in_ifaddr *ifa)
+{
+ kfree_s(ifa, sizeof(*ifa));
+ inet_ifa_count--;
+}
+
+struct in_device *inetdev_init(struct device *dev)
+{
+ struct in_device *in_dev;
+
+ if (dev->mtu < 68)
+ return NULL;
+
+ in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL);
+ if (!in_dev)
+ return NULL;
+ inet_dev_count++;
+ memset(in_dev, 0, sizeof(*in_dev));
+ memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
+ in_dev->cnf.sysctl = NULL;
+ in_dev->dev = dev;
+ if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL) {
+ kfree(in_dev);
+ return NULL;
+ }
+#ifdef CONFIG_SYSCTL
+ neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
+#endif
+ dev->ip_ptr = in_dev;
+#ifdef CONFIG_SYSCTL
+ devinet_sysctl_register(in_dev, &in_dev->cnf);
+#endif
+ if (dev->flags&IFF_UP)
+ ip_mc_up(in_dev);
+ return in_dev;
+}
+
+static void inetdev_destroy(struct in_device *in_dev)
+{
+ struct in_ifaddr *ifa;
+
+ ip_mc_destroy_dev(in_dev);
+
+ while ((ifa = in_dev->ifa_list) != NULL) {
+ inet_del_ifa(in_dev, &in_dev->ifa_list, 0);
+ inet_free_ifa(ifa);
+ }
+
+#ifdef CONFIG_SYSCTL
+ devinet_sysctl_unregister(&in_dev->cnf);
+#endif
+ in_dev->dev->ip_ptr = NULL;
+ synchronize_bh();
+ neigh_parms_release(&arp_tbl, in_dev->arp_parms);
+ kfree(in_dev);
+}
+
+struct in_ifaddr * inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
+{
+ for_primary_ifa(in_dev) {
+ if (inet_ifa_match(a, ifa)) {
+ if (!b || inet_ifa_match(b, ifa))
+ return ifa;
+ }
+ } endfor_ifa(in_dev);
+ return NULL;
+}
+
+static void
+inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy)
+{
+ struct in_ifaddr *ifa1 = *ifap;
+
+ /* 1. Deleting primary ifaddr forces deletion all secondaries */
+
+ if (!(ifa1->ifa_flags&IFA_F_SECONDARY)) {
+ struct in_ifaddr *ifa;
+ struct in_ifaddr **ifap1 = &ifa1->ifa_next;
+
+ while ((ifa=*ifap1) != NULL) {
+ if (!(ifa->ifa_flags&IFA_F_SECONDARY) ||
+ ifa1->ifa_mask != ifa->ifa_mask ||
+ !inet_ifa_match(ifa1->ifa_address, ifa)) {
+ ifap1 = &ifa->ifa_next;
+ continue;
+ }
+ *ifap1 = ifa->ifa_next;
+ synchronize_bh();
+
+ rtmsg_ifa(RTM_DELADDR, ifa);
+ notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
+ inet_free_ifa(ifa);
+ }
+ }
+
+ /* 2. Unlink it */
+
+ *ifap = ifa1->ifa_next;
+ synchronize_bh();
+
+ /* 3. Announce address deletion */
+
+ /* Send message first, then call notifier.
+ At first sight, FIB update triggered by notifier
+ will refer to already deleted ifaddr, that could confuse
+ netlink listeners. It is not true: look, gated sees
+ that route deleted and if it still thinks that ifaddr
+ is valid, it will try to restore deleted routes... Grr.
+ So that, this order is correct.
+ */
+ rtmsg_ifa(RTM_DELADDR, ifa1);
+ notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
+ if (destroy) {
+ inet_free_ifa(ifa1);
+ if (in_dev->ifa_list == NULL)
+ inetdev_destroy(in_dev);
+ }
+}
+
+static int
+inet_insert_ifa(struct in_device *in_dev, struct in_ifaddr *ifa)
+{
+ struct in_ifaddr *ifa1, **ifap, **last_primary;
+
+ if (ifa->ifa_local == 0) {
+ inet_free_ifa(ifa);
+ return 0;
+ }
+
+ ifa->ifa_flags &= ~IFA_F_SECONDARY;
+ last_primary = &in_dev->ifa_list;
+
+ for (ifap=&in_dev->ifa_list; (ifa1=*ifap)!=NULL; ifap=&ifa1->ifa_next) {
+ if (!(ifa1->ifa_flags&IFA_F_SECONDARY) && ifa->ifa_scope <= ifa1->ifa_scope)
+ last_primary = &ifa1->ifa_next;
+ if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa)) {
+ if (ifa1->ifa_local == ifa->ifa_local) {
+ inet_free_ifa(ifa);
+ return -EEXIST;
+ }
+ if (ifa1->ifa_scope != ifa->ifa_scope) {
+ inet_free_ifa(ifa);
+ return -EINVAL;
+ }
+ ifa->ifa_flags |= IFA_F_SECONDARY;
+ }
+ }
+
+ if (!(ifa->ifa_flags&IFA_F_SECONDARY)) {
+ net_srandom(ifa->ifa_local);
+ ifap = last_primary;
+ }
+
+ ifa->ifa_next = *ifap;
+ wmb();
+ *ifap = ifa;
+
+ /* Send message first, then call notifier.
+ Notifier will trigger FIB update, so that
+ listeners of netlink will know about new ifaddr */
+ rtmsg_ifa(RTM_NEWADDR, ifa);
+ notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
+
+ return 0;
+}
+
+static int
+inet_set_ifa(struct device *dev, struct in_ifaddr *ifa)
+{
+ struct in_device *in_dev = dev->ip_ptr;
+
+ if (in_dev == NULL) {
+ in_dev = inetdev_init(dev);
+ if (in_dev == NULL) {
+ inet_free_ifa(ifa);
+ return -ENOBUFS;
+ }
+ }
+ ifa->ifa_dev = in_dev;
+ if (LOOPBACK(ifa->ifa_local))
+ ifa->ifa_scope = RT_SCOPE_HOST;
+ return inet_insert_ifa(in_dev, ifa);
+}
+
+struct in_device *inetdev_by_index(int ifindex)
+{
+ struct device *dev;
+ dev = dev_get_by_index(ifindex);
+ if (dev)
+ return dev->ip_ptr;
+ return NULL;
+}
+
+struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask)
+{
+ for_primary_ifa(in_dev) {
+ if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa))
+ return ifa;
+ } endfor_ifa(in_dev);
+ return NULL;
+}
+
+#ifdef CONFIG_RTNETLINK
+
+/* rtm_{add|del} functions are not reenterable, so that
+ this structure can be made static
+ */
+
+int
+inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct rtattr **rta = arg;
+ struct in_device *in_dev;
+ struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+ struct in_ifaddr *ifa, **ifap;
+
+ if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL)
+ return -EADDRNOTAVAIL;
+
+ for (ifap=&in_dev->ifa_list; (ifa=*ifap)!=NULL; ifap=&ifa->ifa_next) {
+ if ((rta[IFA_LOCAL-1] && memcmp(RTA_DATA(rta[IFA_LOCAL-1]), &ifa->ifa_local, 4)) ||
+ (rta[IFA_LABEL-1] && strcmp(RTA_DATA(rta[IFA_LABEL-1]), ifa->ifa_label)) ||
+ (rta[IFA_ADDRESS-1] &&
+ (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
+ !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS-1]), ifa))))
+ continue;
+ inet_del_ifa(in_dev, ifap, 1);
+ return 0;
+ }
+
+ return -EADDRNOTAVAIL;
+}
+
+int
+inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct rtattr **rta = arg;
+ struct device *dev;
+ struct in_device *in_dev;
+ struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+ struct in_ifaddr *ifa;
+
+ if (ifm->ifa_prefixlen > 32 || rta[IFA_LOCAL-1] == NULL)
+ return -EINVAL;
+
+ if ((dev = dev_get_by_index(ifm->ifa_index)) == NULL)
+ return -ENODEV;
+
+ if ((in_dev = dev->ip_ptr) == NULL) {
+ in_dev = inetdev_init(dev);
+ if (!in_dev)
+ return -ENOBUFS;
+ }
+
+ if ((ifa = inet_alloc_ifa()) == NULL)
+ return -ENOBUFS;
+
+ if (rta[IFA_ADDRESS-1] == NULL)
+ rta[IFA_ADDRESS-1] = rta[IFA_LOCAL-1];
+ memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 4);
+ memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 4);
+ ifa->ifa_prefixlen = ifm->ifa_prefixlen;
+ ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);
+ if (rta[IFA_BROADCAST-1])
+ memcpy(&ifa->ifa_broadcast, RTA_DATA(rta[IFA_BROADCAST-1]), 4);
+ if (rta[IFA_ANYCAST-1])
+ memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST-1]), 4);
+ ifa->ifa_flags = ifm->ifa_flags;
+ ifa->ifa_scope = ifm->ifa_scope;
+ ifa->ifa_dev = in_dev;
+ if (rta[IFA_LABEL-1])
+ memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL-1]), IFNAMSIZ);
+ else
+ memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
+
+ return inet_insert_ifa(in_dev, ifa);
+}
+
+#endif
+
+/*
+ * Determine a default network mask, based on the IP address.
+ */
+
+static __inline__ int inet_abc_len(u32 addr)
+{
+ if (ZERONET(addr))
+ return 0;
+
+ addr = ntohl(addr);
+ if (IN_CLASSA(addr))
+ return 8;
+ if (IN_CLASSB(addr))
+ return 16;
+ if (IN_CLASSC(addr))
+ return 24;
+
+ /*
+ * Something else, probably a multicast.
+ */
+
+ return -1;
+}
+
+
+int devinet_ioctl(unsigned int cmd, void *arg)
+{
+ struct ifreq ifr;
+ struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
+ struct in_device *in_dev;
+ struct in_ifaddr **ifap = NULL;
+ struct in_ifaddr *ifa = NULL;
+ struct device *dev;
+#ifdef CONFIG_IP_ALIAS
+ char *colon;
+#endif
+ int exclusive = 0;
+ int ret = 0;
+
+ /*
+ * Fetch the caller's info block into kernel space
+ */
+
+ if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
+ return -EFAULT;
+ ifr.ifr_name[IFNAMSIZ-1] = 0;
+
+#ifdef CONFIG_IP_ALIAS
+ colon = strchr(ifr.ifr_name, ':');
+ if (colon)
+ *colon = 0;
+#endif
+
+#ifdef CONFIG_KMOD
+ dev_load(ifr.ifr_name);
+#endif
+
+ switch(cmd) {
+ case SIOCGIFADDR: /* Get interface address */
+ case SIOCGIFBRDADDR: /* Get the broadcast address */
+ case SIOCGIFDSTADDR: /* Get the destination address */
+ case SIOCGIFNETMASK: /* Get the netmask for the interface */
+ /* Note that this ioctls will not sleep,
+ so that we do not impose a lock.
+ One day we will be forced to put shlock here (I mean SMP)
+ */
+ memset(sin, 0, sizeof(*sin));
+ sin->sin_family = AF_INET;
+ break;
+
+ case SIOCSIFFLAGS:
+ if (!capable(CAP_NET_ADMIN))
+ return -EACCES;
+ rtnl_lock();
+ exclusive = 1;
+ break;
+ case SIOCSIFADDR: /* Set interface address (and family) */
+ case SIOCSIFBRDADDR: /* Set the broadcast address */
+ case SIOCSIFDSTADDR: /* Set the destination address */
+ case SIOCSIFNETMASK: /* Set the netmask for the interface */
+ if (!capable(CAP_NET_ADMIN))
+ return -EACCES;
+ if (sin->sin_family != AF_INET)
+ return -EINVAL;
+ rtnl_lock();
+ exclusive = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+
+ if ((dev = dev_get(ifr.ifr_name)) == NULL) {
+ ret = -ENODEV;
+ goto done;
+ }
+
+#ifdef CONFIG_IP_ALIAS
+ if (colon)
+ *colon = ':';
+#endif
+
+ if ((in_dev=dev->ip_ptr) != NULL) {
+ for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
+ if (strcmp(ifr.ifr_name, ifa->ifa_label) == 0)
+ break;
+ }
+
+ if (ifa == NULL && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) {
+ ret = -EADDRNOTAVAIL;
+ goto done;
+ }
+
+ switch(cmd) {
+ case SIOCGIFADDR: /* Get interface address */
+ sin->sin_addr.s_addr = ifa->ifa_local;
+ goto rarok;
+
+ case SIOCGIFBRDADDR: /* Get the broadcast address */
+ sin->sin_addr.s_addr = ifa->ifa_broadcast;
+ goto rarok;
+
+ case SIOCGIFDSTADDR: /* Get the destination address */
+ sin->sin_addr.s_addr = ifa->ifa_address;
+ goto rarok;
+
+ case SIOCGIFNETMASK: /* Get the netmask for the interface */
+ sin->sin_addr.s_addr = ifa->ifa_mask;
+ goto rarok;
+
+ case SIOCSIFFLAGS:
+#ifdef CONFIG_IP_ALIAS
+ if (colon) {
+ if (ifa == NULL) {
+ ret = -EADDRNOTAVAIL;
+ break;
+ }
+ if (!(ifr.ifr_flags&IFF_UP))
+ inet_del_ifa(in_dev, ifap, 1);
+ break;
+ }
+#endif
+ ret = dev_change_flags(dev, ifr.ifr_flags);
+ break;
+
+ case SIOCSIFADDR: /* Set interface address (and family) */
+ if (inet_abc_len(sin->sin_addr.s_addr) < 0) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!ifa) {
+ if ((ifa = inet_alloc_ifa()) == NULL) {
+ ret = -ENOBUFS;
+ break;
+ }
+#ifdef CONFIG_IP_ALIAS
+ if (colon)
+ memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
+ else
+#endif
+ memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
+ } else {
+ ret = 0;
+ if (ifa->ifa_local == sin->sin_addr.s_addr)
+ break;
+ inet_del_ifa(in_dev, ifap, 0);
+ ifa->ifa_broadcast = 0;
+ ifa->ifa_anycast = 0;
+ }
+
+ ifa->ifa_address =
+ ifa->ifa_local = sin->sin_addr.s_addr;
+
+ if (!(dev->flags&IFF_POINTOPOINT)) {
+ ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address);
+ ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen);
+ if ((dev->flags&IFF_BROADCAST) && ifa->ifa_prefixlen < 31)
+ ifa->ifa_broadcast = ifa->ifa_address|~ifa->ifa_mask;
+ } else {
+ ifa->ifa_prefixlen = 32;
+ ifa->ifa_mask = inet_make_mask(32);
+ }
+ ret = inet_set_ifa(dev, ifa);
+ break;
+
+ case SIOCSIFBRDADDR: /* Set the broadcast address */
+ if (ifa->ifa_broadcast != sin->sin_addr.s_addr) {
+ inet_del_ifa(in_dev, ifap, 0);
+ ifa->ifa_broadcast = sin->sin_addr.s_addr;
+ inet_insert_ifa(in_dev, ifa);
+ }
+ break;
+
+ case SIOCSIFDSTADDR: /* Set the destination address */
+ if (ifa->ifa_address != sin->sin_addr.s_addr) {
+ if (inet_abc_len(sin->sin_addr.s_addr) < 0) {
+ ret = -EINVAL;
+ break;
+ }
+ inet_del_ifa(in_dev, ifap, 0);
+ ifa->ifa_address = sin->sin_addr.s_addr;
+ inet_insert_ifa(in_dev, ifa);
+ }
+ break;
+
+ case SIOCSIFNETMASK: /* Set the netmask for the interface */
+
+ /*
+ * The mask we set must be legal.
+ */
+ if (bad_mask(sin->sin_addr.s_addr, 0)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ifa->ifa_mask != sin->sin_addr.s_addr) {
+ inet_del_ifa(in_dev, ifap, 0);
+ ifa->ifa_mask = sin->sin_addr.s_addr;
+ ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
+ inet_set_ifa(dev, ifa);
+ }
+ break;
+ }
+done:
+ if (exclusive)
+ rtnl_unlock();
+ return ret;
+
+rarok:
+ if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ return 0;
+}
+
+static int
+inet_gifconf(struct device *dev, char *buf, int len)
+{
+ struct in_device *in_dev = dev->ip_ptr;
+ struct in_ifaddr *ifa;
+ struct ifreq ifr;
+ int done=0;
+
+ if (in_dev==NULL || (ifa=in_dev->ifa_list)==NULL)
+ return 0;
+
+ for ( ; ifa; ifa = ifa->ifa_next) {
+ if (!buf) {
+ done += sizeof(ifr);
+ continue;
+ }
+ if (len < (int) sizeof(ifr))
+ return done;
+ memset(&ifr, 0, sizeof(struct ifreq));
+ if (ifa->ifa_label)
+ strcpy(ifr.ifr_name, ifa->ifa_label);
+ else
+ strcpy(ifr.ifr_name, dev->name);
+
+ (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET;
+ (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local;
+
+ if (copy_to_user(buf, &ifr, sizeof(struct ifreq)))
+ return -EFAULT;
+ buf += sizeof(struct ifreq);
+ len -= sizeof(struct ifreq);
+ done += sizeof(struct ifreq);
+ }
+ return done;
+}
+
+u32 inet_select_addr(struct device *dev, u32 dst, int scope)
+{
+ u32 addr = 0;
+ struct in_device *in_dev = dev->ip_ptr;
+
+ if (in_dev == NULL)
+ return 0;
+
+ for_primary_ifa(in_dev) {
+ if (ifa->ifa_scope > scope)
+ continue;
+ if (!dst || inet_ifa_match(dst, ifa))
+ return ifa->ifa_local;
+ if (!addr)
+ addr = ifa->ifa_local;
+ } endfor_ifa(in_dev);
+
+ if (addr || scope >= RT_SCOPE_LINK)
+ return addr;
+
+ /* Not loopback addresses on loopback should be preferred
+ in this case. It is importnat that lo is the first interface
+ in dev_base list.
+ */
+ for (dev=dev_base; dev; dev=dev->next) {
+ if ((in_dev=dev->ip_ptr) == NULL)
+ continue;
+
+ for_primary_ifa(in_dev) {
+ if (ifa->ifa_scope <= scope)
+ return ifa->ifa_local;
+ } endfor_ifa(in_dev);
+ }
+
+ return 0;
+}
+
+/*
+ * Device notifier
+ */
+
+int register_inetaddr_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_register(&inetaddr_chain, nb);
+}
+
+int unregister_inetaddr_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_unregister(&inetaddr_chain,nb);
+}
+
+static int inetdev_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct device *dev = ptr;
+ struct in_device *in_dev = dev->ip_ptr;
+
+ if (in_dev == NULL)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ if (in_dev)
+ printk(KERN_DEBUG "inetdev_event: bug\n");
+ dev->ip_ptr = NULL;
+ break;
+ case NETDEV_UP:
+ if (dev == &loopback_dev) {
+ struct in_ifaddr *ifa;
+ if ((ifa = inet_alloc_ifa()) != NULL) {
+ ifa->ifa_local =
+ ifa->ifa_address = htonl(INADDR_LOOPBACK);
+ ifa->ifa_prefixlen = 8;
+ ifa->ifa_mask = inet_make_mask(8);
+ ifa->ifa_dev = in_dev;
+ ifa->ifa_scope = RT_SCOPE_HOST;
+ memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
+ inet_insert_ifa(in_dev, ifa);
+ }
+ }
+ ip_mc_up(in_dev);
+ break;
+ case NETDEV_DOWN:
+ ip_mc_down(in_dev);
+ break;
+ case NETDEV_CHANGEMTU:
+ if (dev->mtu >= 68)
+ break;
+ /* MTU falled under minimal IP mtu. Disable IP. */
+ case NETDEV_UNREGISTER:
+ inetdev_destroy(in_dev);
+ break;
+ case NETDEV_CHANGENAME:
+ if (in_dev->ifa_list) {
+ struct in_ifaddr *ifa;
+ for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next)
+ memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
+ /* Do not notify about label change, this event is
+ not interesting to applications using netlink.
+ */
+ }
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+struct notifier_block ip_netdev_notifier={
+ inetdev_event,
+ NULL,
+ 0
+};
+
+#ifdef CONFIG_RTNETLINK
+
+static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
+ u32 pid, u32 seq, int event)
+{
+ struct ifaddrmsg *ifm;
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
+ ifm = NLMSG_DATA(nlh);
+ ifm->ifa_family = AF_INET;
+ ifm->ifa_prefixlen = ifa->ifa_prefixlen;
+ ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT;
+ ifm->ifa_scope = ifa->ifa_scope;
+ ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
+ if (ifa->ifa_address)
+ RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address);
+ if (ifa->ifa_local)
+ RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local);
+ if (ifa->ifa_broadcast)
+ RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast);
+ if (ifa->ifa_anycast)
+ RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast);
+ if (ifa->ifa_label[0])
+ RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx, ip_idx;
+ int s_idx, s_ip_idx;
+ struct device *dev;
+ struct in_device *in_dev;
+ struct in_ifaddr *ifa;
+
+ s_idx = cb->args[0];
+ s_ip_idx = ip_idx = cb->args[1];
+ for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+ if (idx < s_idx)
+ continue;
+ if (idx > s_idx)
+ s_ip_idx = 0;
+ if ((in_dev = dev->ip_ptr) == NULL)
+ continue;
+ for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
+ ifa = ifa->ifa_next, ip_idx++) {
+ if (ip_idx < s_ip_idx)
+ continue;
+ if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0)
+ goto done;
+ }
+ }
+done:
+ cb->args[0] = idx;
+ cb->args[1] = ip_idx;
+
+ return skb->len;
+}
+
+static void rtmsg_ifa(int event, struct in_ifaddr * ifa)
+{
+ struct sk_buff *skb;
+ int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
+
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb) {
+ netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS);
+ return;
+ }
+ if (inet_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
+ kfree_skb(skb);
+ netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL);
+ return;
+ }
+ NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_IFADDR;
+ netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV4_IFADDR, GFP_KERNEL);
+}
+
+
+static struct rtnetlink_link inet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
+{
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+
+ { inet_rtm_newaddr, NULL, },
+ { inet_rtm_deladdr, NULL, },
+ { NULL, inet_dump_ifaddr, },
+ { NULL, NULL, },
+
+ { inet_rtm_newroute, NULL, },
+ { inet_rtm_delroute, NULL, },
+ { inet_rtm_getroute, inet_dump_fib, },
+ { NULL, NULL, },
+
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ { inet_rtm_newrule, NULL, },
+ { inet_rtm_delrule, NULL, },
+ { NULL, inet_dump_rules, },
+ { NULL, NULL, },
+#else
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+#endif
+};
+
+#endif /* CONFIG_RTNETLINK */
+
+
+#ifdef CONFIG_SYSCTL
+
+void inet_forward_change()
+{
+ struct device *dev;
+ int on = ipv4_devconf.forwarding;
+
+ ipv4_devconf.accept_redirects = !on;
+ ipv4_devconf_dflt.forwarding = on;
+
+ for (dev = dev_base; dev; dev = dev->next) {
+ struct in_device *in_dev = dev->ip_ptr;
+ if (in_dev)
+ in_dev->cnf.forwarding = on;
+ }
+
+ rt_cache_flush(0);
+
+ ip_statistics.IpForwarding = on ? 1 : 2;
+}
+
+static
+int devinet_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
+ void *buffer, size_t *lenp)
+{
+ int *valp = ctl->data;
+ int val = *valp;
+ int ret;
+
+ ret = proc_dointvec(ctl, write, filp, buffer, lenp);
+
+ if (write && *valp != val) {
+ if (valp == &ipv4_devconf.forwarding)
+ inet_forward_change();
+ else if (valp != &ipv4_devconf_dflt.forwarding)
+ rt_cache_flush(0);
+ }
+
+ return ret;
+}
+
+static struct devinet_sysctl_table
+{
+ struct ctl_table_header *sysctl_header;
+ ctl_table devinet_vars[12];
+ ctl_table devinet_dev[2];
+ ctl_table devinet_conf_dir[2];
+ ctl_table devinet_proto_dir[2];
+ ctl_table devinet_root_dir[2];
+} devinet_sysctl = {
+ NULL,
+ {{NET_IPV4_CONF_FORWARDING, "forwarding",
+ &ipv4_devconf.forwarding, sizeof(int), 0644, NULL,
+ &devinet_sysctl_forward},
+ {NET_IPV4_CONF_MC_FORWARDING, "mc_forwarding",
+ &ipv4_devconf.mc_forwarding, sizeof(int), 0444, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_ACCEPT_REDIRECTS, "accept_redirects",
+ &ipv4_devconf.accept_redirects, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_SECURE_REDIRECTS, "secure_redirects",
+ &ipv4_devconf.secure_redirects, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_SHARED_MEDIA, "shared_media",
+ &ipv4_devconf.shared_media, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_RP_FILTER, "rp_filter",
+ &ipv4_devconf.rp_filter, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_SEND_REDIRECTS, "send_redirects",
+ &ipv4_devconf.send_redirects, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE, "accept_source_route",
+ &ipv4_devconf.accept_source_route, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_PROXY_ARP, "proxy_arp",
+ &ipv4_devconf.proxy_arp, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_BOOTP_RELAY, "bootp_relay",
+ &ipv4_devconf.bootp_relay, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_CONF_LOG_MARTIANS, "log_martians",
+ &ipv4_devconf.log_martians, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {0}},
+
+ {{NET_PROTO_CONF_ALL, "all", NULL, 0, 0555, devinet_sysctl.devinet_vars},{0}},
+ {{NET_IPV4_CONF, "conf", NULL, 0, 0555, devinet_sysctl.devinet_dev},{0}},
+ {{NET_IPV4, "ipv4", NULL, 0, 0555, devinet_sysctl.devinet_conf_dir},{0}},
+ {{CTL_NET, "net", NULL, 0, 0555, devinet_sysctl.devinet_proto_dir},{0}}
+};
+
+static void devinet_sysctl_register(struct in_device *in_dev, struct ipv4_devconf *p)
+{
+ int i;
+ struct device *dev = in_dev ? in_dev->dev : NULL;
+ struct devinet_sysctl_table *t;
+
+ t = kmalloc(sizeof(*t), GFP_KERNEL);
+ if (t == NULL)
+ return;
+ memcpy(t, &devinet_sysctl, sizeof(*t));
+ for (i=0; i<sizeof(t->devinet_vars)/sizeof(t->devinet_vars[0])-1; i++) {
+ t->devinet_vars[i].data += (char*)p - (char*)&ipv4_devconf;
+ t->devinet_vars[i].de = NULL;
+ }
+ if (dev) {
+ t->devinet_dev[0].procname = dev->name;
+ t->devinet_dev[0].ctl_name = dev->ifindex;
+ } else {
+ t->devinet_dev[0].procname = "default";
+ t->devinet_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
+ }
+ t->devinet_dev[0].child = t->devinet_vars;
+ t->devinet_dev[0].de = NULL;
+ t->devinet_conf_dir[0].child = t->devinet_dev;
+ t->devinet_conf_dir[0].de = NULL;
+ t->devinet_proto_dir[0].child = t->devinet_conf_dir;
+ t->devinet_proto_dir[0].de = NULL;
+ t->devinet_root_dir[0].child = t->devinet_proto_dir;
+ t->devinet_root_dir[0].de = NULL;
+
+ t->sysctl_header = register_sysctl_table(t->devinet_root_dir, 0);
+ if (t->sysctl_header == NULL)
+ kfree(t);
+ else
+ p->sysctl = t;
+}
+
+static void devinet_sysctl_unregister(struct ipv4_devconf *p)
+{
+ if (p->sysctl) {
+ struct devinet_sysctl_table *t = p->sysctl;
+ p->sysctl = NULL;
+ unregister_sysctl_table(t->sysctl_header);
+ kfree(t);
+ }
+}
+#endif
+
+__initfunc(void devinet_init(void))
+{
+ register_gifconf(PF_INET, inet_gifconf);
+ register_netdevice_notifier(&ip_netdev_notifier);
+#ifdef CONFIG_RTNETLINK
+ rtnetlink_links[PF_INET] = inet_rtnetlink_table;
+#endif
+#ifdef CONFIG_SYSCTL
+ devinet_sysctl.sysctl_header =
+ register_sysctl_table(devinet_sysctl.devinet_root_dir, 0);
+ devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
+#endif
+}
diff --git a/pfinet/linux-src/net/ipv4/fib_frontend.c b/pfinet/linux-src/net/ipv4/fib_frontend.c
new file mode 100644
index 00000000..a1747048
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/fib_frontend.c
@@ -0,0 +1,628 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IPv4 Forwarding Information Base: FIB frontend.
+ *
+ * Version: $Id: fib_frontend.c,v 1.15 1999/03/21 05:22:31 davem Exp $
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/init.h>
+
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/arp.h>
+#include <net/ip_fib.h>
+
+#define FFprint(a...) printk(KERN_DEBUG a)
+
+#ifndef CONFIG_IP_MULTIPLE_TABLES
+
+#define RT_TABLE_MIN RT_TABLE_MAIN
+
+struct fib_table *local_table;
+struct fib_table *main_table;
+
+#else
+
+#define RT_TABLE_MIN 1
+
+struct fib_table *fib_tables[RT_TABLE_MAX+1];
+
+struct fib_table *__fib_new_table(int id)
+{
+ struct fib_table *tb;
+
+ tb = fib_hash_init(id);
+ if (!tb)
+ return NULL;
+ fib_tables[id] = tb;
+ return tb;
+}
+
+
+#endif /* CONFIG_IP_MULTIPLE_TABLES */
+
+
+void fib_flush(void)
+{
+ int flushed = 0;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ struct fib_table *tb;
+ int id;
+
+ for (id = RT_TABLE_MAX; id>0; id--) {
+ if ((tb = fib_get_table(id))==NULL)
+ continue;
+ flushed += tb->tb_flush(tb);
+ }
+#else /* CONFIG_IP_MULTIPLE_TABLES */
+ flushed += main_table->tb_flush(main_table);
+ flushed += local_table->tb_flush(local_table);
+#endif /* CONFIG_IP_MULTIPLE_TABLES */
+
+ if (flushed)
+ rt_cache_flush(-1);
+}
+
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Called from the PROCfs module. This outputs /proc/net/route.
+ *
+ * It always works in backward compatibility mode.
+ * The format of the file is not supposed to be changed.
+ */
+
+static int
+fib_get_procinfo(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int first = offset/128;
+ char *ptr = buffer;
+ int count = (length+127)/128;
+ int len;
+
+ *start = buffer + offset%128;
+
+ if (--first < 0) {
+ sprintf(buffer, "%-127s\n", "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT");
+ --count;
+ ptr += 128;
+ first = 0;
+ }
+
+ /* rtnl_shlock(); -- it is pointless at the moment --ANK */
+ if (main_table && count > 0) {
+ int n = main_table->tb_get_info(main_table, ptr, first, count);
+ count -= n;
+ ptr += n*128;
+ }
+ /* rtnl_shunlock(); */
+ len = ptr - *start;
+ if (len >= length)
+ return length;
+ if (len >= 0)
+ return len;
+ return 0;
+}
+
+#endif /* CONFIG_PROC_FS */
+
+/*
+ * Find the first device with a given source address.
+ */
+
+struct device * ip_dev_find(u32 addr)
+{
+ struct rt_key key;
+ struct fib_result res;
+
+ memset(&key, 0, sizeof(key));
+ key.dst = addr;
+
+ if (!local_table || local_table->tb_lookup(local_table, &key, &res)
+ || res.type != RTN_LOCAL)
+ return NULL;
+
+ return FIB_RES_DEV(res);
+}
+
+unsigned inet_addr_type(u32 addr)
+{
+ struct rt_key key;
+ struct fib_result res;
+
+ if (ZERONET(addr) || BADCLASS(addr))
+ return RTN_BROADCAST;
+ if (MULTICAST(addr))
+ return RTN_MULTICAST;
+
+ memset(&key, 0, sizeof(key));
+ key.dst = addr;
+
+ if (local_table) {
+ if (local_table->tb_lookup(local_table, &key, &res) == 0)
+ return res.type;
+ return RTN_UNICAST;
+ }
+ return RTN_BROADCAST;
+}
+
+/* Given (packet source, input interface) and optional (dst, oif, tos):
+ - (main) check, that source is valid i.e. not broadcast or our local
+ address.
+ - figure out what "logical" interface this packet arrived
+ and calculate "specific destination" address.
+ - check, that packet arrived from expected physical interface.
+ */
+
+int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
+ struct device *dev, u32 *spec_dst, u32 *itag)
+{
+ struct in_device *in_dev = dev->ip_ptr;
+ struct rt_key key;
+ struct fib_result res;
+
+ key.dst = src;
+ key.src = dst;
+ key.tos = tos;
+ key.oif = 0;
+ key.iif = oif;
+ key.scope = RT_SCOPE_UNIVERSE;
+
+ if (in_dev == NULL)
+ return -EINVAL;
+ if (fib_lookup(&key, &res))
+ goto last_resort;
+ if (res.type != RTN_UNICAST)
+ return -EINVAL;
+ *spec_dst = FIB_RES_PREFSRC(res);
+ if (itag)
+ fib_combine_itag(itag, &res);
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
+#else
+ if (FIB_RES_DEV(res) == dev)
+#endif
+ return FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+
+ if (in_dev->ifa_list == NULL)
+ goto last_resort;
+ if (IN_DEV_RPFILTER(in_dev))
+ return -EINVAL;
+ key.oif = dev->ifindex;
+ if (fib_lookup(&key, &res) == 0 && res.type == RTN_UNICAST) {
+ *spec_dst = FIB_RES_PREFSRC(res);
+ return FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+ }
+ return 0;
+
+last_resort:
+ if (IN_DEV_RPFILTER(in_dev))
+ return -EINVAL;
+ *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
+ *itag = 0;
+ return 0;
+}
+
+#ifndef CONFIG_IP_NOSIOCRT
+
+/*
+ * Handle IP routing ioctl calls. These are used to manipulate the routing tables
+ */
+
+int ip_rt_ioctl(unsigned int cmd, void *arg)
+{
+ int err;
+ struct kern_rta rta;
+ struct rtentry r;
+ struct {
+ struct nlmsghdr nlh;
+ struct rtmsg rtm;
+ } req;
+
+ switch (cmd) {
+ case SIOCADDRT: /* Add a route */
+ case SIOCDELRT: /* Delete a route */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&r, arg, sizeof(struct rtentry)))
+ return -EFAULT;
+ rtnl_lock();
+ err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r);
+ if (err == 0) {
+ if (cmd == SIOCDELRT) {
+ struct fib_table *tb = fib_get_table(req.rtm.rtm_table);
+ err = -ESRCH;
+ if (tb)
+ err = tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
+ } else {
+ struct fib_table *tb = fib_new_table(req.rtm.rtm_table);
+ err = -ENOBUFS;
+ if (tb)
+ err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
+ }
+ if (rta.rta_mx)
+ kfree(rta.rta_mx);
+ }
+ rtnl_unlock();
+ return err;
+ }
+ return -EINVAL;
+}
+
+#else
+
+int ip_rt_ioctl(unsigned int cmd, void *arg)
+{
+ return -EINVAL;
+}
+
+#endif
+
+#ifdef CONFIG_RTNETLINK
+
+static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
+{
+ int i;
+
+ for (i=1; i<=RTA_MAX; i++) {
+ struct rtattr *attr = rta[i-1];
+ if (attr) {
+ if (RTA_PAYLOAD(attr) < 4)
+ return -EINVAL;
+ if (i != RTA_MULTIPATH && i != RTA_METRICS)
+ rta[i-1] = (struct rtattr*)RTA_DATA(attr);
+ }
+ }
+ return 0;
+}
+
+int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+{
+ struct fib_table * tb;
+ struct rtattr **rta = arg;
+ struct rtmsg *r = NLMSG_DATA(nlh);
+
+ if (inet_check_attr(r, rta))
+ return -EINVAL;
+
+ tb = fib_get_table(r->rtm_table);
+ if (tb)
+ return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
+ return -ESRCH;
+}
+
+int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+{
+ struct fib_table * tb;
+ struct rtattr **rta = arg;
+ struct rtmsg *r = NLMSG_DATA(nlh);
+
+ if (inet_check_attr(r, rta))
+ return -EINVAL;
+
+ tb = fib_new_table(r->rtm_table);
+ if (tb)
+ return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
+ return -ENOBUFS;
+}
+
+int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int t;
+ int s_t;
+ struct fib_table *tb;
+
+ if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
+ ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
+ return ip_rt_dump(skb, cb);
+
+ s_t = cb->args[0];
+ if (s_t == 0)
+ s_t = cb->args[0] = RT_TABLE_MIN;
+
+ for (t=s_t; t<=RT_TABLE_MAX; t++) {
+ if (t < s_t) continue;
+ if (t > s_t)
+ memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
+ if ((tb = fib_get_table(t))==NULL)
+ continue;
+ if (tb->tb_dump(tb, skb, cb) < 0)
+ break;
+ }
+
+ cb->args[0] = t;
+
+ return skb->len;
+}
+
+#endif
+
+/* Prepare and feed intra-kernel routing request.
+ Really, it should be netlink message, but :-( netlink
+ can be not configured, so that we feed it directly
+ to fib engine. It is legal, because all events occur
+ only when netlink is already locked.
+ */
+
+static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa)
+{
+ struct fib_table * tb;
+ struct {
+ struct nlmsghdr nlh;
+ struct rtmsg rtm;
+ } req;
+ struct kern_rta rta;
+
+ memset(&req.rtm, 0, sizeof(req.rtm));
+ memset(&rta, 0, sizeof(rta));
+
+ if (type == RTN_UNICAST)
+ tb = fib_new_table(RT_TABLE_MAIN);
+ else
+ tb = fib_new_table(RT_TABLE_LOCAL);
+
+ if (tb == NULL)
+ return;
+
+ req.nlh.nlmsg_len = sizeof(req);
+ req.nlh.nlmsg_type = cmd;
+ req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
+ req.nlh.nlmsg_pid = 0;
+ req.nlh.nlmsg_seq = 0;
+
+ req.rtm.rtm_dst_len = dst_len;
+ req.rtm.rtm_table = tb->tb_id;
+ req.rtm.rtm_protocol = RTPROT_KERNEL;
+ req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
+ req.rtm.rtm_type = type;
+
+ rta.rta_dst = &dst;
+ rta.rta_prefsrc = &ifa->ifa_local;
+ rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
+
+ if (cmd == RTM_NEWROUTE)
+ tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
+ else
+ tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
+}
+
+static void fib_add_ifaddr(struct in_ifaddr *ifa)
+{
+ struct in_device *in_dev = ifa->ifa_dev;
+ struct device *dev = in_dev->dev;
+ struct in_ifaddr *prim = ifa;
+ u32 mask = ifa->ifa_mask;
+ u32 addr = ifa->ifa_local;
+ u32 prefix = ifa->ifa_address&mask;
+
+ if (ifa->ifa_flags&IFA_F_SECONDARY) {
+ prim = inet_ifa_byprefix(in_dev, prefix, mask);
+ if (prim == NULL) {
+ printk(KERN_DEBUG "fib_add_ifaddr: bug: prim == NULL\n");
+ return;
+ }
+ }
+
+ fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
+
+ if (!(dev->flags&IFF_UP))
+ return;
+
+ /* Add broadcast address, if it is explicitly assigned. */
+ if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF)
+ fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
+
+ if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
+ (prefix != addr || ifa->ifa_prefixlen < 32)) {
+ fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
+ RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim);
+
+ /* Add network specific broadcasts, when it takes a sense */
+ if (ifa->ifa_prefixlen < 31) {
+ fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
+ fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim);
+ }
+ }
+}
+
+static void fib_del_ifaddr(struct in_ifaddr *ifa)
+{
+ struct in_device *in_dev = ifa->ifa_dev;
+ struct device *dev = in_dev->dev;
+ struct in_ifaddr *ifa1;
+ struct in_ifaddr *prim = ifa;
+ u32 brd = ifa->ifa_address|~ifa->ifa_mask;
+ u32 any = ifa->ifa_address&ifa->ifa_mask;
+#define LOCAL_OK 1
+#define BRD_OK 2
+#define BRD0_OK 4
+#define BRD1_OK 8
+ unsigned ok = 0;
+
+ if (!(ifa->ifa_flags&IFA_F_SECONDARY))
+ fib_magic(RTM_DELROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
+ RTN_UNICAST, any, ifa->ifa_prefixlen, prim);
+ else {
+ prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
+ if (prim == NULL) {
+ printk(KERN_DEBUG "fib_del_ifaddr: bug: prim == NULL\n");
+ return;
+ }
+ }
+
+ /* Deletion is more complicated than add.
+ We should take care of not to delete too much :-)
+
+ Scan address list to be sure that addresses are really gone.
+ */
+
+ for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
+ if (ifa->ifa_local == ifa1->ifa_local)
+ ok |= LOCAL_OK;
+ if (ifa->ifa_broadcast == ifa1->ifa_broadcast)
+ ok |= BRD_OK;
+ if (brd == ifa1->ifa_broadcast)
+ ok |= BRD1_OK;
+ if (any == ifa1->ifa_broadcast)
+ ok |= BRD0_OK;
+ }
+
+ if (!(ok&BRD_OK))
+ fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
+ if (!(ok&BRD1_OK))
+ fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim);
+ if (!(ok&BRD0_OK))
+ fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim);
+ if (!(ok&LOCAL_OK)) {
+ fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
+
+ /* Check, that this local address finally disappeared. */
+ if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
+ /* And the last, but not the least thing.
+ We must flush stray FIB entries.
+
+ First of all, we scan fib_info list searching
+ for stray nexthop entries, then ignite fib_flush.
+ */
+ if (fib_sync_down(ifa->ifa_local, NULL, 0))
+ fib_flush();
+ }
+ }
+#undef LOCAL_OK
+#undef BRD_OK
+#undef BRD0_OK
+#undef BRD1_OK
+}
+
+static void fib_disable_ip(struct device *dev, int force)
+{
+ if (fib_sync_down(0, dev, force))
+ fib_flush();
+ rt_cache_flush(0);
+ arp_ifdown(dev);
+}
+
+static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct in_ifaddr *ifa = (struct in_ifaddr*)ptr;
+
+ switch (event) {
+ case NETDEV_UP:
+ fib_add_ifaddr(ifa);
+ rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+ if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
+ /* Last address was deleted from this interface.
+ Disable IP.
+ */
+ fib_disable_ip(ifa->ifa_dev->dev, 1);
+ } else {
+ fib_del_ifaddr(ifa);
+ rt_cache_flush(-1);
+ }
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct device *dev = ptr;
+ struct in_device *in_dev = dev->ip_ptr;
+
+ if (!in_dev)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_UP:
+ for_ifa(in_dev) {
+ fib_add_ifaddr(ifa);
+ } endfor_ifa(in_dev);
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ fib_sync_up(dev);
+#endif
+ rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+ fib_disable_ip(dev, 0);
+ break;
+ case NETDEV_UNREGISTER:
+ fib_disable_ip(dev, 1);
+ break;
+ case NETDEV_CHANGEMTU:
+ case NETDEV_CHANGE:
+ rt_cache_flush(0);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+struct notifier_block fib_inetaddr_notifier = {
+ fib_inetaddr_event,
+ NULL,
+ 0
+};
+
+struct notifier_block fib_netdev_notifier = {
+ fib_netdev_event,
+ NULL,
+ 0
+};
+
+__initfunc(void ip_fib_init(void))
+{
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&(struct proc_dir_entry) {
+ PROC_NET_ROUTE, 5, "route",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ fib_get_procinfo
+ });
+#endif /* CONFIG_PROC_FS */
+
+#ifndef CONFIG_IP_MULTIPLE_TABLES
+ local_table = fib_hash_init(RT_TABLE_LOCAL);
+ main_table = fib_hash_init(RT_TABLE_MAIN);
+#else
+ fib_rules_init();
+#endif
+
+ register_netdevice_notifier(&fib_netdev_notifier);
+ register_inetaddr_notifier(&fib_inetaddr_notifier);
+}
+
diff --git a/pfinet/linux-src/net/ipv4/fib_hash.c b/pfinet/linux-src/net/ipv4/fib_hash.c
new file mode 100644
index 00000000..d9e029ce
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/fib_hash.c
@@ -0,0 +1,885 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IPv4 FIB: lookup engine and maintenance routines.
+ *
+ * Version: $Id: fib_hash.c,v 1.8 1999/03/25 10:04:17 davem Exp $
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/init.h>
+
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <net/ip_fib.h>
+
+#define FTprint(a...)
+/*
+ printk(KERN_DEBUG a)
+ */
+
+/*
+ These bizarre types are just to force strict type checking.
+ When I reversed order of bytes and changed to natural mask lengths,
+ I forgot to make fixes in several places. Now I am lazy to return
+ it back.
+ */
+
+typedef struct {
+ u32 datum;
+} fn_key_t;
+
+typedef struct {
+ u32 datum;
+} fn_hash_idx_t;
+
+struct fib_node
+{
+ struct fib_node *fn_next;
+ struct fib_info *fn_info;
+#define FIB_INFO(f) ((f)->fn_info)
+ fn_key_t fn_key;
+ u8 fn_tos;
+ u8 fn_type;
+ u8 fn_scope;
+ u8 fn_state;
+};
+
+#define FN_S_ZOMBIE 1
+#define FN_S_ACCESSED 2
+
+static int fib_hash_zombies;
+
+struct fn_zone
+{
+ struct fn_zone *fz_next; /* Next not empty zone */
+ struct fib_node **fz_hash; /* Hash table pointer */
+ int fz_nent; /* Number of entries */
+
+ int fz_divisor; /* Hash divisor */
+ u32 fz_hashmask; /* (1<<fz_divisor) - 1 */
+#define FZ_HASHMASK(fz) ((fz)->fz_hashmask)
+
+ int fz_order; /* Zone order */
+ u32 fz_mask;
+#define FZ_MASK(fz) ((fz)->fz_mask)
+};
+
+/* NOTE. On fast computers evaluation of fz_hashmask and fz_mask
+ can be cheaper than memory lookup, so that FZ_* macros are used.
+ */
+
+struct fn_hash
+{
+ struct fn_zone *fn_zones[33];
+ struct fn_zone *fn_zone_list;
+};
+
+static __inline__ fn_hash_idx_t fn_hash(fn_key_t key, struct fn_zone *fz)
+{
+ u32 h = ntohl(key.datum)>>(32 - fz->fz_order);
+ h ^= (h>>20);
+ h ^= (h>>10);
+ h ^= (h>>5);
+ h &= FZ_HASHMASK(fz);
+ return *(fn_hash_idx_t*)&h;
+}
+
+#define fz_key_0(key) ((key).datum = 0)
+#define fz_prefix(key,fz) ((key).datum)
+
+static __inline__ fn_key_t fz_key(u32 dst, struct fn_zone *fz)
+{
+ fn_key_t k;
+ k.datum = dst & FZ_MASK(fz);
+ return k;
+}
+
+static __inline__ struct fib_node ** fz_chain_p(fn_key_t key, struct fn_zone *fz)
+{
+ return &fz->fz_hash[fn_hash(key, fz).datum];
+}
+
+static __inline__ struct fib_node * fz_chain(fn_key_t key, struct fn_zone *fz)
+{
+ return fz->fz_hash[fn_hash(key, fz).datum];
+}
+
+extern __inline__ int fn_key_eq(fn_key_t a, fn_key_t b)
+{
+ return a.datum == b.datum;
+}
+
+extern __inline__ int fn_key_leq(fn_key_t a, fn_key_t b)
+{
+ return a.datum <= b.datum;
+}
+
+#define FZ_MAX_DIVISOR 1024
+
+#ifdef CONFIG_IP_ROUTE_LARGE_TABLES
+
+static __inline__ void fn_rebuild_zone(struct fn_zone *fz,
+ struct fib_node **old_ht,
+ int old_divisor)
+{
+ int i;
+ struct fib_node *f, **fp, *next;
+
+ for (i=0; i<old_divisor; i++) {
+ for (f=old_ht[i]; f; f=next) {
+ next = f->fn_next;
+ for (fp = fz_chain_p(f->fn_key, fz);
+ *fp && fn_key_leq((*fp)->fn_key, f->fn_key);
+ fp = &(*fp)->fn_next)
+ /* NONE */;
+ f->fn_next = *fp;
+ *fp = f;
+ }
+ }
+}
+
+static void fn_rehash_zone(struct fn_zone *fz)
+{
+ struct fib_node **ht, **old_ht;
+ int old_divisor, new_divisor;
+ u32 new_hashmask;
+
+ old_divisor = fz->fz_divisor;
+
+ switch (old_divisor) {
+ case 16:
+ new_divisor = 256;
+ new_hashmask = 0xFF;
+ break;
+ case 256:
+ new_divisor = 1024;
+ new_hashmask = 0x3FF;
+ break;
+ default:
+ printk(KERN_CRIT "route.c: bad divisor %d!\n", old_divisor);
+ return;
+ }
+#if RT_CACHE_DEBUG >= 2
+ printk("fn_rehash_zone: hash for zone %d grows from %d\n", fz->fz_order, old_divisor);
+#endif
+
+ ht = kmalloc(new_divisor*sizeof(struct fib_node*), GFP_KERNEL);
+
+ if (ht) {
+ memset(ht, 0, new_divisor*sizeof(struct fib_node*));
+ start_bh_atomic();
+ old_ht = fz->fz_hash;
+ fz->fz_hash = ht;
+ fz->fz_hashmask = new_hashmask;
+ fz->fz_divisor = new_divisor;
+ fn_rebuild_zone(fz, old_ht, old_divisor);
+ end_bh_atomic();
+ kfree(old_ht);
+ }
+}
+#endif /* CONFIG_IP_ROUTE_LARGE_TABLES */
+
+static void fn_free_node(struct fib_node * f)
+{
+ fib_release_info(FIB_INFO(f));
+ kfree_s(f, sizeof(struct fib_node));
+}
+
+
+static struct fn_zone *
+fn_new_zone(struct fn_hash *table, int z)
+{
+ int i;
+ struct fn_zone *fz = kmalloc(sizeof(struct fn_zone), GFP_KERNEL);
+ if (!fz)
+ return NULL;
+
+ memset(fz, 0, sizeof(struct fn_zone));
+ if (z) {
+ fz->fz_divisor = 16;
+ fz->fz_hashmask = 0xF;
+ } else {
+ fz->fz_divisor = 1;
+ fz->fz_hashmask = 0;
+ }
+ fz->fz_hash = kmalloc(fz->fz_divisor*sizeof(struct fib_node*), GFP_KERNEL);
+ if (!fz->fz_hash) {
+ kfree(fz);
+ return NULL;
+ }
+ memset(fz->fz_hash, 0, fz->fz_divisor*sizeof(struct fib_node*));
+ fz->fz_order = z;
+ fz->fz_mask = inet_make_mask(z);
+
+ /* Find the first not empty zone with more specific mask */
+ for (i=z+1; i<=32; i++)
+ if (table->fn_zones[i])
+ break;
+ if (i>32) {
+ /* No more specific masks, we are the first. */
+ fz->fz_next = table->fn_zone_list;
+ table->fn_zone_list = fz;
+ } else {
+ fz->fz_next = table->fn_zones[i]->fz_next;
+ table->fn_zones[i]->fz_next = fz;
+ }
+ table->fn_zones[z] = fz;
+ return fz;
+}
+
+static int
+fn_hash_lookup(struct fib_table *tb, const struct rt_key *key, struct fib_result *res)
+{
+ int err;
+ struct fn_zone *fz;
+ struct fn_hash *t = (struct fn_hash*)tb->tb_data;
+
+ for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {
+ struct fib_node *f;
+ fn_key_t k = fz_key(key->dst, fz);
+
+ for (f = fz_chain(k, fz); f; f = f->fn_next) {
+ if (!fn_key_eq(k, f->fn_key)) {
+ if (fn_key_leq(k, f->fn_key))
+ break;
+ else
+ continue;
+ }
+#ifdef CONFIG_IP_ROUTE_TOS
+ if (f->fn_tos && f->fn_tos != key->tos)
+ continue;
+#endif
+ f->fn_state |= FN_S_ACCESSED;
+
+ if (f->fn_state&FN_S_ZOMBIE)
+ continue;
+ if (f->fn_scope < key->scope)
+ continue;
+
+ err = fib_semantic_match(f->fn_type, FIB_INFO(f), key, res);
+ if (err == 0) {
+ res->type = f->fn_type;
+ res->scope = f->fn_scope;
+ res->prefixlen = fz->fz_order;
+ res->prefix = &fz_prefix(f->fn_key, fz);
+ return 0;
+ }
+ if (err < 0)
+ return err;
+ }
+ }
+ return 1;
+}
+
+static int fn_hash_last_dflt=-1;
+
+static int fib_detect_death(struct fib_info *fi, int order,
+ struct fib_info **last_resort, int *last_idx)
+{
+ struct neighbour *n;
+ int state = NUD_NONE;
+
+ n = neigh_lookup(&arp_tbl, &fi->fib_nh[0].nh_gw, fi->fib_dev);
+ if (n) {
+ state = n->nud_state;
+ neigh_release(n);
+ }
+ if (state==NUD_REACHABLE)
+ return 0;
+ if ((state&NUD_VALID) && order != fn_hash_last_dflt)
+ return 0;
+ if ((state&NUD_VALID) ||
+ (*last_idx<0 && order > fn_hash_last_dflt)) {
+ *last_resort = fi;
+ *last_idx = order;
+ }
+ return 1;
+}
+
+static void
+fn_hash_select_default(struct fib_table *tb, const struct rt_key *key, struct fib_result *res)
+{
+ int order, last_idx;
+ struct fib_node *f;
+ struct fib_info *fi = NULL;
+ struct fib_info *last_resort;
+ struct fn_hash *t = (struct fn_hash*)tb->tb_data;
+ struct fn_zone *fz = t->fn_zones[0];
+
+ if (fz == NULL)
+ return;
+
+ last_idx = -1;
+ last_resort = NULL;
+ order = -1;
+
+ for (f = fz->fz_hash[0]; f; f = f->fn_next) {
+ struct fib_info *next_fi = FIB_INFO(f);
+
+ if ((f->fn_state&FN_S_ZOMBIE) ||
+ f->fn_scope != res->scope ||
+ f->fn_type != RTN_UNICAST)
+ continue;
+
+ if (next_fi->fib_priority > res->fi->fib_priority)
+ break;
+ if (!next_fi->fib_nh[0].nh_gw || next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+ continue;
+ f->fn_state |= FN_S_ACCESSED;
+
+ if (fi == NULL) {
+ if (next_fi != res->fi)
+ break;
+ } else if (!fib_detect_death(fi, order, &last_resort, &last_idx)) {
+ res->fi = fi;
+ fn_hash_last_dflt = order;
+ return;
+ }
+ fi = next_fi;
+ order++;
+ }
+
+ if (order<=0 || fi==NULL) {
+ fn_hash_last_dflt = -1;
+ return;
+ }
+
+ if (!fib_detect_death(fi, order, &last_resort, &last_idx)) {
+ res->fi = fi;
+ fn_hash_last_dflt = order;
+ return;
+ }
+
+ if (last_idx >= 0)
+ res->fi = last_resort;
+ fn_hash_last_dflt = last_idx;
+}
+
+#define FIB_SCAN(f, fp) \
+for ( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next)
+
+#define FIB_SCAN_KEY(f, fp, key) \
+for ( ; ((f) = *(fp)) != NULL && fn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
+
+#ifndef CONFIG_IP_ROUTE_TOS
+#define FIB_SCAN_TOS(f, fp, key, tos) FIB_SCAN_KEY(f, fp, key)
+#else
+#define FIB_SCAN_TOS(f, fp, key, tos) \
+for ( ; ((f) = *(fp)) != NULL && fn_key_eq((f)->fn_key, (key)) && \
+ (f)->fn_tos == (tos) ; (fp) = &(f)->fn_next)
+#endif
+
+
+#ifdef CONFIG_RTNETLINK
+static void rtmsg_fib(int, struct fib_node*, int, int,
+ struct nlmsghdr *n,
+ struct netlink_skb_parms *);
+#else
+#define rtmsg_fib(a, b, c, d, e, f)
+#endif
+
+
+static int
+fn_hash_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
+ struct nlmsghdr *n, struct netlink_skb_parms *req)
+{
+ struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+ struct fib_node *new_f, *f, **fp, **del_fp;
+ struct fn_zone *fz;
+ struct fib_info *fi;
+
+ int z = r->rtm_dst_len;
+ int type = r->rtm_type;
+#ifdef CONFIG_IP_ROUTE_TOS
+ u8 tos = r->rtm_tos;
+#endif
+ fn_key_t key;
+ int err;
+
+FTprint("tb(%d)_insert: %d %08x/%d %d %08x\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
+*(u32*)rta->rta_dst : 0, z, rta->rta_oif ? *rta->rta_oif : -1,
+rta->rta_prefsrc ? *(u32*)rta->rta_prefsrc : 0);
+ if (z > 32)
+ return -EINVAL;
+ fz = table->fn_zones[z];
+ if (!fz && !(fz = fn_new_zone(table, z)))
+ return -ENOBUFS;
+
+ fz_key_0(key);
+ if (rta->rta_dst) {
+ u32 dst;
+ memcpy(&dst, rta->rta_dst, 4);
+ if (dst & ~FZ_MASK(fz))
+ return -EINVAL;
+ key = fz_key(dst, fz);
+ }
+
+ if ((fi = fib_create_info(r, rta, n, &err)) == NULL)
+ return err;
+
+#ifdef CONFIG_IP_ROUTE_LARGE_TABLES
+ if (fz->fz_nent > (fz->fz_divisor<<2) &&
+ fz->fz_divisor < FZ_MAX_DIVISOR &&
+ (z==32 || (1<<z) > fz->fz_divisor))
+ fn_rehash_zone(fz);
+#endif
+
+ fp = fz_chain_p(key, fz);
+
+ /*
+ * Scan list to find the first route with the same destination
+ */
+ FIB_SCAN(f, fp) {
+ if (fn_key_leq(key,f->fn_key))
+ break;
+ }
+
+#ifdef CONFIG_IP_ROUTE_TOS
+ /*
+ * Find route with the same destination and tos.
+ */
+ FIB_SCAN_KEY(f, fp, key) {
+ if (f->fn_tos <= tos)
+ break;
+ }
+#endif
+
+ del_fp = NULL;
+
+ if (f && (f->fn_state&FN_S_ZOMBIE) &&
+#ifdef CONFIG_IP_ROUTE_TOS
+ f->fn_tos == tos &&
+#endif
+ fn_key_eq(f->fn_key, key)) {
+ del_fp = fp;
+ fp = &f->fn_next;
+ f = *fp;
+ goto create;
+ }
+
+ FIB_SCAN_TOS(f, fp, key, tos) {
+ if (fi->fib_priority <= FIB_INFO(f)->fib_priority)
+ break;
+ }
+
+ /* Now f==*fp points to the first node with the same
+ keys [prefix,tos,priority], if such key already
+ exists or to the node, before which we will insert new one.
+ */
+
+ if (f &&
+#ifdef CONFIG_IP_ROUTE_TOS
+ f->fn_tos == tos &&
+#endif
+ fn_key_eq(f->fn_key, key) &&
+ fi->fib_priority == FIB_INFO(f)->fib_priority) {
+ struct fib_node **ins_fp;
+
+ err = -EEXIST;
+ if (n->nlmsg_flags&NLM_F_EXCL)
+ goto out;
+
+ if (n->nlmsg_flags&NLM_F_REPLACE) {
+ del_fp = fp;
+ fp = &f->fn_next;
+ f = *fp;
+ goto replace;
+ }
+
+ ins_fp = fp;
+ err = -EEXIST;
+
+ FIB_SCAN_TOS(f, fp, key, tos) {
+ if (fi->fib_priority != FIB_INFO(f)->fib_priority)
+ break;
+ if (f->fn_type == type && f->fn_scope == r->rtm_scope
+ && FIB_INFO(f) == fi)
+ goto out;
+ }
+
+ if (!(n->nlmsg_flags&NLM_F_APPEND)) {
+ fp = ins_fp;
+ f = *fp;
+ }
+ }
+
+create:
+ err = -ENOENT;
+ if (!(n->nlmsg_flags&NLM_F_CREATE))
+ goto out;
+
+replace:
+ err = -ENOBUFS;
+ new_f = (struct fib_node *) kmalloc(sizeof(struct fib_node), GFP_KERNEL);
+ if (new_f == NULL)
+ goto out;
+
+ memset(new_f, 0, sizeof(struct fib_node));
+
+ new_f->fn_key = key;
+#ifdef CONFIG_IP_ROUTE_TOS
+ new_f->fn_tos = tos;
+#endif
+ new_f->fn_type = type;
+ new_f->fn_scope = r->rtm_scope;
+ FIB_INFO(new_f) = fi;
+
+ /*
+ * Insert new entry to the list.
+ */
+
+ new_f->fn_next = f;
+ *fp = new_f;
+ fz->fz_nent++;
+
+ if (del_fp) {
+ f = *del_fp;
+ /* Unlink replaced node */
+ *del_fp = f->fn_next;
+ synchronize_bh();
+
+ if (!(f->fn_state&FN_S_ZOMBIE))
+ rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
+ if (f->fn_state&FN_S_ACCESSED)
+ rt_cache_flush(-1);
+ fn_free_node(f);
+ fz->fz_nent--;
+ } else {
+ rt_cache_flush(-1);
+ }
+ rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->tb_id, n, req);
+ return 0;
+
+out:
+ fib_release_info(fi);
+ return err;
+}
+
+
+static int
+fn_hash_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
+ struct nlmsghdr *n, struct netlink_skb_parms *req)
+{
+ struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+ struct fib_node **fp, **del_fp, *f;
+ int z = r->rtm_dst_len;
+ struct fn_zone *fz;
+ fn_key_t key;
+ int matched;
+#ifdef CONFIG_IP_ROUTE_TOS
+ u8 tos = r->rtm_tos;
+#endif
+
+FTprint("tb(%d)_delete: %d %08x/%d %d\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
+ *(u32*)rta->rta_dst : 0, z, rta->rta_oif ? *rta->rta_oif : -1);
+ if (z > 32)
+ return -EINVAL;
+ if ((fz = table->fn_zones[z]) == NULL)
+ return -ESRCH;
+
+ fz_key_0(key);
+ if (rta->rta_dst) {
+ u32 dst;
+ memcpy(&dst, rta->rta_dst, 4);
+ if (dst & ~FZ_MASK(fz))
+ return -EINVAL;
+ key = fz_key(dst, fz);
+ }
+
+ fp = fz_chain_p(key, fz);
+
+ FIB_SCAN(f, fp) {
+ if (fn_key_eq(f->fn_key, key))
+ break;
+ if (fn_key_leq(key, f->fn_key))
+ return -ESRCH;
+ }
+#ifdef CONFIG_IP_ROUTE_TOS
+ FIB_SCAN_KEY(f, fp, key) {
+ if (f->fn_tos == tos)
+ break;
+ }
+#endif
+
+ matched = 0;
+ del_fp = NULL;
+ FIB_SCAN_TOS(f, fp, key, tos) {
+ struct fib_info * fi = FIB_INFO(f);
+
+ if (f->fn_state&FN_S_ZOMBIE)
+ return -ESRCH;
+
+ matched++;
+
+ if (del_fp == NULL &&
+ (!r->rtm_type || f->fn_type == r->rtm_type) &&
+ (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
+ (!r->rtm_protocol || fi->fib_protocol == r->rtm_protocol) &&
+ fib_nh_match(r, n, rta, fi) == 0)
+ del_fp = fp;
+ }
+
+ if (del_fp) {
+ f = *del_fp;
+ rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
+
+ if (matched != 1) {
+ *del_fp = f->fn_next;
+ synchronize_bh();
+
+ if (f->fn_state&FN_S_ACCESSED)
+ rt_cache_flush(-1);
+ fn_free_node(f);
+ fz->fz_nent--;
+ } else {
+ f->fn_state |= FN_S_ZOMBIE;
+ if (f->fn_state&FN_S_ACCESSED) {
+ f->fn_state &= ~FN_S_ACCESSED;
+ rt_cache_flush(-1);
+ }
+ if (++fib_hash_zombies > 128)
+ fib_flush();
+ }
+
+ return 0;
+ }
+ return -ESRCH;
+}
+
+extern __inline__ int
+fn_flush_list(struct fib_node ** fp, int z, struct fn_hash *table)
+{
+ int found = 0;
+ struct fib_node *f;
+
+ while ((f = *fp) != NULL) {
+ struct fib_info *fi = FIB_INFO(f);
+
+ if (fi && ((f->fn_state&FN_S_ZOMBIE) || (fi->fib_flags&RTNH_F_DEAD))) {
+ *fp = f->fn_next;
+ synchronize_bh();
+
+ fn_free_node(f);
+ found++;
+ continue;
+ }
+ fp = &f->fn_next;
+ }
+ return found;
+}
+
+static int fn_hash_flush(struct fib_table *tb)
+{
+ struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+ struct fn_zone *fz;
+ int found = 0;
+
+ fib_hash_zombies = 0;
+ for (fz = table->fn_zone_list; fz; fz = fz->fz_next) {
+ int i;
+ int tmp = 0;
+ for (i=fz->fz_divisor-1; i>=0; i--)
+ tmp += fn_flush_list(&fz->fz_hash[i], fz->fz_order, table);
+ fz->fz_nent -= tmp;
+ found += tmp;
+ }
+ return found;
+}
+
+
+#ifdef CONFIG_PROC_FS
+
+static int fn_hash_get_info(struct fib_table *tb, char *buffer, int first, int count)
+{
+ struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+ struct fn_zone *fz;
+ int pos = 0;
+ int n = 0;
+
+ for (fz=table->fn_zone_list; fz; fz = fz->fz_next) {
+ int i;
+ struct fib_node *f;
+ int maxslot = fz->fz_divisor;
+ struct fib_node **fp = fz->fz_hash;
+
+ if (fz->fz_nent == 0)
+ continue;
+
+ if (pos + fz->fz_nent <= first) {
+ pos += fz->fz_nent;
+ continue;
+ }
+
+ for (i=0; i < maxslot; i++, fp++) {
+ for (f = *fp; f; f = f->fn_next) {
+ if (++pos <= first)
+ continue;
+ fib_node_get_info(f->fn_type,
+ f->fn_state&FN_S_ZOMBIE,
+ FIB_INFO(f),
+ fz_prefix(f->fn_key, fz),
+ FZ_MASK(fz), buffer);
+ buffer += 128;
+ if (++n >= count)
+ return n;
+ }
+ }
+ }
+ return n;
+}
+#endif
+
+
+#ifdef CONFIG_RTNETLINK
+
+extern __inline__ int
+fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
+ struct fib_table *tb,
+ struct fn_zone *fz,
+ struct fib_node *f)
+{
+ int i, s_i;
+
+ s_i = cb->args[3];
+ for (i=0; f; i++, f=f->fn_next) {
+ if (i < s_i) continue;
+ if (f->fn_state&FN_S_ZOMBIE) continue;
+ if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+ RTM_NEWROUTE,
+ tb->tb_id, (f->fn_state&FN_S_ZOMBIE) ? 0 : f->fn_type, f->fn_scope,
+ &f->fn_key, fz->fz_order, f->fn_tos,
+ f->fn_info) < 0) {
+ cb->args[3] = i;
+ return -1;
+ }
+ }
+ cb->args[3] = i;
+ return skb->len;
+}
+
+extern __inline__ int
+fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb,
+ struct fib_table *tb,
+ struct fn_zone *fz)
+{
+ int h, s_h;
+
+ s_h = cb->args[2];
+ for (h=0; h < fz->fz_divisor; h++) {
+ if (h < s_h) continue;
+ if (h > s_h)
+ memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
+ if (fz->fz_hash == NULL || fz->fz_hash[h] == NULL)
+ continue;
+ if (fn_hash_dump_bucket(skb, cb, tb, fz, fz->fz_hash[h]) < 0) {
+ cb->args[2] = h;
+ return -1;
+ }
+ }
+ cb->args[2] = h;
+ return skb->len;
+}
+
+static int fn_hash_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int m, s_m;
+ struct fn_zone *fz;
+ struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+
+ s_m = cb->args[1];
+ for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
+ if (m < s_m) continue;
+ if (m > s_m)
+ memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0]));
+ if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
+ cb->args[1] = m;
+ return -1;
+ }
+ }
+ cb->args[1] = m;
+ return skb->len;
+}
+
+static void rtmsg_fib(int event, struct fib_node* f, int z, int tb_id,
+ struct nlmsghdr *n, struct netlink_skb_parms *req)
+{
+ struct sk_buff *skb;
+ u32 pid = req ? req->pid : 0;
+ int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
+
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb)
+ return;
+
+ if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id,
+ f->fn_type, f->fn_scope, &f->fn_key, z, f->fn_tos,
+ FIB_INFO(f)) < 0) {
+ kfree_skb(skb);
+ return;
+ }
+ NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_ROUTE;
+ if (n->nlmsg_flags&NLM_F_ECHO)
+ atomic_inc(&skb->users);
+ netlink_broadcast(rtnl, skb, pid, RTMGRP_IPV4_ROUTE, GFP_KERNEL);
+ if (n->nlmsg_flags&NLM_F_ECHO)
+ netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
+}
+
+#endif /* CONFIG_RTNETLINK */
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+struct fib_table * fib_hash_init(int id)
+#else
+__initfunc(struct fib_table * fib_hash_init(int id))
+#endif
+{
+ struct fib_table *tb;
+ tb = kmalloc(sizeof(struct fib_table) + sizeof(struct fn_hash), GFP_KERNEL);
+ if (tb == NULL)
+ return NULL;
+ tb->tb_id = id;
+ tb->tb_lookup = fn_hash_lookup;
+ tb->tb_insert = fn_hash_insert;
+ tb->tb_delete = fn_hash_delete;
+ tb->tb_flush = fn_hash_flush;
+ tb->tb_select_default = fn_hash_select_default;
+#ifdef CONFIG_RTNETLINK
+ tb->tb_dump = fn_hash_dump;
+#endif
+#ifdef CONFIG_PROC_FS
+ tb->tb_get_info = fn_hash_get_info;
+#endif
+ memset(tb->tb_data, 0, sizeof(struct fn_hash));
+ return tb;
+}
diff --git a/pfinet/linux-src/net/ipv4/fib_rules.c b/pfinet/linux-src/net/ipv4/fib_rules.c
new file mode 100644
index 00000000..868c44c3
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/fib_rules.c
@@ -0,0 +1,419 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IPv4 Forwarding Information Base: policy rules.
+ *
+ * Version: $Id: fib_rules.c,v 1.9 1999/03/25 10:04:23 davem Exp $
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ * Rani Assaf : local_rule cannot be deleted
+ * Marc Boucher : routing by fwmark
+ */
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/init.h>
+
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <net/ip_fib.h>
+
+#define FRprintk(a...)
+
+struct fib_rule
+{
+ struct fib_rule *r_next;
+ u32 r_preference;
+ unsigned char r_table;
+ unsigned char r_action;
+ unsigned char r_dst_len;
+ unsigned char r_src_len;
+ u32 r_src;
+ u32 r_srcmask;
+ u32 r_dst;
+ u32 r_dstmask;
+ u32 r_srcmap;
+ u8 r_flags;
+ u8 r_tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ u32 r_fwmark;
+#endif
+ int r_ifindex;
+#ifdef CONFIG_NET_CLS_ROUTE
+ __u32 r_tclassid;
+#endif
+ char r_ifname[IFNAMSIZ];
+};
+
+static struct fib_rule default_rule = { NULL, 0x7FFF, RT_TABLE_DEFAULT, RTN_UNICAST, };
+static struct fib_rule main_rule = { &default_rule, 0x7FFE, RT_TABLE_MAIN, RTN_UNICAST, };
+static struct fib_rule local_rule = { &main_rule, 0, RT_TABLE_LOCAL, RTN_UNICAST, };
+
+static struct fib_rule *fib_rules = &local_rule;
+
+int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+{
+ struct rtattr **rta = arg;
+ struct rtmsg *rtm = NLMSG_DATA(nlh);
+ struct fib_rule *r, **rp;
+
+ for (rp=&fib_rules; (r=*rp) != NULL; rp=&r->r_next) {
+ if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) &&
+ rtm->rtm_src_len == r->r_src_len &&
+ rtm->rtm_dst_len == r->r_dst_len &&
+ (!rta[RTA_DST-1] || memcmp(RTA_DATA(rta[RTA_DST-1]), &r->r_dst, 4) == 0) &&
+ rtm->rtm_tos == r->r_tos &&
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ (!rta[RTA_PROTOINFO-1] || memcmp(RTA_DATA(rta[RTA_PROTOINFO-1]), &r->r_fwmark, 4) == 0) &&
+#endif
+ (!rtm->rtm_type || rtm->rtm_type == r->r_action) &&
+ (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
+ (!rta[RTA_IIF-1] || strcmp(RTA_DATA(rta[RTA_IIF-1]), r->r_ifname) == 0) &&
+ (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
+ if (r == &local_rule)
+ return -EPERM;
+
+ *rp = r->r_next;
+ synchronize_bh();
+
+ if (r != &default_rule && r != &main_rule)
+ kfree(r);
+ return 0;
+ }
+ }
+ return -ESRCH;
+}
+
+/* Allocate new unique table id */
+
+static struct fib_table *fib_empty_table(void)
+{
+ int id;
+
+ for (id = 1; id <= RT_TABLE_MAX; id++)
+ if (fib_tables[id] == NULL)
+ return __fib_new_table(id);
+ return NULL;
+}
+
+
+int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+{
+ struct rtattr **rta = arg;
+ struct rtmsg *rtm = NLMSG_DATA(nlh);
+ struct fib_rule *r, *new_r, **rp;
+ unsigned char table_id;
+
+ if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 ||
+ (rtm->rtm_tos & ~IPTOS_TOS_MASK))
+ return -EINVAL;
+
+ if (rta[RTA_IIF-1] && RTA_PAYLOAD(rta[RTA_IIF-1]) > IFNAMSIZ)
+ return -EINVAL;
+
+ table_id = rtm->rtm_table;
+ if (table_id == RT_TABLE_UNSPEC) {
+ struct fib_table *table;
+ if (rtm->rtm_type == RTN_UNICAST || rtm->rtm_type == RTN_NAT) {
+ if ((table = fib_empty_table()) == NULL)
+ return -ENOBUFS;
+ table_id = table->tb_id;
+ }
+ }
+
+ new_r = kmalloc(sizeof(*new_r), GFP_KERNEL);
+ if (!new_r)
+ return -ENOMEM;
+ memset(new_r, 0, sizeof(*new_r));
+ if (rta[RTA_SRC-1])
+ memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4);
+ if (rta[RTA_DST-1])
+ memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 4);
+ if (rta[RTA_GATEWAY-1])
+ memcpy(&new_r->r_srcmap, RTA_DATA(rta[RTA_GATEWAY-1]), 4);
+ new_r->r_src_len = rtm->rtm_src_len;
+ new_r->r_dst_len = rtm->rtm_dst_len;
+ new_r->r_srcmask = inet_make_mask(rtm->rtm_src_len);
+ new_r->r_dstmask = inet_make_mask(rtm->rtm_dst_len);
+ new_r->r_tos = rtm->rtm_tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ if (rta[RTA_PROTOINFO-1])
+ memcpy(&new_r->r_fwmark, RTA_DATA(rta[RTA_PROTOINFO-1]), 4);
+#endif
+ new_r->r_action = rtm->rtm_type;
+ new_r->r_flags = rtm->rtm_flags;
+ if (rta[RTA_PRIORITY-1])
+ memcpy(&new_r->r_preference, RTA_DATA(rta[RTA_PRIORITY-1]), 4);
+ new_r->r_table = table_id;
+ if (rta[RTA_IIF-1]) {
+ struct device *dev;
+ memcpy(new_r->r_ifname, RTA_DATA(rta[RTA_IIF-1]), IFNAMSIZ);
+ new_r->r_ifname[IFNAMSIZ-1] = 0;
+ new_r->r_ifindex = -1;
+ dev = dev_get(new_r->r_ifname);
+ if (dev)
+ new_r->r_ifindex = dev->ifindex;
+ }
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (rta[RTA_FLOW-1])
+ memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4);
+#endif
+
+ rp = &fib_rules;
+ if (!new_r->r_preference) {
+ r = fib_rules;
+ if (r && (r = r->r_next) != NULL) {
+ rp = &fib_rules->r_next;
+ if (r->r_preference)
+ new_r->r_preference = r->r_preference - 1;
+ }
+ }
+
+ while ( (r = *rp) != NULL ) {
+ if (r->r_preference > new_r->r_preference)
+ break;
+ rp = &r->r_next;
+ }
+
+ new_r->r_next = r;
+ *rp = new_r;
+ return 0;
+}
+
+u32 fib_rules_map_destination(u32 daddr, struct fib_result *res)
+{
+ u32 mask = inet_make_mask(res->prefixlen);
+ return (daddr&~mask)|res->fi->fib_nh->nh_gw;
+}
+
+u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags)
+{
+ struct fib_rule *r = res->r;
+
+ if (r->r_action == RTN_NAT) {
+ int addrtype = inet_addr_type(r->r_srcmap);
+
+ if (addrtype == RTN_NAT) {
+ /* Packet is from translated source; remember it */
+ saddr = (saddr&~r->r_srcmask)|r->r_srcmap;
+ *flags |= RTCF_SNAT;
+ } else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) {
+ /* Packet is from masqueraded source; remember it */
+ saddr = r->r_srcmap;
+ *flags |= RTCF_MASQ;
+ }
+ }
+ return saddr;
+}
+
+#ifdef CONFIG_NET_CLS_ROUTE
+u32 fib_rules_tclass(struct fib_result *res)
+{
+ if (res->r)
+ return res->r->r_tclassid;
+ return 0;
+}
+#endif
+
+
+static void fib_rules_detach(struct device *dev)
+{
+ struct fib_rule *r;
+
+ for (r=fib_rules; r; r=r->r_next) {
+ if (r->r_ifindex == dev->ifindex)
+ r->r_ifindex = -1;
+ }
+}
+
+static void fib_rules_attach(struct device *dev)
+{
+ struct fib_rule *r;
+
+ for (r=fib_rules; r; r=r->r_next) {
+ if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0)
+ r->r_ifindex = dev->ifindex;
+ }
+}
+
+int fib_lookup(const struct rt_key *key, struct fib_result *res)
+{
+ int err;
+ struct fib_rule *r, *policy;
+ struct fib_table *tb;
+
+ u32 daddr = key->dst;
+ u32 saddr = key->src;
+
+FRprintk("Lookup: %08x <- %08x ", key->dst, key->src);
+ for (r = fib_rules; r; r=r->r_next) {
+ if (((saddr^r->r_src) & r->r_srcmask) ||
+ ((daddr^r->r_dst) & r->r_dstmask) ||
+#ifdef CONFIG_IP_ROUTE_TOS
+ (r->r_tos && r->r_tos != key->tos) ||
+#endif
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ (r->r_fwmark && r->r_fwmark != key->fwmark) ||
+#endif
+ (r->r_ifindex && r->r_ifindex != key->iif))
+ continue;
+
+FRprintk("tb %d r %d ", r->r_table, r->r_action);
+ switch (r->r_action) {
+ case RTN_UNICAST:
+ case RTN_NAT:
+ policy = r;
+ break;
+ case RTN_UNREACHABLE:
+ return -ENETUNREACH;
+ default:
+ case RTN_BLACKHOLE:
+ return -EINVAL;
+ case RTN_PROHIBIT:
+ return -EACCES;
+ }
+
+ if ((tb = fib_get_table(r->r_table)) == NULL)
+ continue;
+ err = tb->tb_lookup(tb, key, res);
+ if (err == 0) {
+FRprintk("ok\n");
+ res->r = policy;
+ return 0;
+ }
+ if (err < 0 && err != -EAGAIN)
+ return err;
+ }
+FRprintk("FAILURE\n");
+ return -ENETUNREACH;
+}
+
+void fib_select_default(const struct rt_key *key, struct fib_result *res)
+{
+ if (res->r && res->r->r_action == RTN_UNICAST &&
+ FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
+ struct fib_table *tb;
+ if ((tb = fib_get_table(res->r->r_table)) != NULL)
+ tb->tb_select_default(tb, key, res);
+ }
+}
+
+static int fib_rules_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct device *dev = ptr;
+
+ if (event == NETDEV_UNREGISTER)
+ fib_rules_detach(dev);
+ else if (event == NETDEV_REGISTER)
+ fib_rules_attach(dev);
+ return NOTIFY_DONE;
+}
+
+
+struct notifier_block fib_rules_notifier = {
+ fib_rules_event,
+ NULL,
+ 0
+};
+
+#ifdef CONFIG_RTNETLINK
+
+extern __inline__ int inet_fill_rule(struct sk_buff *skb,
+ struct fib_rule *r,
+ struct netlink_callback *cb)
+{
+ struct rtmsg *rtm;
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
+ rtm = NLMSG_DATA(nlh);
+ rtm->rtm_family = AF_INET;
+ rtm->rtm_dst_len = r->r_dst_len;
+ rtm->rtm_src_len = r->r_src_len;
+ rtm->rtm_tos = r->r_tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ if (r->r_fwmark)
+ RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark);
+#endif
+ rtm->rtm_table = r->r_table;
+ rtm->rtm_protocol = 0;
+ rtm->rtm_scope = 0;
+ rtm->rtm_type = r->r_action;
+ rtm->rtm_flags = r->r_flags;
+
+ if (r->r_dst_len)
+ RTA_PUT(skb, RTA_DST, 4, &r->r_dst);
+ if (r->r_src_len)
+ RTA_PUT(skb, RTA_SRC, 4, &r->r_src);
+ if (r->r_ifname[0])
+ RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname);
+ if (r->r_preference)
+ RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference);
+ if (r->r_srcmap)
+ RTA_PUT(skb, RTA_GATEWAY, 4, &r->r_srcmap);
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (r->r_tclassid)
+ RTA_PUT(skb, RTA_FLOW, 4, &r->r_tclassid);
+#endif
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+ skb_put(skb, b - skb->tail);
+ return -1;
+}
+
+int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx;
+ int s_idx = cb->args[0];
+ struct fib_rule *r;
+
+ for (r=fib_rules, idx=0; r; r = r->r_next, idx++) {
+ if (idx < s_idx)
+ continue;
+ if (inet_fill_rule(skb, r, cb) < 0)
+ break;
+ }
+ cb->args[0] = idx;
+
+ return skb->len;
+}
+
+#endif /* CONFIG_RTNETLINK */
+
+__initfunc(void fib_rules_init(void))
+{
+ register_netdevice_notifier(&fib_rules_notifier);
+}
diff --git a/pfinet/linux-src/net/ipv4/fib_semantics.c b/pfinet/linux-src/net/ipv4/fib_semantics.c
new file mode 100644
index 00000000..b78f7eba
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/fib_semantics.c
@@ -0,0 +1,991 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IPv4 Forwarding Information Base: semantics.
+ *
+ * Version: $Id: fib_semantics.c,v 1.13 1999/03/21 05:22:34 davem Exp $
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/init.h>
+
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <net/ip_fib.h>
+
+#define FSprintk(a...)
+
+static struct fib_info *fib_info_list;
+
+#define for_fib_info() { struct fib_info *fi; \
+ for (fi = fib_info_list; fi; fi = fi->fib_next)
+
+#define endfor_fib_info() }
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+
+#define for_nexthops(fi) { int nhsel; const struct fib_nh * nh; \
+for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
+
+#define change_nexthops(fi) { int nhsel; struct fib_nh * nh; \
+for (nhsel=0, nh = (struct fib_nh*)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++)
+
+#else /* CONFIG_IP_ROUTE_MULTIPATH */
+
+/* Hope, that gcc will optimize it to get rid of dummy loop */
+
+#define for_nexthops(fi) { int nhsel=0; const struct fib_nh * nh = (fi)->fib_nh; \
+for (nhsel=0; nhsel < 1; nhsel++)
+
+#define change_nexthops(fi) { int nhsel=0; struct fib_nh * nh = (struct fib_nh*)((fi)->fib_nh); \
+for (nhsel=0; nhsel < 1; nhsel++)
+
+#endif /* CONFIG_IP_ROUTE_MULTIPATH */
+
+#define endfor_nexthops(fi) }
+
+
+static struct
+{
+ int error;
+ u8 scope;
+} fib_props[RTA_MAX+1] = {
+ { 0, RT_SCOPE_NOWHERE}, /* RTN_UNSPEC */
+ { 0, RT_SCOPE_UNIVERSE}, /* RTN_UNICAST */
+ { 0, RT_SCOPE_HOST}, /* RTN_LOCAL */
+ { 0, RT_SCOPE_LINK}, /* RTN_BROADCAST */
+ { 0, RT_SCOPE_LINK}, /* RTN_ANYCAST */
+ { 0, RT_SCOPE_UNIVERSE}, /* RTN_MULTICAST */
+ { -EINVAL, RT_SCOPE_UNIVERSE}, /* RTN_BLACKHOLE */
+ { -EHOSTUNREACH, RT_SCOPE_UNIVERSE},/* RTN_UNREACHABLE */
+ { -EACCES, RT_SCOPE_UNIVERSE}, /* RTN_PROHIBIT */
+ { -EAGAIN, RT_SCOPE_UNIVERSE}, /* RTN_THROW */
+#ifdef CONFIG_IP_ROUTE_NAT
+ { 0, RT_SCOPE_HOST}, /* RTN_NAT */
+#else
+ { -EINVAL, RT_SCOPE_NOWHERE}, /* RTN_NAT */
+#endif
+ { -EINVAL, RT_SCOPE_NOWHERE} /* RTN_XRESOLVE */
+};
+
+/* Release a nexthop info record */
+
+void fib_release_info(struct fib_info *fi)
+{
+ if (fi && !--fi->fib_refcnt) {
+ if (fi->fib_next)
+ fi->fib_next->fib_prev = fi->fib_prev;
+ if (fi->fib_prev)
+ fi->fib_prev->fib_next = fi->fib_next;
+ if (fi == fib_info_list)
+ fib_info_list = fi->fib_next;
+ kfree(fi);
+ }
+}
+
+extern __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
+{
+ const struct fib_nh *onh = ofi->fib_nh;
+
+ for_nexthops(fi) {
+ if (nh->nh_oif != onh->nh_oif ||
+ nh->nh_gw != onh->nh_gw ||
+ nh->nh_scope != onh->nh_scope ||
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ nh->nh_weight != onh->nh_weight ||
+#endif
+#ifdef CONFIG_NET_CLS_ROUTE
+ nh->nh_tclassid != onh->nh_tclassid ||
+#endif
+ ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD))
+ return -1;
+ onh++;
+ } endfor_nexthops(fi);
+ return 0;
+}
+
+extern __inline__ struct fib_info * fib_find_info(const struct fib_info *nfi)
+{
+ for_fib_info() {
+ if (fi->fib_nhs != nfi->fib_nhs)
+ continue;
+ if (nfi->fib_protocol == fi->fib_protocol &&
+ nfi->fib_prefsrc == fi->fib_prefsrc &&
+ nfi->fib_priority == fi->fib_priority &&
+ nfi->fib_mtu == fi->fib_mtu &&
+ nfi->fib_rtt == fi->fib_rtt &&
+ nfi->fib_window == fi->fib_window &&
+ ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
+ (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
+ return fi;
+ } endfor_fib_info();
+ return NULL;
+}
+
+/* Check, that the gateway is already configured.
+ Used only by redirect accept routine.
+ */
+
+int ip_fib_check_default(u32 gw, struct device *dev)
+{
+ for_fib_info() {
+ if (fi->fib_flags & RTNH_F_DEAD)
+ continue;
+ for_nexthops(fi) {
+ if (nh->nh_dev == dev && nh->nh_gw == gw &&
+ !(nh->nh_flags&RTNH_F_DEAD))
+ return 0;
+ } endfor_nexthops(fi);
+ } endfor_fib_info();
+ return -1;
+}
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+
+static u32 fib_get_attr32(struct rtattr *attr, int attrlen, int type)
+{
+ while (RTA_OK(attr,attrlen)) {
+ if (attr->rta_type == type)
+ return *(u32*)RTA_DATA(attr);
+ attr = RTA_NEXT(attr, attrlen);
+ }
+ return 0;
+}
+
+static int
+fib_count_nexthops(struct rtattr *rta)
+{
+ int nhs = 0;
+ struct rtnexthop *nhp = RTA_DATA(rta);
+ int nhlen = RTA_PAYLOAD(rta);
+
+ while (nhlen >= (int)sizeof(struct rtnexthop)) {
+ if ((nhlen -= nhp->rtnh_len) < 0)
+ return 0;
+ nhs++;
+ nhp = RTNH_NEXT(nhp);
+ };
+ return nhs;
+}
+
+static int
+fib_get_nhs(struct fib_info *fi, const struct rtattr *rta, const struct rtmsg *r)
+{
+ struct rtnexthop *nhp = RTA_DATA(rta);
+ int nhlen = RTA_PAYLOAD(rta);
+
+ change_nexthops(fi) {
+ int attrlen = nhlen - sizeof(struct rtnexthop);
+ if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
+ return -EINVAL;
+ nh->nh_flags = (r->rtm_flags&~0xFF) | nhp->rtnh_flags;
+ nh->nh_oif = nhp->rtnh_ifindex;
+ nh->nh_weight = nhp->rtnh_hops + 1;
+ if (attrlen) {
+ nh->nh_gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
+#ifdef CONFIG_NET_CLS_ROUTE
+ nh->nh_tclassid = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_FLOW);
+#endif
+ }
+ nhp = RTNH_NEXT(nhp);
+ } endfor_nexthops(fi);
+ return 0;
+}
+
+#endif
+
+int fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct kern_rta *rta,
+ struct fib_info *fi)
+{
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ struct rtnexthop *nhp;
+ int nhlen;
+#endif
+
+ if (rta->rta_priority &&
+ *rta->rta_priority != fi->fib_priority)
+ return 1;
+
+ if (rta->rta_oif || rta->rta_gw) {
+ if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&
+ (!rta->rta_gw || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 4) == 0))
+ return 0;
+ return 1;
+ }
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (rta->rta_mp == NULL)
+ return 0;
+ nhp = RTA_DATA(rta->rta_mp);
+ nhlen = RTA_PAYLOAD(rta->rta_mp);
+
+ for_nexthops(fi) {
+ int attrlen = nhlen - sizeof(struct rtnexthop);
+ u32 gw;
+
+ if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
+ return -EINVAL;
+ if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif)
+ return 1;
+ if (attrlen) {
+ gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
+ if (gw && gw != nh->nh_gw)
+ return 1;
+#ifdef CONFIG_NET_CLS_ROUTE
+ gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_FLOW);
+ if (gw && gw != nh->nh_tclassid)
+ return 1;
+#endif
+ }
+ nhp = RTNH_NEXT(nhp);
+ } endfor_nexthops(fi);
+#endif
+ return 0;
+}
+
+
+/*
+ Picture
+ -------
+
+ Semantics of nexthop is very messy by historical reasons.
+ We have to take into account, that:
+ a) gateway can be actually local interface address,
+ so that gatewayed route is direct.
+ b) gateway must be on-link address, possibly
+ described not by an ifaddr, but also by a direct route.
+ c) If both gateway and interface are specified, they should not
+ contradict.
+ d) If we use tunnel routes, gateway could be not on-link.
+
+ Attempt to reconcile all of these (alas, self-contradictory) conditions
+ results in pretty ugly and hairy code with obscure logic.
+
+ I choosed to generalized it instead, so that the size
+ of code does not increase practically, but it becomes
+ much more general.
+ Every prefix is assigned a "scope" value: "host" is local address,
+ "link" is direct route,
+ [ ... "site" ... "interior" ... ]
+ and "universe" is true gateway route with global meaning.
+
+ Every prefix refers to a set of "nexthop"s (gw, oif),
+ where gw must have narrower scope. This recursion stops
+ when gw has LOCAL scope or if "nexthop" is declared ONLINK,
+ which means that gw is forced to be on link.
+
+ Code is still hairy, but now it is apparently logically
+ consistent and very flexible. F.e. as by-product it allows
+ to co-exists in peace independent exterior and interior
+ routing processes.
+
+ Normally it looks as following.
+
+ {universe prefix} -> (gw, oif) [scope link]
+ |
+ |-> {link prefix} -> (gw, oif) [scope local]
+ |
+ |-> {local prefix} (terminal node)
+ */
+
+static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_nh *nh)
+{
+ int err;
+
+ if (nh->nh_gw) {
+ struct rt_key key;
+ struct fib_result res;
+
+#ifdef CONFIG_IP_ROUTE_PERVASIVE
+ if (nh->nh_flags&RTNH_F_PERVASIVE)
+ return 0;
+#endif
+ if (nh->nh_flags&RTNH_F_ONLINK) {
+ struct device *dev;
+
+ if (r->rtm_scope >= RT_SCOPE_LINK)
+ return -EINVAL;
+ if (inet_addr_type(nh->nh_gw) != RTN_UNICAST)
+ return -EINVAL;
+ if ((dev = dev_get_by_index(nh->nh_oif)) == NULL)
+ return -ENODEV;
+ if (!(dev->flags&IFF_UP))
+ return -ENETDOWN;
+ nh->nh_dev = dev;
+ nh->nh_scope = RT_SCOPE_LINK;
+ return 0;
+ }
+ memset(&key, 0, sizeof(key));
+ key.dst = nh->nh_gw;
+ key.oif = nh->nh_oif;
+ key.scope = r->rtm_scope + 1;
+
+ /* It is not necessary, but requires a bit of thinking */
+ if (key.scope < RT_SCOPE_LINK)
+ key.scope = RT_SCOPE_LINK;
+
+ if ((err = fib_lookup(&key, &res)) != 0)
+ return err;
+ nh->nh_scope = res.scope;
+ nh->nh_oif = FIB_RES_OIF(res);
+ nh->nh_dev = FIB_RES_DEV(res);
+ } else {
+ struct in_device *in_dev;
+
+ if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
+ return -EINVAL;
+
+ in_dev = inetdev_by_index(nh->nh_oif);
+ if (in_dev == NULL)
+ return -ENODEV;
+ if (!(in_dev->dev->flags&IFF_UP))
+ return -ENETDOWN;
+ nh->nh_dev = in_dev->dev;
+ nh->nh_scope = RT_SCOPE_HOST;
+ }
+ return 0;
+}
+
+struct fib_info *
+fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
+ const struct nlmsghdr *nlh, int *errp)
+{
+ int err;
+ struct fib_info *fi = NULL;
+ struct fib_info *ofi;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ int nhs = 1;
+#else
+ const int nhs = 1;
+#endif
+
+ /* Fast check to catch the most weird cases */
+ if (fib_props[r->rtm_type].scope > r->rtm_scope)
+ goto err_inval;
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (rta->rta_mp) {
+ nhs = fib_count_nexthops(rta->rta_mp);
+ if (nhs == 0)
+ goto err_inval;
+ }
+#endif
+
+ fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
+ err = -ENOBUFS;
+ if (fi == NULL)
+ goto failure;
+ memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct fib_nh));
+
+ fi->fib_protocol = r->rtm_protocol;
+ fi->fib_nhs = nhs;
+ fi->fib_flags = r->rtm_flags;
+ if (rta->rta_priority)
+ fi->fib_priority = *rta->rta_priority;
+ if (rta->rta_mx) {
+ int attrlen = RTA_PAYLOAD(rta->rta_mx);
+ struct rtattr *attr = RTA_DATA(rta->rta_mx);
+
+ while (RTA_OK(attr, attrlen)) {
+ unsigned flavor = attr->rta_type;
+ if (flavor) {
+ if (flavor > FIB_MAX_METRICS)
+ goto err_inval;
+ fi->fib_metrics[flavor-1] = *(unsigned*)RTA_DATA(attr);
+ }
+ attr = RTA_NEXT(attr, attrlen);
+ }
+ }
+ if (rta->rta_prefsrc)
+ memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 4);
+
+ if (rta->rta_mp) {
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if ((err = fib_get_nhs(fi, rta->rta_mp, r)) != 0)
+ goto failure;
+ if (rta->rta_oif && fi->fib_nh->nh_oif != *rta->rta_oif)
+ goto err_inval;
+ if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 4))
+ goto err_inval;
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (rta->rta_flow && memcmp(&fi->fib_nh->nh_tclassid, rta->rta_flow, 4))
+ goto err_inval;
+#endif
+#else
+ goto err_inval;
+#endif
+ } else {
+ struct fib_nh *nh = fi->fib_nh;
+ if (rta->rta_oif)
+ nh->nh_oif = *rta->rta_oif;
+ if (rta->rta_gw)
+ memcpy(&nh->nh_gw, rta->rta_gw, 4);
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (rta->rta_flow)
+ memcpy(&nh->nh_tclassid, rta->rta_flow, 4);
+#endif
+ nh->nh_flags = r->rtm_flags;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ nh->nh_weight = 1;
+#endif
+ }
+
+#ifdef CONFIG_IP_ROUTE_NAT
+ if (r->rtm_type == RTN_NAT) {
+ if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
+ goto err_inval;
+ memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 4);
+ goto link_it;
+ }
+#endif
+
+ if (fib_props[r->rtm_type].error) {
+ if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
+ goto err_inval;
+ goto link_it;
+ }
+
+ if (r->rtm_scope > RT_SCOPE_HOST)
+ goto err_inval;
+
+ if (r->rtm_scope == RT_SCOPE_HOST) {
+ struct fib_nh *nh = fi->fib_nh;
+
+ /* Local address is added. */
+ if (nhs != 1 || nh->nh_gw)
+ goto err_inval;
+ nh->nh_scope = RT_SCOPE_NOWHERE;
+ nh->nh_dev = dev_get_by_index(fi->fib_nh->nh_oif);
+ err = -ENODEV;
+ if (nh->nh_dev == NULL)
+ goto failure;
+ } else {
+ change_nexthops(fi) {
+ if ((err = fib_check_nh(r, fi, nh)) != 0)
+ goto failure;
+ } endfor_nexthops(fi)
+ }
+
+ if (fi->fib_prefsrc) {
+ if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
+ memcmp(&fi->fib_prefsrc, rta->rta_dst, 4))
+ if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
+ goto err_inval;
+ }
+
+link_it:
+ if ((ofi = fib_find_info(fi)) != NULL) {
+ kfree(fi);
+ ofi->fib_refcnt++;
+ return ofi;
+ }
+
+ fi->fib_refcnt++;
+ fi->fib_next = fib_info_list;
+ fi->fib_prev = NULL;
+ if (fib_info_list)
+ fib_info_list->fib_prev = fi;
+ fib_info_list = fi;
+ return fi;
+
+err_inval:
+ err = -EINVAL;
+
+failure:
+ *errp = err;
+ if (fi)
+ kfree(fi);
+ return NULL;
+}
+
+int
+fib_semantic_match(int type, struct fib_info *fi, const struct rt_key *key, struct fib_result *res)
+{
+ int err = fib_props[type].error;
+
+ if (err == 0) {
+ if (fi->fib_flags&RTNH_F_DEAD)
+ return 1;
+
+ res->fi = fi;
+
+ switch (type) {
+#ifdef CONFIG_IP_ROUTE_NAT
+ case RTN_NAT:
+ FIB_RES_RESET(*res);
+ return 0;
+#endif
+ case RTN_UNICAST:
+ case RTN_LOCAL:
+ case RTN_BROADCAST:
+ case RTN_ANYCAST:
+ case RTN_MULTICAST:
+ for_nexthops(fi) {
+ if (nh->nh_flags&RTNH_F_DEAD)
+ continue;
+ if (!key->oif || key->oif == nh->nh_oif)
+ break;
+ }
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (nhsel < fi->fib_nhs) {
+ res->nh_sel = nhsel;
+ return 0;
+ }
+#else
+ if (nhsel < 1)
+ return 0;
+#endif
+ endfor_nexthops(fi);
+ return 1;
+ default:
+ printk(KERN_DEBUG "impossible 102\n");
+ return -EINVAL;
+ }
+ }
+ return err;
+}
+
+/* Find appropriate source address to this destination */
+
+u32 __fib_res_prefsrc(struct fib_result *res)
+{
+ return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
+}
+
+#ifdef CONFIG_RTNETLINK
+
+int
+fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+ u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
+ struct fib_info *fi)
+{
+ struct rtmsg *rtm;
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
+ rtm = NLMSG_DATA(nlh);
+ rtm->rtm_family = AF_INET;
+ rtm->rtm_dst_len = dst_len;
+ rtm->rtm_src_len = 0;
+ rtm->rtm_tos = tos;
+ rtm->rtm_table = tb_id;
+ rtm->rtm_type = type;
+ rtm->rtm_flags = fi->fib_flags;
+ rtm->rtm_scope = scope;
+ if (rtm->rtm_dst_len)
+ RTA_PUT(skb, RTA_DST, 4, dst);
+ rtm->rtm_protocol = fi->fib_protocol;
+ if (fi->fib_priority)
+ RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority);
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (fi->fib_nh[0].nh_tclassid)
+ RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid);
+#endif
+ if (fi->fib_mtu || fi->fib_window || fi->fib_rtt) {
+ int i;
+ struct rtattr *mx = (struct rtattr *)skb->tail;
+ RTA_PUT(skb, RTA_METRICS, 0, NULL);
+ for (i=0; i<FIB_MAX_METRICS; i++) {
+ if (fi->fib_metrics[i])
+ RTA_PUT(skb, i+1, sizeof(unsigned), fi->fib_metrics + i);
+ }
+ mx->rta_len = skb->tail - (u8*)mx;
+ }
+ if (fi->fib_prefsrc)
+ RTA_PUT(skb, RTA_PREFSRC, 4, &fi->fib_prefsrc);
+ if (fi->fib_nhs == 1) {
+ if (fi->fib_nh->nh_gw)
+ RTA_PUT(skb, RTA_GATEWAY, 4, &fi->fib_nh->nh_gw);
+ if (fi->fib_nh->nh_oif)
+ RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif);
+ }
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (fi->fib_nhs > 1) {
+ struct rtnexthop *nhp;
+ struct rtattr *mp_head;
+ if (skb_tailroom(skb) <= RTA_SPACE(0))
+ goto rtattr_failure;
+ mp_head = (struct rtattr*)skb_put(skb, RTA_SPACE(0));
+
+ for_nexthops(fi) {
+ if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
+ goto rtattr_failure;
+ nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
+ nhp->rtnh_flags = nh->nh_flags & 0xFF;
+ nhp->rtnh_hops = nh->nh_weight-1;
+ nhp->rtnh_ifindex = nh->nh_oif;
+ if (nh->nh_gw)
+ RTA_PUT(skb, RTA_GATEWAY, 4, &nh->nh_gw);
+ nhp->rtnh_len = skb->tail - (unsigned char*)nhp;
+ } endfor_nexthops(fi);
+ mp_head->rta_type = RTA_MULTIPATH;
+ mp_head->rta_len = skb->tail - (u8*)mp_head;
+ }
+#endif
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+#endif /* CONFIG_RTNETLINK */
+
+#ifndef CONFIG_IP_NOSIOCRT
+
+int
+fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
+ struct kern_rta *rta, struct rtentry *r)
+{
+ int plen;
+ u32 *ptr;
+
+ memset(rtm, 0, sizeof(*rtm));
+ memset(rta, 0, sizeof(*rta));
+
+ if (r->rt_dst.sa_family != AF_INET)
+ return -EAFNOSUPPORT;
+
+ /* Check mask for validity:
+ a) it must be contiguous.
+ b) destination must have all host bits clear.
+ c) if application forgot to set correct family (AF_INET),
+ reject request unless it is absolutely clear i.e.
+ both family and mask are zero.
+ */
+ plen = 32;
+ ptr = &((struct sockaddr_in*)&r->rt_dst)->sin_addr.s_addr;
+ if (!(r->rt_flags&RTF_HOST)) {
+ u32 mask = ((struct sockaddr_in*)&r->rt_genmask)->sin_addr.s_addr;
+ if (r->rt_genmask.sa_family != AF_INET) {
+ if (mask || r->rt_genmask.sa_family)
+ return -EAFNOSUPPORT;
+ }
+ if (bad_mask(mask, *ptr))
+ return -EINVAL;
+ plen = inet_mask_len(mask);
+ }
+
+ nl->nlmsg_flags = NLM_F_REQUEST;
+ nl->nlmsg_pid = 0;
+ nl->nlmsg_seq = 0;
+ nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));
+ if (cmd == SIOCDELRT) {
+ nl->nlmsg_type = RTM_DELROUTE;
+ nl->nlmsg_flags = 0;
+ } else {
+ nl->nlmsg_type = RTM_NEWROUTE;
+ nl->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE;
+ rtm->rtm_protocol = RTPROT_BOOT;
+ }
+
+ rtm->rtm_dst_len = plen;
+ rta->rta_dst = ptr;
+
+ if (r->rt_metric) {
+ *(u32*)&r->rt_pad3 = r->rt_metric - 1;
+ rta->rta_priority = (u32*)&r->rt_pad3;
+ }
+ if (r->rt_flags&RTF_REJECT) {
+ rtm->rtm_scope = RT_SCOPE_HOST;
+ rtm->rtm_type = RTN_UNREACHABLE;
+ return 0;
+ }
+ rtm->rtm_scope = RT_SCOPE_NOWHERE;
+ rtm->rtm_type = RTN_UNICAST;
+
+ if (r->rt_dev) {
+#ifdef CONFIG_IP_ALIAS
+ char *colon;
+#endif
+ struct device *dev;
+ char devname[IFNAMSIZ];
+
+ if (copy_from_user(devname, r->rt_dev, IFNAMSIZ-1))
+ return -EFAULT;
+ devname[IFNAMSIZ-1] = 0;
+#ifdef CONFIG_IP_ALIAS
+ colon = strchr(devname, ':');
+ if (colon)
+ *colon = 0;
+#endif
+ dev = dev_get(devname);
+ if (!dev)
+ return -ENODEV;
+ rta->rta_oif = &dev->ifindex;
+#ifdef CONFIG_IP_ALIAS
+ if (colon) {
+ struct in_ifaddr *ifa;
+ struct in_device *in_dev = dev->ip_ptr;
+ if (!in_dev)
+ return -ENODEV;
+ *colon = ':';
+ for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next)
+ if (strcmp(ifa->ifa_label, devname) == 0)
+ break;
+ if (ifa == NULL)
+ return -ENODEV;
+ rta->rta_prefsrc = &ifa->ifa_local;
+ }
+#endif
+ }
+
+ ptr = &((struct sockaddr_in*)&r->rt_gateway)->sin_addr.s_addr;
+ if (r->rt_gateway.sa_family == AF_INET && *ptr) {
+ rta->rta_gw = ptr;
+ if (r->rt_flags&RTF_GATEWAY && inet_addr_type(*ptr) == RTN_UNICAST)
+ rtm->rtm_scope = RT_SCOPE_UNIVERSE;
+ }
+
+ if (cmd == SIOCDELRT)
+ return 0;
+
+ if (r->rt_flags&RTF_GATEWAY && rta->rta_gw == NULL)
+ return -EINVAL;
+
+ if (rtm->rtm_scope == RT_SCOPE_NOWHERE)
+ rtm->rtm_scope = RT_SCOPE_LINK;
+
+ if (r->rt_flags&(RTF_MTU|RTF_WINDOW|RTF_IRTT)) {
+ struct rtattr *rec;
+ struct rtattr *mx = kmalloc(RTA_LENGTH(3*RTA_LENGTH(4)), GFP_KERNEL);
+ if (mx == NULL)
+ return -ENOMEM;
+ rta->rta_mx = mx;
+ mx->rta_type = RTA_METRICS;
+ mx->rta_len = RTA_LENGTH(0);
+ if (r->rt_flags&RTF_MTU) {
+ rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));
+ rec->rta_type = RTAX_MTU;
+ rec->rta_len = RTA_LENGTH(4);
+ mx->rta_len += RTA_LENGTH(4);
+ *(u32*)RTA_DATA(rec) = r->rt_mtu;
+ }
+ if (r->rt_flags&RTF_WINDOW) {
+ rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));
+ rec->rta_type = RTAX_WINDOW;
+ rec->rta_len = RTA_LENGTH(4);
+ mx->rta_len += RTA_LENGTH(4);
+ *(u32*)RTA_DATA(rec) = r->rt_window;
+ }
+ if (r->rt_flags&RTF_IRTT) {
+ rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));
+ rec->rta_type = RTAX_RTT;
+ rec->rta_len = RTA_LENGTH(4);
+ mx->rta_len += RTA_LENGTH(4);
+ *(u32*)RTA_DATA(rec) = r->rt_irtt;
+ }
+ }
+ return 0;
+}
+
+#endif
+
+/*
+ Update FIB if:
+ - local address disappeared -> we must delete all the entries
+ referring to it.
+ - device went down -> we must shutdown all nexthops going via it.
+ */
+
+int fib_sync_down(u32 local, struct device *dev, int force)
+{
+ int ret = 0;
+ int scope = RT_SCOPE_NOWHERE;
+
+ if (force)
+ scope = -1;
+
+ for_fib_info() {
+ if (local && fi->fib_prefsrc == local) {
+ fi->fib_flags |= RTNH_F_DEAD;
+ ret++;
+ } else if (dev && fi->fib_nhs) {
+ int dead = 0;
+
+ change_nexthops(fi) {
+ if (nh->nh_flags&RTNH_F_DEAD)
+ dead++;
+ else if (nh->nh_dev == dev &&
+ nh->nh_scope != scope) {
+ nh->nh_flags |= RTNH_F_DEAD;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ fi->fib_power -= nh->nh_power;
+ nh->nh_power = 0;
+#endif
+ dead++;
+ }
+ } endfor_nexthops(fi)
+ if (dead == fi->fib_nhs) {
+ fi->fib_flags |= RTNH_F_DEAD;
+ ret++;
+ }
+ }
+ } endfor_fib_info();
+ return ret;
+}
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+
+/*
+ Dead device goes up. We wake up dead nexthops.
+ It takes sense only on multipath routes.
+ */
+
+int fib_sync_up(struct device *dev)
+{
+ int ret = 0;
+
+ if (!(dev->flags&IFF_UP))
+ return 0;
+
+ for_fib_info() {
+ int alive = 0;
+
+ change_nexthops(fi) {
+ if (!(nh->nh_flags&RTNH_F_DEAD)) {
+ alive++;
+ continue;
+ }
+ if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
+ continue;
+ if (nh->nh_dev != dev || dev->ip_ptr == NULL)
+ continue;
+ alive++;
+ nh->nh_power = 0;
+ nh->nh_flags &= ~RTNH_F_DEAD;
+ } endfor_nexthops(fi)
+
+ if (alive == fi->fib_nhs) {
+ fi->fib_flags &= ~RTNH_F_DEAD;
+ ret++;
+ }
+ } endfor_fib_info();
+ return ret;
+}
+
+/*
+ The algorithm is suboptimal, but it provides really
+ fair weighted route distribution.
+ */
+
+void fib_select_multipath(const struct rt_key *key, struct fib_result *res)
+{
+ struct fib_info *fi = res->fi;
+ int w;
+
+ if (fi->fib_power <= 0) {
+ int power = 0;
+ change_nexthops(fi) {
+ if (!(nh->nh_flags&RTNH_F_DEAD)) {
+ power += nh->nh_weight;
+ nh->nh_power = nh->nh_weight;
+ }
+ } endfor_nexthops(fi);
+ fi->fib_power = power;
+#if 1
+ if (power <= 0) {
+ printk(KERN_CRIT "impossible 777\n");
+ return;
+ }
+#endif
+ }
+
+
+ /* w should be random number [0..fi->fib_power-1],
+ it is pretty bad approximation.
+ */
+
+ w = jiffies % fi->fib_power;
+
+ change_nexthops(fi) {
+ if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) {
+ if ((w -= nh->nh_power) <= 0) {
+ nh->nh_power--;
+ fi->fib_power--;
+ res->nh_sel = nhsel;
+ return;
+ }
+ }
+ } endfor_nexthops(fi);
+
+#if 1
+ printk(KERN_CRIT "impossible 888\n");
+#endif
+ return;
+}
+#endif
+
+
+#ifdef CONFIG_PROC_FS
+
+static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi)
+{
+ static unsigned type2flags[RTN_MAX+1] = {
+ 0, 0, 0, 0, 0, 0, 0, RTF_REJECT, RTF_REJECT, 0, 0, 0
+ };
+ unsigned flags = type2flags[type];
+
+ if (fi && fi->fib_nh->nh_gw)
+ flags |= RTF_GATEWAY;
+ if (mask == 0xFFFFFFFF)
+ flags |= RTF_HOST;
+ if (!dead)
+ flags |= RTF_UP;
+ return flags;
+}
+
+void fib_node_get_info(int type, int dead, struct fib_info *fi, u32 prefix, u32 mask, char *buffer)
+{
+ int len;
+ unsigned flags = fib_flag_trans(type, dead, mask, fi);
+
+ if (fi) {
+ len = sprintf(buffer, "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+ fi->fib_dev ? fi->fib_dev->name : "*", prefix,
+ fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
+ mask, fi->fib_mtu, fi->fib_window, fi->fib_rtt);
+ } else {
+ len = sprintf(buffer, "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+ prefix, 0,
+ flags, 0, 0, 0,
+ mask, 0, 0, 0);
+ }
+ memset(buffer+len, ' ', 127-len);
+ buffer[127] = '\n';
+}
+
+#endif
diff --git a/pfinet/linux-src/net/ipv4/icmp.c b/pfinet/linux-src/net/ipv4/icmp.c
new file mode 100644
index 00000000..34b48a93
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/icmp.c
@@ -0,0 +1,1155 @@
+/*
+ * NET3: Implementation of the ICMP protocol layer.
+ *
+ * Alan Cox, <alan@redhat.com>
+ *
+ * Version: $Id: icmp.c,v 1.52.2.2 1999/06/20 21:27:39 davem Exp $
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Some of the function names and the icmp unreach table for this
+ * module were derived from [icmp.c 1.0.11 06/02/93] by
+ * Ross Biro, Fred N. van Kempen, Mark Evans, Alan Cox, Gerhard Koerting.
+ * Other than that this module is a complete rewrite.
+ *
+ * Fixes:
+ * Mike Shaver : RFC1122 checks.
+ * Alan Cox : Multicast ping reply as self.
+ * Alan Cox : Fix atomicity lockup in ip_build_xmit
+ * call.
+ * Alan Cox : Added 216,128 byte paths to the MTU
+ * code.
+ * Martin Mares : RFC1812 checks.
+ * Martin Mares : Can be configured to follow redirects
+ * if acting as a router _without_ a
+ * routing protocol (RFC 1812).
+ * Martin Mares : Echo requests may be configured to
+ * be ignored (RFC 1812).
+ * Martin Mares : Limitation of ICMP error message
+ * transmit rate (RFC 1812).
+ * Martin Mares : TOS and Precedence set correctly
+ * (RFC 1812).
+ * Martin Mares : Now copying as much data from the
+ * original packet as we can without
+ * exceeding 576 bytes (RFC 1812).
+ * Willy Konynenberg : Transparent proxying support.
+ * Keith Owens : RFC1191 correction for 4.2BSD based
+ * path MTU bug.
+ * Thomas Quinot : ICMP Dest Unreach codes up to 15 are
+ * valid (RFC 1812).
+ * Andi Kleen : Check all packet lengths properly
+ * and moved all kfree_skb() up to
+ * icmp_rcv.
+ * Andi Kleen : Move the rate limit bookkeeping
+ * into the dest entry and use a token
+ * bucket filter (thanks to ANK). Make
+ * the rates sysctl configurable.
+ * Yu Tianli : Fixed two ugly bugs in icmp_send
+ * - IP option length was accounted wrongly
+ * - ICMP header length was not accounted at all.
+ * Tristan Greaves : Added sysctl option to ignore bogus broadcast
+ * responses from broken routers.
+ *
+ * To Fix:
+ *
+ * - Should use skb_pull() instead of all the manual checking.
+ * This would also greatly simply some upper layer error handlers. --AK
+ *
+ * RFC1122 (Host Requirements -- Comm. Layer) Status:
+ * (boy, are there a lot of rules for ICMP)
+ * 3.2.2 (Generic ICMP stuff)
+ * MUST discard messages of unknown type. (OK)
+ * MUST copy at least the first 8 bytes from the offending packet
+ * when sending ICMP errors. (OBSOLETE -- see RFC1812)
+ * MUST pass received ICMP errors up to protocol level. (OK)
+ * SHOULD send ICMP errors with TOS == 0. (OBSOLETE -- see RFC1812)
+ * MUST NOT send ICMP errors in reply to:
+ * ICMP errors (OK)
+ * Broadcast/multicast datagrams (OK)
+ * MAC broadcasts (OK)
+ * Non-initial fragments (OK)
+ * Datagram with a source address that isn't a single host. (OK)
+ * 3.2.2.1 (Destination Unreachable)
+ * All the rules govern the IP layer, and are dealt with in ip.c, not here.
+ * 3.2.2.2 (Redirect)
+ * Host SHOULD NOT send ICMP_REDIRECTs. (OK)
+ * MUST update routing table in response to host or network redirects.
+ * (host OK, network OBSOLETE)
+ * SHOULD drop redirects if they're not from directly connected gateway
+ * (OK -- we drop it if it's not from our old gateway, which is close
+ * enough)
+ * 3.2.2.3 (Source Quench)
+ * MUST pass incoming SOURCE_QUENCHs to transport layer (OK)
+ * Other requirements are dealt with at the transport layer.
+ * 3.2.2.4 (Time Exceeded)
+ * MUST pass TIME_EXCEEDED to transport layer (OK)
+ * Other requirements dealt with at IP (generating TIME_EXCEEDED).
+ * 3.2.2.5 (Parameter Problem)
+ * SHOULD generate these (OK)
+ * MUST pass received PARAMPROBLEM to transport layer (NOT YET)
+ * [Solaris 2.X seems to assert EPROTO when this occurs] -- AC
+ * 3.2.2.6 (Echo Request/Reply)
+ * MUST reply to ECHO_REQUEST, and give app to do ECHO stuff (OK, OK)
+ * MAY discard broadcast ECHO_REQUESTs. (Configurable with a sysctl.)
+ * MUST reply using same source address as the request was sent to.
+ * We're OK for unicast ECHOs, and it doesn't say anything about
+ * how to handle broadcast ones, since it's optional.
+ * MUST copy data from REQUEST to REPLY (OK)
+ * unless it would require illegal fragmentation (OK)
+ * MUST pass REPLYs to transport/user layer (OK)
+ * MUST use any provided source route (reversed) for REPLY. (NOT YET)
+ * 3.2.2.7 (Information Request/Reply)
+ * MUST NOT implement this. (I guess that means silently discard...?) (OK)
+ * 3.2.2.8 (Timestamp Request/Reply)
+ * MAY implement (OK)
+ * SHOULD be in-kernel for "minimum variability" (OK)
+ * MAY discard broadcast REQUESTs. (OK, but see source for inconsistency)
+ * MUST reply using same source address as the request was sent to. (OK)
+ * MUST reverse source route, as per ECHO (NOT YET)
+ * MUST pass REPLYs to transport/user layer (requires RAW, just like
+ * ECHO) (OK)
+ * MUST update clock for timestamp at least 15 times/sec (OK)
+ * MUST be "correct within a few minutes" (OK)
+ * 3.2.2.9 (Address Mask Request/Reply)
+ * MAY implement (OK)
+ * MUST send a broadcast REQUEST if using this system to set netmask
+ * (OK... we don't use it)
+ * MUST discard received REPLYs if not using this system (OK)
+ * MUST NOT send replies unless specifically made agent for this sort
+ * of thing. (OK)
+ *
+ *
+ * RFC 1812 (IPv4 Router Requirements) Status (even longer):
+ * 4.3.2.1 (Unknown Message Types)
+ * MUST pass messages of unknown type to ICMP user iface or silently discard
+ * them (OK)
+ * 4.3.2.2 (ICMP Message TTL)
+ * MUST initialize TTL when originating an ICMP message (OK)
+ * 4.3.2.3 (Original Message Header)
+ * SHOULD copy as much data from the offending packet as possible without
+ * the length of the ICMP datagram exceeding 576 bytes (OK)
+ * MUST leave original IP header of the offending packet, but we're not
+ * required to undo modifications made (OK)
+ * 4.3.2.4 (Original Message Source Address)
+ * MUST use one of addresses for the interface the orig. packet arrived as
+ * source address (OK)
+ * 4.3.2.5 (TOS and Precedence)
+ * SHOULD leave TOS set to the same value unless the packet would be
+ * discarded for that reason (OK)
+ * MUST use TOS=0 if not possible to leave original value (OK)
+ * MUST leave IP Precedence for Source Quench messages (OK -- not sent
+ * at all)
+ * SHOULD use IP Precedence = 6 (Internetwork Control) or 7 (Network Control)
+ * for all other error messages (OK, we use 6)
+ * MAY allow configuration of IP Precedence (OK -- not done)
+ * MUST leave IP Precedence and TOS for reply messages (OK)
+ * 4.3.2.6 (Source Route)
+ * SHOULD use reverse source route UNLESS sending Parameter Problem on source
+ * routing and UNLESS the packet would be immediately discarded (NOT YET)
+ * 4.3.2.7 (When Not to Send ICMP Errors)
+ * MUST NOT send ICMP errors in reply to:
+ * ICMP errors (OK)
+ * Packets failing IP header validation tests unless otherwise noted (OK)
+ * Broadcast/multicast datagrams (OK)
+ * MAC broadcasts (OK)
+ * Non-initial fragments (OK)
+ * Datagram with a source address that isn't a single host. (OK)
+ * 4.3.2.8 (Rate Limiting)
+ * SHOULD be able to limit error message rate (OK)
+ * SHOULD allow setting of rate limits (OK, in the source)
+ * 4.3.3.1 (Destination Unreachable)
+ * All the rules govern the IP layer, and are dealt with in ip.c, not here.
+ * 4.3.3.2 (Redirect)
+ * MAY ignore ICMP Redirects if running a routing protocol or if forwarding
+ * is enabled on the interface (OK -- ignores)
+ * 4.3.3.3 (Source Quench)
+ * SHOULD NOT originate SQ messages (OK)
+ * MUST be able to limit SQ rate if originates them (OK as we don't
+ * send them)
+ * MAY ignore SQ messages it receives (OK -- we don't)
+ * 4.3.3.4 (Time Exceeded)
+ * Requirements dealt with at IP (generating TIME_EXCEEDED).
+ * 4.3.3.5 (Parameter Problem)
+ * MUST generate these for all errors not covered by other messages (OK)
+ * MUST include original value of the value pointed by (OK)
+ * 4.3.3.6 (Echo Request)
+ * MUST implement echo server function (OK)
+ * MUST process at ER of at least max(576, MTU) (OK)
+ * MAY reject broadcast/multicast ER's (We don't, but that's OK)
+ * SHOULD have a config option for silently ignoring ER's (OK)
+ * MUST have a default value for the above switch = NO (OK)
+ * MUST have application layer interface for Echo Request/Reply (OK)
+ * MUST reply using same source address as the request was sent to.
+ * We're OK for unicast ECHOs, and it doesn't say anything about
+ * how to handle broadcast ones, since it's optional.
+ * MUST copy data from Request to Reply (OK)
+ * SHOULD update Record Route / Timestamp options (??)
+ * MUST use reversed Source Route for Reply if possible (NOT YET)
+ * 4.3.3.7 (Information Request/Reply)
+ * SHOULD NOT originate or respond to these (OK)
+ * 4.3.3.8 (Timestamp / Timestamp Reply)
+ * MAY implement (OK)
+ * MUST reply to every Timestamp message received (OK)
+ * MAY discard broadcast REQUESTs. (OK, but see source for inconsistency)
+ * MUST reply using same source address as the request was sent to. (OK)
+ * MUST use reversed Source Route if possible (NOT YET)
+ * SHOULD update Record Route / Timestamp options (??)
+ * MUST pass REPLYs to transport/user layer (requires RAW, just like
+ * ECHO) (OK)
+ * MUST update clock for timestamp at least 16 times/sec (OK)
+ * MUST be "correct within a few minutes" (OK)
+ * 4.3.3.9 (Address Mask Request/Reply)
+ * MUST have support for receiving AMRq and responding with AMRe (OK,
+ * but only as a compile-time option)
+ * SHOULD have option for each interface for AMRe's, MUST default to
+ * NO (NOT YET)
+ * MUST NOT reply to AMRq before knows the correct AM (OK)
+ * MUST NOT respond to AMRq with source address 0.0.0.0 on physical
+ * interfaces having multiple logical i-faces with different masks
+ * (NOT YET)
+ * SHOULD examine all AMRe's it receives and check them (NOT YET)
+ * SHOULD log invalid AMRe's (AM+sender) (NOT YET)
+ * MUST NOT use contents of AMRe to determine correct AM (OK)
+ * MAY broadcast AMRe's after having configured address masks (OK -- doesn't)
+ * MUST NOT do broadcast AMRe's if not set by extra option (OK, no option)
+ * MUST use the { <NetPrefix>, -1 } form of broadcast addresses (OK)
+ * 4.3.3.10 (Router Advertisement and Solicitations)
+ * MUST support router part of Router Discovery Protocol on all networks we
+ * support broadcast or multicast addressing. (OK -- done by gated)
+ * MUST have all config parameters with the respective defaults (OK)
+ * 5.2.7.1 (Destination Unreachable)
+ * MUST generate DU's (OK)
+ * SHOULD choose a best-match response code (OK)
+ * SHOULD NOT generate Host Isolated codes (OK)
+ * SHOULD use Communication Administratively Prohibited when administratively
+ * filtering packets (NOT YET -- bug-to-bug compatibility)
+ * MAY include config option for not generating the above and silently
+ * discard the packets instead (OK)
+ * MAY include config option for not generating Precedence Violation and
+ * Precedence Cutoff messages (OK as we don't generate them at all)
+ * MUST use Host Unreachable or Dest. Host Unknown codes whenever other hosts
+ * on the same network might be reachable (OK -- no net unreach's at all)
+ * MUST use new form of Fragmentation Needed and DF Set messages (OK)
+ * 5.2.7.2 (Redirect)
+ * MUST NOT generate network redirects (OK)
+ * MUST be able to generate host redirects (OK)
+ * SHOULD be able to generate Host+TOS redirects (NO as we don't use TOS)
+ * MUST have an option to use Host redirects instead of Host+TOS ones (OK as
+ * no Host+TOS Redirects are used)
+ * MUST NOT generate redirects unless forwarding to the same i-face and the
+ * dest. address is on the same subnet as the src. address and no source
+ * routing is in use. (OK)
+ * MUST NOT follow redirects when using a routing protocol (OK)
+ * MAY use redirects if not using a routing protocol (OK, compile-time option)
+ * MUST comply to Host Requirements when not acting as a router (OK)
+ * 5.2.7.3 (Time Exceeded)
+ * MUST generate Time Exceeded Code 0 when discarding packet due to TTL=0 (OK)
+ * MAY have a per-interface option to disable origination of TE messages, but
+ * it MUST default to "originate" (OK -- we don't support it)
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/protocol.h>
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/raw.h>
+#include <net/snmp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <net/checksum.h>
+
+#ifdef CONFIG_IP_MASQUERADE
+#include <net/ip_masq.h>
+#endif
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+/*
+ * Statistics
+ */
+
+struct icmp_mib icmp_statistics;
+
+/* An array of errno for error messages from dest unreach. */
+/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOS_UNREACH and SR_FAIELD MUST be considered 'transient errs'. */
+
+struct icmp_err icmp_err_convert[] = {
+ { ENETUNREACH, 0 }, /* ICMP_NET_UNREACH */
+ { EHOSTUNREACH, 0 }, /* ICMP_HOST_UNREACH */
+ { ENOPROTOOPT, 1 }, /* ICMP_PROT_UNREACH */
+ { ECONNREFUSED, 1 }, /* ICMP_PORT_UNREACH */
+ { EMSGSIZE, 0 }, /* ICMP_FRAG_NEEDED */
+ { EOPNOTSUPP, 0 }, /* ICMP_SR_FAILED */
+ { ENETUNREACH, 1 }, /* ICMP_NET_UNKNOWN */
+ { EHOSTDOWN, 1 }, /* ICMP_HOST_UNKNOWN */
+ { ENONET, 1 }, /* ICMP_HOST_ISOLATED */
+ { ENETUNREACH, 1 }, /* ICMP_NET_ANO */
+ { EHOSTUNREACH, 1 }, /* ICMP_HOST_ANO */
+ { ENETUNREACH, 0 }, /* ICMP_NET_UNR_TOS */
+ { EHOSTUNREACH, 0 }, /* ICMP_HOST_UNR_TOS */
+ { EHOSTUNREACH, 1 }, /* ICMP_PKT_FILTERED */
+ { EHOSTUNREACH, 1 }, /* ICMP_PREC_VIOLATION */
+ { EHOSTUNREACH, 1 } /* ICMP_PREC_CUTOFF */
+};
+
+/* Control parameters for ECHO relies. */
+int sysctl_icmp_echo_ignore_all = 0;
+int sysctl_icmp_echo_ignore_broadcasts = 0;
+
+/* Control parameter - ignore bogus broadcast responses? */
+int sysctl_icmp_ignore_bogus_error_responses =0;
+
+/*
+ * ICMP control array. This specifies what to do with each ICMP.
+ */
+
+struct icmp_control
+{
+ unsigned long *output; /* Address to increment on output */
+ unsigned long *input; /* Address to increment on input */
+ void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, int len);
+ short error; /* This ICMP is classed as an error message */
+ int *timeout; /* Rate limit */
+};
+
+static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
+
+/*
+ * Build xmit assembly blocks
+ */
+
+struct icmp_bxm
+{
+ void *data_ptr;
+ int data_len;
+ struct icmphdr icmph;
+ unsigned long csum;
+ struct ip_options replyopts;
+ unsigned char optbuf[40];
+};
+
+/*
+ * The ICMP socket. This is the most convenient way to flow control
+ * our ICMP output as well as maintain a clean interface throughout
+ * all layers. All Socketless IP sends will soon be gone.
+ */
+
+struct inode icmp_inode;
+struct socket *icmp_socket=&icmp_inode.u.socket_i;
+
+/*
+ * Send an ICMP frame.
+ */
+
+/*
+ * Check transmit rate limitation for given message.
+ * The rate information is held in the destination cache now.
+ * This function is generic and could be used for other purposes
+ * too. It uses a Token bucket filter as suggested by Alexey Kuznetsov.
+ *
+ * Note that the same dst_entry fields are modified by functions in
+ * route.c too, but these work for packet destinations while xrlim_allow
+ * works for icmp destinations. This means the rate limiting information
+ * for one "ip object" is shared.
+ *
+ * Note that the same dst_entry fields are modified by functions in
+ * route.c too, but these work for packet destinations while xrlim_allow
+ * works for icmp destinations. This means the rate limiting information
+ * for one "ip object" is shared - and these ICMPs are twice limited:
+ * by source and by destination.
+ *
+ * RFC 1812: 4.3.2.8 SHOULD be able to limit error message rate
+ * SHOULD allow setting of rate limits
+ *
+ * Shared between ICMPv4 and ICMPv6.
+ */
+#define XRLIM_BURST_FACTOR 6
+int xrlim_allow(struct dst_entry *dst, int timeout)
+{
+ unsigned long now;
+
+ now = jiffies;
+ dst->rate_tokens += now - dst->rate_last;
+ dst->rate_last = now;
+ if (dst->rate_tokens > XRLIM_BURST_FACTOR*timeout)
+ dst->rate_tokens = XRLIM_BURST_FACTOR*timeout;
+ if (dst->rate_tokens >= timeout) {
+ dst->rate_tokens -= timeout;
+ return 1;
+ }
+ return 0;
+}
+
+static inline int icmpv4_xrlim_allow(struct rtable *rt, int type, int code)
+{
+ struct dst_entry *dst = &rt->u.dst;
+
+ if (type > NR_ICMP_TYPES || !icmp_pointers[type].timeout)
+ return 1;
+
+ /* Don't limit PMTU discovery. */
+ if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
+ return 1;
+
+ /* Redirect has its own rate limit mechanism */
+ if (type == ICMP_REDIRECT)
+ return 1;
+
+ /* No rate limit on loopback */
+ if (dst->dev && (dst->dev->flags&IFF_LOOPBACK))
+ return 1;
+
+ return xrlim_allow(dst, *(icmp_pointers[type].timeout));
+}
+
+/*
+ * Maintain the counters used in the SNMP statistics for outgoing ICMP
+ */
+
+static void icmp_out_count(int type)
+{
+ if (type>NR_ICMP_TYPES)
+ return;
+ (*icmp_pointers[type].output)++;
+ icmp_statistics.IcmpOutMsgs++;
+}
+
+/*
+ * Checksum each fragment, and on the first include the headers and final checksum.
+ */
+
+static int icmp_glue_bits(const void *p, char *to, unsigned int offset, unsigned int fraglen)
+{
+ struct icmp_bxm *icmp_param = (struct icmp_bxm *)p;
+ struct icmphdr *icmph;
+ unsigned long csum;
+
+ if (offset) {
+ icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr),
+ to, fraglen,icmp_param->csum);
+ return 0;
+ }
+
+ /*
+ * First fragment includes header. Note that we've done
+ * the other fragments first, so that we get the checksum
+ * for the whole packet here.
+ */
+ csum = csum_partial_copy((void *)&icmp_param->icmph,
+ to, sizeof(struct icmphdr),
+ icmp_param->csum);
+ csum = csum_partial_copy(icmp_param->data_ptr,
+ to+sizeof(struct icmphdr),
+ fraglen-sizeof(struct icmphdr), csum);
+ icmph=(struct icmphdr *)to;
+ icmph->checksum = csum_fold(csum);
+ return 0;
+}
+
+/*
+ * Driving logic for building and sending ICMP messages.
+ */
+
+static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
+{
+ struct sock *sk=icmp_socket->sk;
+ struct ipcm_cookie ipc;
+ struct rtable *rt = (struct rtable*)skb->dst;
+ u32 daddr;
+
+ if (ip_options_echo(&icmp_param->replyopts, skb))
+ return;
+
+ icmp_param->icmph.checksum=0;
+ icmp_param->csum=0;
+ icmp_out_count(icmp_param->icmph.type);
+
+ sk->ip_tos = skb->nh.iph->tos;
+ daddr = ipc.addr = rt->rt_src;
+ ipc.opt = &icmp_param->replyopts;
+ if (ipc.opt->srr)
+ daddr = icmp_param->replyopts.faddr;
+ if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0))
+ return;
+ ip_build_xmit(sk, icmp_glue_bits, icmp_param,
+ icmp_param->data_len+sizeof(struct icmphdr),
+ &ipc, rt, MSG_DONTWAIT);
+ ip_rt_put(rt);
+}
+
+
+/*
+ * Send an ICMP message in response to a situation
+ *
+ * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we do).
+ * MUST NOT change this header information.
+ * MUST NOT reply to a multicast/broadcast IP address.
+ * MUST NOT reply to a multicast/broadcast MAC address.
+ * MUST reply to only the first fragment.
+ */
+
+void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info)
+{
+ struct iphdr *iph;
+ struct icmphdr *icmph;
+ int room;
+ struct icmp_bxm icmp_param;
+ struct rtable *rt = (struct rtable*)skb_in->dst;
+ struct ipcm_cookie ipc;
+ u32 saddr;
+ u8 tos;
+
+ /*
+ * Find the original header
+ */
+
+ iph = skb_in->nh.iph;
+
+ /*
+ * No replies to physical multicast/broadcast
+ */
+
+ if (skb_in->pkt_type!=PACKET_HOST)
+ return;
+
+ /*
+ * Now check at the protocol level
+ */
+ if (!rt) {
+#ifndef CONFIG_IP_ALWAYS_DEFRAG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "icmp_send: destinationless packet\n");
+#endif
+ return;
+ }
+ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
+ return;
+
+
+ /*
+ * Only reply to fragment 0. We byte re-order the constant
+ * mask for efficiency.
+ */
+
+ if (iph->frag_off&htons(IP_OFFSET))
+ return;
+
+ /*
+ * If we send an ICMP error to an ICMP error a mess would result..
+ */
+
+ if (icmp_pointers[type].error) {
+ /*
+ * We are an error, check if we are replying to an ICMP error
+ */
+
+ if (iph->protocol==IPPROTO_ICMP) {
+ icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
+ /*
+ * Assume any unknown ICMP type is an error. This isn't
+ * specified by the RFC, but think about it..
+ */
+ if (icmph->type>NR_ICMP_TYPES || icmp_pointers[icmph->type].error)
+ return;
+ }
+ }
+
+
+ /*
+ * Construct source address and options.
+ */
+
+#ifdef CONFIG_IP_ROUTE_NAT
+ /*
+ * Restore original addresses if packet has been translated.
+ */
+ if (rt->rt_flags&RTCF_NAT && IPCB(skb_in)->flags&IPSKB_TRANSLATED) {
+ iph->daddr = rt->key.dst;
+ iph->saddr = rt->key.src;
+ }
+#endif
+#ifdef CONFIG_IP_MASQUERADE
+ if (type==ICMP_DEST_UNREACH && IPCB(skb_in)->flags&IPSKB_MASQUERADED) {
+ ip_fw_unmasq_icmp(skb_in);
+ }
+#endif
+
+ saddr = iph->daddr;
+ if (!(rt->rt_flags & RTCF_LOCAL))
+ saddr = 0;
+
+ tos = icmp_pointers[type].error ?
+ ((iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL) :
+ iph->tos;
+
+ /* XXX: use a more aggressive expire for routes created by
+ * this call (not longer than the rate limit timeout).
+ * It could be also worthwhile to not put them into ipv4
+ * fast routing cache at first. Otherwise an attacker can
+ * grow the routing table.
+ */
+ if (ip_route_output(&rt, iph->saddr, saddr, RT_TOS(tos), 0))
+ return;
+
+ if (ip_options_echo(&icmp_param.replyopts, skb_in))
+ goto ende;
+
+
+ /*
+ * Prepare data for ICMP header.
+ */
+
+ icmp_param.icmph.type=type;
+ icmp_param.icmph.code=code;
+ icmp_param.icmph.un.gateway = info;
+ icmp_param.icmph.checksum=0;
+ icmp_param.csum=0;
+ icmp_param.data_ptr=iph;
+ icmp_out_count(icmp_param.icmph.type);
+ icmp_socket->sk->ip_tos = tos;
+ ipc.addr = iph->saddr;
+ ipc.opt = &icmp_param.replyopts;
+ if (icmp_param.replyopts.srr) {
+ ip_rt_put(rt);
+ if (ip_route_output(&rt, icmp_param.replyopts.faddr, saddr, RT_TOS(tos), 0))
+ return;
+ }
+
+ if (!icmpv4_xrlim_allow(rt, type, code))
+ goto ende;
+
+ /* RFC says return as much as we can without exceeding 576 bytes. */
+
+ room = rt->u.dst.pmtu;
+ if (room > 576)
+ room = 576;
+ room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen;
+ room -= sizeof(struct icmphdr);
+
+ icmp_param.data_len=(iph->ihl<<2)+skb_in->len;
+ if (icmp_param.data_len > room)
+ icmp_param.data_len = room;
+
+ ip_build_xmit(icmp_socket->sk, icmp_glue_bits, &icmp_param,
+ icmp_param.data_len+sizeof(struct icmphdr),
+ &ipc, rt, MSG_DONTWAIT);
+
+ende:
+ ip_rt_put(rt);
+}
+
+
+/*
+ * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH.
+ */
+
+static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len)
+{
+ struct iphdr *iph;
+ int hash;
+ struct inet_protocol *ipprot;
+ unsigned char *dp;
+ struct sock *raw_sk;
+
+ /*
+ * Incomplete header ?
+ * Only checks for the IP header, there should be an
+ * additional check for longer headers in upper levels.
+ */
+
+ if(len<sizeof(struct iphdr)) {
+ icmp_statistics.IcmpInErrors++;
+ return;
+ }
+
+ iph = (struct iphdr *) (icmph + 1);
+ dp = (unsigned char*)iph;
+
+ if(icmph->type==ICMP_DEST_UNREACH) {
+ switch(icmph->code & 15) {
+ case ICMP_NET_UNREACH:
+ break;
+ case ICMP_HOST_UNREACH:
+ break;
+ case ICMP_PROT_UNREACH:
+ break;
+ case ICMP_PORT_UNREACH:
+ break;
+ case ICMP_FRAG_NEEDED:
+ if (ipv4_config.no_pmtu_disc) {
+ if (net_ratelimit())
+ printk(KERN_INFO "ICMP: %d.%d.%d.%d: fragmentation needed and DF set.\n",
+ NIPQUAD(iph->daddr));
+ } else {
+ unsigned short new_mtu;
+ new_mtu = ip_rt_frag_needed(iph, ntohs(icmph->un.frag.mtu));
+ if (!new_mtu)
+ return;
+ icmph->un.frag.mtu = htons(new_mtu);
+ }
+ break;
+ case ICMP_SR_FAILED:
+ if (net_ratelimit())
+ printk(KERN_INFO "ICMP: %d.%d.%d.%d: Source Route Failed.\n", NIPQUAD(iph->daddr));
+ break;
+ default:
+ break;
+ }
+ if (icmph->code>NR_ICMP_UNREACH)
+ return;
+ }
+
+ /*
+ * Throw it at our lower layers
+ *
+ * RFC 1122: 3.2.2 MUST extract the protocol ID from the passed header.
+ * RFC 1122: 3.2.2.1 MUST pass ICMP unreach messages to the transport layer.
+ * RFC 1122: 3.2.2.2 MUST pass ICMP time expired messages to transport layer.
+ */
+
+ /*
+ * Check the other end isnt violating RFC 1122. Some routers send
+ * bogus responses to broadcast frames. If you see this message
+ * first check your netmask matches at both ends, if it does then
+ * get the other vendor to fix their kit.
+ */
+
+ if (!sysctl_icmp_ignore_bogus_error_responses)
+ {
+
+ if (inet_addr_type(iph->daddr) == RTN_BROADCAST)
+ {
+ if (net_ratelimit())
+ printk(KERN_WARNING "%d.%d.%d.%d sent an invalid ICMP error to a broadcast.\n",
+ NIPQUAD(skb->nh.iph->saddr));
+ return;
+ }
+ }
+
+ /*
+ * Deliver ICMP message to raw sockets. Pretty useless feature?
+ */
+
+ /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */
+ hash = iph->protocol & (MAX_INET_PROTOS - 1);
+ if ((raw_sk = raw_v4_htable[hash]) != NULL)
+ {
+ while ((raw_sk = raw_v4_lookup(raw_sk, iph->protocol, iph->saddr,
+ iph->daddr, skb->dev->ifindex)) != NULL) {
+ raw_err(raw_sk, skb);
+ raw_sk = raw_sk->next;
+ }
+ }
+
+ /*
+ * This can't change while we are doing it.
+ */
+
+ ipprot = (struct inet_protocol *) inet_protos[hash];
+ while(ipprot != NULL) {
+ struct inet_protocol *nextip;
+
+ nextip = (struct inet_protocol *) ipprot->next;
+
+ /*
+ * Pass it off to everyone who wants it.
+ */
+
+ /* RFC1122: OK. Passes appropriate ICMP errors to the */
+ /* appropriate protocol layer (MUST), as per 3.2.2. */
+
+ if (iph->protocol == ipprot->protocol && ipprot->err_handler)
+ ipprot->err_handler(skb, dp, len);
+
+ ipprot = nextip;
+ }
+}
+
+
+/*
+ * Handle ICMP_REDIRECT.
+ */
+
+static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, int len)
+{
+ struct iphdr *iph;
+ unsigned long ip;
+
+ if (len < sizeof(struct iphdr)) {
+ icmp_statistics.IcmpInErrors++;
+ return;
+ }
+
+ /*
+ * Get the copied header of the packet that caused the redirect
+ */
+
+ iph = (struct iphdr *) (icmph + 1);
+ ip = iph->daddr;
+
+ switch(icmph->code & 7) {
+ case ICMP_REDIR_NET:
+ case ICMP_REDIR_NETTOS:
+ /*
+ * As per RFC recommendations now handle it as
+ * a host redirect.
+ */
+
+ case ICMP_REDIR_HOST:
+ case ICMP_REDIR_HOSTTOS:
+ ip_rt_redirect(skb->nh.iph->saddr, ip, icmph->un.gateway, iph->saddr, iph->tos, skb->dev);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Handle ICMP_ECHO ("ping") requests.
+ *
+ * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo requests.
+ * RFC 1122: 3.2.2.6 Data received in the ICMP_ECHO request MUST be included in the reply.
+ * RFC 1812: 4.3.3.6 SHOULD have a config option for silently ignoring echo requests, MUST have default=NOT.
+ * See also WRT handling of options once they are done and working.
+ */
+
+static void icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, int len)
+{
+ if (!sysctl_icmp_echo_ignore_all) {
+ struct icmp_bxm icmp_param;
+
+ icmp_param.icmph=*icmph;
+ icmp_param.icmph.type=ICMP_ECHOREPLY;
+ icmp_param.data_ptr=(icmph+1);
+ icmp_param.data_len=len;
+ icmp_reply(&icmp_param, skb);
+ }
+}
+
+/*
+ * Handle ICMP Timestamp requests.
+ * RFC 1122: 3.2.2.8 MAY implement ICMP timestamp requests.
+ * SHOULD be in the kernel for minimum random latency.
+ * MUST be accurate to a few minutes.
+ * MUST be updated at least at 15Hz.
+ */
+
+static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, int len)
+{
+ struct timeval tv;
+ __u32 times[3]; /* So the new timestamp works on ALPHA's.. */
+ struct icmp_bxm icmp_param;
+
+ /*
+ * Too short.
+ */
+
+ if(len<12) {
+ icmp_statistics.IcmpInErrors++;
+ return;
+ }
+
+ /*
+ * Fill in the current time as ms since midnight UT:
+ */
+
+ do_gettimeofday(&tv);
+ times[1] = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
+ times[2] = times[1];
+ memcpy((void *)&times[0], icmph+1, 4); /* Incoming stamp */
+ icmp_param.icmph=*icmph;
+ icmp_param.icmph.type=ICMP_TIMESTAMPREPLY;
+ icmp_param.icmph.code=0;
+ icmp_param.data_ptr=&times;
+ icmp_param.data_len=12;
+ icmp_reply(&icmp_param, skb);
+}
+
+
+/*
+ * Handle ICMP_ADDRESS_MASK requests. (RFC950)
+ *
+ * RFC1122 (3.2.2.9). A host MUST only send replies to
+ * ADDRESS_MASK requests if it's been configured as an address mask
+ * agent. Receiving a request doesn't constitute implicit permission to
+ * act as one. Of course, implementing this correctly requires (SHOULD)
+ * a way to turn the functionality on and off. Another one for sysctl(),
+ * I guess. -- MS
+ *
+ * RFC1812 (4.3.3.9). A router MUST implement it.
+ * A router SHOULD have switch turning it on/off.
+ * This switch MUST be ON by default.
+ *
+ * Gratuitous replies, zero-source replies are not implemented,
+ * that complies with RFC. DO NOT implement them!!! All the idea
+ * of broadcast addrmask replies as specified in RFC950 is broken.
+ * The problem is that it is not uncommon to have several prefixes
+ * on one physical interface. Moreover, addrmask agent can even be
+ * not aware of existing another prefixes.
+ * If source is zero, addrmask agent cannot choose correct prefix.
+ * Gratuitous mask announcements suffer from the same problem.
+ * RFC1812 explains it, but still allows to use ADDRMASK,
+ * that is pretty silly. --ANK
+ *
+ * All these rules are so bizarre, that I removed kernel addrmask
+ * support at all. It is wrong, it is obsolete, nobody uses it in
+ * any case. --ANK
+ *
+ * Furthermore you can do it with a usermode address agent program
+ * anyway...
+ */
+
+static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, int len)
+{
+#if 0
+ if (net_ratelimit())
+ printk(KERN_DEBUG "a guy asks for address mask. Who is it?\n");
+#endif
+}
+
+/*
+ * RFC1812 (4.3.3.9). A router SHOULD listen all replies, and complain
+ * loudly if an inconsistency is found.
+ */
+
+static void icmp_address_reply(struct icmphdr *icmph, struct sk_buff *skb, int len)
+{
+ struct rtable *rt = (struct rtable*)skb->dst;
+ struct device *dev = skb->dev;
+ struct in_device *in_dev = dev->ip_ptr;
+ struct in_ifaddr *ifa;
+ u32 mask;
+
+ if (!in_dev || !in_dev->ifa_list ||
+ !IN_DEV_LOG_MARTIANS(in_dev) ||
+ !IN_DEV_FORWARD(in_dev) ||
+ len < 4 ||
+ !(rt->rt_flags&RTCF_DIRECTSRC))
+ return;
+
+ mask = *(u32*)&icmph[1];
+ for (ifa=in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
+ if (mask == ifa->ifa_mask && inet_ifa_match(rt->rt_src, ifa))
+ return;
+ }
+ if (net_ratelimit())
+ printk(KERN_INFO "Wrong address mask %08lX from %08lX/%s\n",
+ ntohl(mask), ntohl(rt->rt_src), dev->name);
+}
+
+static void icmp_discard(struct icmphdr *icmph, struct sk_buff *skb, int len)
+{
+}
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ * Check incoming icmp packets not addressed locally, to check whether
+ * they relate to a (proxying) socket on our system.
+ * Needed for transparent proxying.
+ *
+ * This code is presently ugly and needs cleanup.
+ * Probably should add a chkaddr entry to ipprot to call a chk routine
+ * in udp.c or tcp.c...
+ */
+
+/* This should work with the new hashes now. -DaveM */
+extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
+
+int icmp_chkaddr(struct sk_buff *skb)
+{
+ struct icmphdr *icmph=(struct icmphdr *)(skb->nh.raw + skb->nh.iph->ihl*4);
+ struct iphdr *iph = (struct iphdr *) (icmph + 1);
+ void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, int len) = icmp_pointers[icmph->type].handler;
+
+ if (handler == icmp_unreach || handler == icmp_redirect) {
+ struct sock *sk;
+
+ switch (iph->protocol) {
+ case IPPROTO_TCP:
+ {
+ struct tcphdr *th = (struct tcphdr *)(((unsigned char *)iph)+(iph->ihl<<2));
+
+ sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, th->source, skb->dev->ifindex);
+ if (!sk || (sk->state == TCP_LISTEN))
+ return 0;
+ /*
+ * This packet came from us.
+ */
+ return 1;
+ }
+ case IPPROTO_UDP:
+ {
+ struct udphdr *uh = (struct udphdr *)(((unsigned char *)iph)+(iph->ihl<<2));
+
+ sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev->ifindex);
+ if (!sk) return 0;
+ if (sk->saddr != iph->saddr && inet_addr_type(iph->saddr) != RTN_LOCAL)
+ return 0;
+ /*
+ * This packet may have come from us.
+ * Assume it did.
+ */
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+#endif
+
+/*
+ * Deal with incoming ICMP packets.
+ */
+
+int icmp_rcv(struct sk_buff *skb, unsigned short len)
+{
+ struct icmphdr *icmph = skb->h.icmph;
+ struct rtable *rt = (struct rtable*)skb->dst;
+
+ icmp_statistics.IcmpInMsgs++;
+
+ /*
+ * 18 is the highest 'known' ICMP type. Anything else is a mystery
+ *
+ * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently discarded.
+ */
+ if(len < sizeof(struct icmphdr) ||
+ ip_compute_csum((unsigned char *) icmph, len) ||
+ icmph->type > NR_ICMP_TYPES)
+ goto error;
+
+ /*
+ * Parse the ICMP message
+ */
+
+ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST)) {
+ /*
+ * RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be
+ * silently ignored (we let user decide with a sysctl).
+ * RFC 1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently
+ * discarded if to broadcast/multicast.
+ */
+ if (icmph->type == ICMP_ECHO &&
+ sysctl_icmp_echo_ignore_broadcasts) {
+ goto error;
+ }
+ if (icmph->type != ICMP_ECHO &&
+ icmph->type != ICMP_TIMESTAMP &&
+ icmph->type != ICMP_ADDRESS &&
+ icmph->type != ICMP_ADDRESSREPLY) {
+ goto error;
+ }
+ }
+
+ len -= sizeof(struct icmphdr);
+ (*icmp_pointers[icmph->type].input)++;
+ (icmp_pointers[icmph->type].handler)(icmph, skb, len);
+
+drop:
+ kfree_skb(skb);
+ return 0;
+error:
+ icmp_statistics.IcmpInErrors++;
+ goto drop;
+}
+
+/*
+ * A spare long used to speed up statistics updating
+ */
+
+static unsigned long dummy;
+
+/*
+ * Configurable rate limits.
+ * Someone should check if these default values are correct.
+ * Note that these values interact with the routing cache GC timeout.
+ * If you chose them too high they won't take effect, because the
+ * dst_entry gets expired too early. The same should happen when
+ * the cache grows too big.
+ */
+int sysctl_icmp_destunreach_time = 1*HZ;
+int sysctl_icmp_timeexceed_time = 1*HZ;
+int sysctl_icmp_paramprob_time = 1*HZ;
+int sysctl_icmp_echoreply_time = 0; /* don't limit it per default. */
+
+/*
+ * This table is the definition of how we handle ICMP.
+ */
+
+static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1] = {
+/* ECHO REPLY (0) */
+ { &icmp_statistics.IcmpOutEchoReps, &icmp_statistics.IcmpInEchoReps, icmp_discard, 0, &sysctl_icmp_echoreply_time},
+ { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+ { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+/* DEST UNREACH (3) */
+ { &icmp_statistics.IcmpOutDestUnreachs, &icmp_statistics.IcmpInDestUnreachs, icmp_unreach, 1, &sysctl_icmp_destunreach_time },
+/* SOURCE QUENCH (4) */
+ { &icmp_statistics.IcmpOutSrcQuenchs, &icmp_statistics.IcmpInSrcQuenchs, icmp_unreach, 1, },
+/* REDIRECT (5) */
+ { &icmp_statistics.IcmpOutRedirects, &icmp_statistics.IcmpInRedirects, icmp_redirect, 1, },
+ { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+ { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+/* ECHO (8) */
+ { &icmp_statistics.IcmpOutEchos, &icmp_statistics.IcmpInEchos, icmp_echo, 0, },
+ { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+ { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+/* TIME EXCEEDED (11) */
+ { &icmp_statistics.IcmpOutTimeExcds, &icmp_statistics.IcmpInTimeExcds, icmp_unreach, 1, &sysctl_icmp_timeexceed_time },
+/* PARAMETER PROBLEM (12) */
+ { &icmp_statistics.IcmpOutParmProbs, &icmp_statistics.IcmpInParmProbs, icmp_unreach, 1, &sysctl_icmp_paramprob_time },
+/* TIMESTAMP (13) */
+ { &icmp_statistics.IcmpOutTimestamps, &icmp_statistics.IcmpInTimestamps, icmp_timestamp, 0, },
+/* TIMESTAMP REPLY (14) */
+ { &icmp_statistics.IcmpOutTimestampReps, &icmp_statistics.IcmpInTimestampReps, icmp_discard, 0, },
+/* INFO (15) */
+ { &dummy, &dummy, icmp_discard, 0, },
+/* INFO REPLY (16) */
+ { &dummy, &dummy, icmp_discard, 0, },
+/* ADDR MASK (17) */
+ { &icmp_statistics.IcmpOutAddrMasks, &icmp_statistics.IcmpInAddrMasks, icmp_address, 0, },
+/* ADDR MASK REPLY (18) */
+ { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_address_reply, 0, }
+};
+
+__initfunc(void icmp_init(struct net_proto_family *ops))
+{
+ int err;
+
+ icmp_inode.i_mode = S_IFSOCK;
+ icmp_inode.i_sock = 1;
+ icmp_inode.i_uid = 0;
+ icmp_inode.i_gid = 0;
+
+ icmp_socket->inode = &icmp_inode;
+ icmp_socket->state = SS_UNCONNECTED;
+ icmp_socket->type=SOCK_RAW;
+
+ if ((err=ops->create(icmp_socket, IPPROTO_ICMP))<0)
+ panic("Failed to create the ICMP control socket.\n");
+ icmp_socket->sk->allocation=GFP_ATOMIC;
+ icmp_socket->sk->num = 256; /* Don't receive any data */
+ icmp_socket->sk->ip_ttl = MAXTTL;
+}
diff --git a/pfinet/linux-src/net/ipv4/igmp.c b/pfinet/linux-src/net/ipv4/igmp.c
new file mode 100644
index 00000000..934e8601
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/igmp.c
@@ -0,0 +1,698 @@
+/*
+ * Linux NET3: Internet Group Management Protocol [IGMP]
+ *
+ * This code implements the IGMP protocol as defined in RFC1112. There has
+ * been a further revision of this protocol since which is now supported.
+ *
+ * If you have trouble with this module be careful what gcc you have used,
+ * the older version didn't come out right using gcc 2.5.8, the newer one
+ * seems to fall out with gcc 2.6.2.
+ *
+ * Version: $Id: igmp.c,v 1.30.2.1 1999/07/23 15:29:22 davem Exp $
+ *
+ * Authors:
+ * Alan Cox <Alan.Cox@linux.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ *
+ * Alan Cox : Added lots of __inline__ to optimise
+ * the memory usage of all the tiny little
+ * functions.
+ * Alan Cox : Dumped the header building experiment.
+ * Alan Cox : Minor tweaks ready for multicast routing
+ * and extended IGMP protocol.
+ * Alan Cox : Removed a load of inline directives. Gcc 2.5.8
+ * writes utterly bogus code otherwise (sigh)
+ * fixed IGMP loopback to behave in the manner
+ * desired by mrouted, fixed the fact it has been
+ * broken since 1.3.6 and cleaned up a few minor
+ * points.
+ *
+ * Chih-Jen Chang : Tried to revise IGMP to Version 2
+ * Tsu-Sheng Tsao E-mail: chihjenc@scf.usc.edu and tsusheng@scf.usc.edu
+ * The enhancements are mainly based on Steve Deering's
+ * ipmulti-3.5 source code.
+ * Chih-Jen Chang : Added the igmp_get_mrouter_info and
+ * Tsu-Sheng Tsao igmp_set_mrouter_info to keep track of
+ * the mrouted version on that device.
+ * Chih-Jen Chang : Added the max_resp_time parameter to
+ * Tsu-Sheng Tsao igmp_heard_query(). Using this parameter
+ * to identify the multicast router version
+ * and do what the IGMP version 2 specified.
+ * Chih-Jen Chang : Added a timer to revert to IGMP V2 router
+ * Tsu-Sheng Tsao if the specified time expired.
+ * Alan Cox : Stop IGMP from 0.0.0.0 being accepted.
+ * Alan Cox : Use GFP_ATOMIC in the right places.
+ * Christian Daudt : igmp timer wasn't set for local group
+ * memberships but was being deleted,
+ * which caused a "del_timer() called
+ * from %p with timer not initialized\n"
+ * message (960131).
+ * Christian Daudt : removed del_timer from
+ * igmp_timer_expire function (960205).
+ * Christian Daudt : igmp_heard_report now only calls
+ * igmp_timer_expire if tm->running is
+ * true (960216).
+ * Malcolm Beattie : ttl comparison wrong in igmp_rcv made
+ * igmp_heard_query never trigger. Expiry
+ * miscalculation fixed in igmp_heard_query
+ * and random() made to return unsigned to
+ * prevent negative expiry times.
+ * Alexey Kuznetsov: Wrong group leaving behaviour, backport
+ * fix from pending 2.1.x patches.
+ * Alan Cox: Forget to enable FDDI support earlier.
+ * Alexey Kuznetsov: Fixed leaving groups on device down.
+ * Alexey Kuznetsov: Accordance to igmp-v2-06 draft.
+ */
+
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/sock.h>
+#include <net/checksum.h>
+#ifdef CONFIG_IP_MROUTE
+#include <linux/mroute.h>
+#endif
+
+#define IP_MAX_MEMBERSHIPS 20
+
+#ifdef CONFIG_IP_MULTICAST
+
+/* Parameter names and values are taken from igmp-v2-06 draft */
+
+#define IGMP_V1_Router_Present_Timeout (400*HZ)
+#define IGMP_Unsolicited_Report_Interval (10*HZ)
+#define IGMP_Query_Response_Interval (10*HZ)
+#define IGMP_Unsolicited_Report_Count 2
+
+
+#define IGMP_Initial_Report_Delay (1*HZ)
+
+/* IGMP_Initial_Report_Delay is not from IGMP specs!
+ * IGMP specs require to report membership immediately after
+ * joining a group, but we delay the first report by a
+ * small interval. It seems more natural and still does not
+ * contradict to specs provided this delay is small enough.
+ */
+
+#define IGMP_V1_SEEN(in_dev) ((in_dev)->mr_v1_seen && (long)(jiffies - (in_dev)->mr_v1_seen) < 0)
+
+/*
+ * Timer management
+ */
+
+static __inline__ void igmp_stop_timer(struct ip_mc_list *im)
+{
+ if (im->tm_running) {
+ del_timer(&im->timer);
+ im->tm_running=0;
+ }
+}
+
+static __inline__ void igmp_start_timer(struct ip_mc_list *im, int max_delay)
+{
+ int tv;
+ if (im->tm_running)
+ return;
+ tv=net_random() % max_delay;
+ im->timer.expires=jiffies+tv+2;
+ im->tm_running=1;
+ add_timer(&im->timer);
+}
+
+/*
+ * Send an IGMP report.
+ */
+
+#define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4)
+
+static int igmp_send_report(struct device *dev, u32 group, int type)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct igmphdr *ih;
+ struct rtable *rt;
+ u32 dst;
+
+ /* According to IGMPv2 specs, LEAVE messages are
+ * sent to all-routers group.
+ */
+ dst = group;
+ if (type == IGMP_HOST_LEAVE_MESSAGE)
+ dst = IGMP_ALL_ROUTER;
+
+ if (ip_route_output(&rt, dst, 0, 0, dev->ifindex))
+ return -1;
+ if (rt->rt_src == 0) {
+ ip_rt_put(rt);
+ return -1;
+ }
+
+ skb=alloc_skb(IGMP_SIZE+dev->hard_header_len+15, GFP_ATOMIC);
+ if (skb == NULL) {
+ ip_rt_put(rt);
+ return -1;
+ }
+
+ skb->dst = &rt->u.dst;
+
+ skb_reserve(skb, (dev->hard_header_len+15)&~15);
+
+ skb->nh.iph = iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr)+4);
+
+ iph->version = 4;
+ iph->ihl = (sizeof(struct iphdr)+4)>>2;
+ iph->tos = 0;
+ iph->frag_off = 0;
+ iph->ttl = 1;
+ iph->daddr = dst;
+ iph->saddr = rt->rt_src;
+ iph->protocol = IPPROTO_IGMP;
+ iph->tot_len = htons(IGMP_SIZE);
+ iph->id = htons(ip_id_count++);
+ ((u8*)&iph[1])[0] = IPOPT_RA;
+ ((u8*)&iph[1])[1] = 4;
+ ((u8*)&iph[1])[2] = 0;
+ ((u8*)&iph[1])[3] = 0;
+ ip_send_check(iph);
+
+ ih = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
+ ih->type=type;
+ ih->code=0;
+ ih->csum=0;
+ ih->group=group;
+ ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
+
+ return skb->dst->output(skb);
+}
+
+
+static void igmp_timer_expire(unsigned long data)
+{
+ struct ip_mc_list *im=(struct ip_mc_list *)data;
+ struct in_device *in_dev = im->interface;
+ int err;
+
+ im->tm_running=0;
+
+ if (IGMP_V1_SEEN(in_dev))
+ err = igmp_send_report(in_dev->dev, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
+ else
+ err = igmp_send_report(in_dev->dev, im->multiaddr, IGMP_HOST_NEW_MEMBERSHIP_REPORT);
+
+ /* Failed. Retry later. */
+ if (err) {
+ igmp_start_timer(im, IGMP_Unsolicited_Report_Interval);
+ return;
+ }
+
+ if (im->unsolicit_count) {
+ im->unsolicit_count--;
+ igmp_start_timer(im, IGMP_Unsolicited_Report_Interval);
+ }
+ im->reporter = 1;
+}
+
+static void igmp_heard_report(struct in_device *in_dev, u32 group)
+{
+ struct ip_mc_list *im;
+
+ /* Timers are only set for non-local groups */
+
+ if (group == IGMP_ALL_HOSTS)
+ return;
+
+ for (im=in_dev->mc_list; im!=NULL; im=im->next) {
+ if (im->multiaddr == group) {
+ igmp_stop_timer(im);
+ im->reporter = 0;
+ im->unsolicit_count = 0;
+ return;
+ }
+ }
+}
+
+static void igmp_heard_query(struct in_device *in_dev, unsigned char max_resp_time,
+ u32 group)
+{
+ struct ip_mc_list *im;
+ int max_delay;
+
+ max_delay = max_resp_time*(HZ/IGMP_TIMER_SCALE);
+
+ if (max_resp_time == 0) {
+ /* Alas, old v1 router presents here. */
+
+ max_delay = IGMP_Query_Response_Interval;
+ in_dev->mr_v1_seen = jiffies + IGMP_V1_Router_Present_Timeout;
+ group = 0;
+ }
+
+ /*
+ * - Start the timers in all of our membership records
+ * that the query applies to for the interface on
+ * which the query arrived excl. those that belong
+ * to a "local" group (224.0.0.X)
+ * - For timers already running check if they need to
+ * be reset.
+ * - Use the igmp->igmp_code field as the maximum
+ * delay possible
+ */
+ for (im=in_dev->mc_list; im!=NULL; im=im->next) {
+ if (group && group != im->multiaddr)
+ continue;
+ if (im->multiaddr == IGMP_ALL_HOSTS)
+ continue;
+ im->unsolicit_count = 0;
+ if (im->tm_running && (long)(im->timer.expires-jiffies) > max_delay)
+ igmp_stop_timer(im);
+ igmp_start_timer(im, max_delay);
+ }
+}
+
+int igmp_rcv(struct sk_buff *skb, unsigned short len)
+{
+ /* This basically follows the spec line by line -- see RFC1112 */
+ struct igmphdr *ih = skb->h.igmph;
+ struct in_device *in_dev = skb->dev->ip_ptr;
+
+ if (len < sizeof(struct igmphdr) || ip_compute_csum((void *)ih, len)
+ || in_dev==NULL) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ switch (ih->type) {
+ case IGMP_HOST_MEMBERSHIP_QUERY:
+ igmp_heard_query(in_dev, ih->code, ih->group);
+ break;
+ case IGMP_HOST_MEMBERSHIP_REPORT:
+ case IGMP_HOST_NEW_MEMBERSHIP_REPORT:
+ /* Is it our report looped back? */
+ if (((struct rtable*)skb->dst)->key.iif == 0)
+ break;
+ igmp_heard_report(in_dev, ih->group);
+ break;
+ case IGMP_PIM:
+#ifdef CONFIG_IP_PIMSM_V1
+ return pim_rcv_v1(skb, len);
+#endif
+ case IGMP_DVMRP:
+ case IGMP_TRACE:
+ case IGMP_HOST_LEAVE_MESSAGE:
+ case IGMP_MTRACE:
+ case IGMP_MTRACE_RESP:
+ break;
+ default:
+ NETDEBUG(printk(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type));
+ }
+ kfree_skb(skb);
+ return 0;
+}
+
+#endif
+
+
+/*
+ * Add a filter to a device
+ */
+
+static void ip_mc_filter_add(struct in_device *in_dev, u32 addr)
+{
+ char buf[MAX_ADDR_LEN];
+ struct device *dev = in_dev->dev;
+
+ /* Checking for IFF_MULTICAST here is WRONG-WRONG-WRONG.
+ We will get multicast token leakage, when IFF_MULTICAST
+ is changed. This check should be done in dev->set_multicast_list
+ routine. Something sort of:
+ if (dev->mc_list && dev->flags&IFF_MULTICAST) { do it; }
+ --ANK
+ */
+ if (arp_mc_map(addr, buf, dev, 0) == 0)
+ dev_mc_add(dev,buf,dev->addr_len,0);
+}
+
+/*
+ * Remove a filter from a device
+ */
+
+static void ip_mc_filter_del(struct in_device *in_dev, u32 addr)
+{
+ char buf[MAX_ADDR_LEN];
+ struct device *dev = in_dev->dev;
+
+ if (arp_mc_map(addr, buf, dev, 0) == 0)
+ dev_mc_delete(dev,buf,dev->addr_len,0);
+}
+
+static void igmp_group_dropped(struct ip_mc_list *im)
+{
+ if (im->loaded) {
+ im->loaded = 0;
+ ip_mc_filter_del(im->interface, im->multiaddr);
+ }
+
+#ifdef CONFIG_IP_MULTICAST
+ if (im->multiaddr == IGMP_ALL_HOSTS)
+ return;
+
+ start_bh_atomic();
+ igmp_stop_timer(im);
+ end_bh_atomic();
+
+ if (im->reporter && !IGMP_V1_SEEN(im->interface))
+ igmp_send_report(im->interface->dev, im->multiaddr, IGMP_HOST_LEAVE_MESSAGE);
+#endif
+}
+
+static void igmp_group_added(struct ip_mc_list *im)
+{
+ if (im->loaded == 0) {
+ im->loaded = 1;
+ ip_mc_filter_add(im->interface, im->multiaddr);
+ }
+
+#ifdef CONFIG_IP_MULTICAST
+ if (im->multiaddr == IGMP_ALL_HOSTS)
+ return;
+
+ start_bh_atomic();
+ igmp_start_timer(im, IGMP_Initial_Report_Delay);
+ end_bh_atomic();
+#endif
+}
+
+
+/*
+ * Multicast list managers
+ */
+
+
+/*
+ * A socket has joined a multicast group on device dev.
+ */
+
+void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
+{
+ struct ip_mc_list *i, *im;
+
+ im = (struct ip_mc_list *)kmalloc(sizeof(*im), GFP_KERNEL);
+
+ for (i=in_dev->mc_list; i; i=i->next) {
+ if (i->multiaddr == addr) {
+ i->users++;
+ if (im)
+ kfree(im);
+ return;
+ }
+ }
+ if (!im)
+ return;
+ im->users=1;
+ im->interface=in_dev;
+ im->multiaddr=addr;
+#ifdef CONFIG_IP_MULTICAST
+ im->tm_running=0;
+ init_timer(&im->timer);
+ im->timer.data=(unsigned long)im;
+ im->timer.function=&igmp_timer_expire;
+ im->unsolicit_count = IGMP_Unsolicited_Report_Count;
+ im->reporter = 0;
+ im->loaded = 0;
+#endif
+ im->next=in_dev->mc_list;
+ in_dev->mc_list=im;
+ igmp_group_added(im);
+ if (in_dev->dev->flags & IFF_UP)
+ ip_rt_multicast_event(in_dev);
+ return;
+}
+
+/*
+ * A socket has left a multicast group on device dev
+ */
+
+int ip_mc_dec_group(struct in_device *in_dev, u32 addr)
+{
+ struct ip_mc_list *i, **ip;
+
+ for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
+ if (i->multiaddr==addr) {
+ if (--i->users == 0) {
+ *ip = i->next;
+ synchronize_bh();
+
+ igmp_group_dropped(i);
+ if (in_dev->dev->flags & IFF_UP)
+ ip_rt_multicast_event(in_dev);
+ kfree_s(i, sizeof(*i));
+ }
+ return 0;
+ }
+ }
+ return -ESRCH;
+}
+
+/* Device going down */
+
+void ip_mc_down(struct in_device *in_dev)
+{
+ struct ip_mc_list *i;
+
+ for (i=in_dev->mc_list; i; i=i->next)
+ igmp_group_dropped(i);
+
+ ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS);
+}
+
+/* Device going up */
+
+void ip_mc_up(struct in_device *in_dev)
+{
+ struct ip_mc_list *i;
+
+ ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
+
+ for (i=in_dev->mc_list; i; i=i->next)
+ igmp_group_added(i);
+}
+
+/*
+ * Device is about to be destroyed: clean up.
+ */
+
+void ip_mc_destroy_dev(struct in_device *in_dev)
+{
+ struct ip_mc_list *i;
+
+ while ((i = in_dev->mc_list) != NULL) {
+ in_dev->mc_list = i->next;
+ igmp_group_dropped(i);
+ kfree_s(i, sizeof(*i));
+ }
+}
+
+static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
+{
+ struct rtable *rt;
+ struct device *dev = NULL;
+
+ if (imr->imr_address.s_addr) {
+ dev = ip_dev_find(imr->imr_address.s_addr);
+ if (!dev)
+ return NULL;
+ }
+
+ if (!dev && !ip_route_output(&rt, imr->imr_multiaddr.s_addr, 0, 0, 0)) {
+ dev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ }
+ if (dev) {
+ imr->imr_ifindex = dev->ifindex;
+ return dev->ip_ptr;
+ }
+ return NULL;
+}
+
+/*
+ * Join a socket to a group
+ */
+int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS;
+
+int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
+{
+ int err;
+ u32 addr = imr->imr_multiaddr.s_addr;
+ struct ip_mc_socklist *iml, *i;
+ struct in_device *in_dev;
+ int count = 0;
+
+ if (!MULTICAST(addr))
+ return -EINVAL;
+
+ rtnl_shlock();
+
+ if (!imr->imr_ifindex)
+ in_dev = ip_mc_find_dev(imr);
+ else
+ in_dev = inetdev_by_index(imr->imr_ifindex);
+
+ if (!in_dev) {
+ iml = NULL;
+ err = -ENODEV;
+ goto done;
+ }
+
+ iml = (struct ip_mc_socklist *)sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);
+
+ err = -EADDRINUSE;
+ for (i=sk->ip_mc_list; i; i=i->next) {
+ if (memcmp(&i->multi, imr, sizeof(*imr)) == 0) {
+ /* New style additions are reference counted */
+ if (imr->imr_address.s_addr == 0) {
+ i->count++;
+ err = 0;
+ }
+ goto done;
+ }
+ count++;
+ }
+ err = -ENOBUFS;
+ if (iml == NULL || count >= sysctl_igmp_max_memberships)
+ goto done;
+ memcpy(&iml->multi, imr, sizeof(*imr));
+ iml->next = sk->ip_mc_list;
+ iml->count = 1;
+ sk->ip_mc_list = iml;
+ ip_mc_inc_group(in_dev, addr);
+ iml = NULL;
+ err = 0;
+done:
+ rtnl_shunlock();
+ if (iml)
+ sock_kfree_s(sk, iml, sizeof(*iml));
+ return err;
+}
+
+/*
+ * Ask a socket to leave a group.
+ */
+
+int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
+{
+ struct ip_mc_socklist *iml, **imlp;
+
+ for (imlp=&sk->ip_mc_list; (iml=*imlp)!=NULL; imlp=&iml->next) {
+ if (iml->multi.imr_multiaddr.s_addr==imr->imr_multiaddr.s_addr &&
+ iml->multi.imr_address.s_addr==imr->imr_address.s_addr &&
+ (!imr->imr_ifindex || iml->multi.imr_ifindex==imr->imr_ifindex)) {
+ struct in_device *in_dev;
+ if (--iml->count)
+ return 0;
+
+ *imlp = iml->next;
+ synchronize_bh();
+
+ in_dev = inetdev_by_index(iml->multi.imr_ifindex);
+ if (in_dev)
+ ip_mc_dec_group(in_dev, imr->imr_multiaddr.s_addr);
+ sock_kfree_s(sk, iml, sizeof(*iml));
+ return 0;
+ }
+ }
+ return -EADDRNOTAVAIL;
+}
+
+/*
+ * A socket is closing.
+ */
+
+void ip_mc_drop_socket(struct sock *sk)
+{
+ struct ip_mc_socklist *iml;
+
+ while ((iml=sk->ip_mc_list) != NULL) {
+ struct in_device *in_dev;
+ sk->ip_mc_list = iml->next;
+ if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL)
+ ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
+ sock_kfree_s(sk, iml, sizeof(*iml));
+ }
+}
+
+
+#ifdef CONFIG_IP_MULTICAST
+
+int ip_mc_procinfo(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ off_t pos=0, begin=0;
+ struct ip_mc_list *im;
+ int len=0;
+ struct device *dev;
+
+ len=sprintf(buffer,"Idx\tDevice : Count Querier\tGroup Users Timer\tReporter\n");
+
+ for(dev = dev_base; dev; dev = dev->next)
+ {
+ struct in_device *in_dev = dev->ip_ptr;
+ char *querier = "NONE";
+
+ if (in_dev == NULL)
+ continue;
+
+ querier = IGMP_V1_SEEN(in_dev) ? "V1" : "V2";
+
+ len+=sprintf(buffer+len,"%d\t%-10s: %5d %7s\n",
+ dev->ifindex, dev->name, dev->mc_count, querier);
+
+ for (im = in_dev->mc_list; im; im = im->next) {
+ len+=sprintf(buffer+len,
+ "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
+ im->multiaddr, im->users,
+ im->tm_running, im->timer.expires-jiffies, im->reporter);
+
+ pos=begin+len;
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ goto done;
+ }
+ }
+done:
+ *start=buffer+(offset-begin);
+ len-=(offset-begin);
+ if(len>length)
+ len=length;
+ if(len<0)
+ len=0;
+ return len;
+}
+#endif
+
diff --git a/pfinet/linux-src/net/ipv4/ip_forward.c b/pfinet/linux-src/net/ipv4/ip_forward.c
new file mode 100644
index 00000000..08ebbc2f
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_forward.c
@@ -0,0 +1,297 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * The IP forwarding functionality.
+ *
+ * Version: $Id: ip_forward.c,v 1.43 1999/03/21 05:22:37 davem Exp $
+ *
+ * Authors: see ip.c
+ *
+ * Fixes:
+ * Many : Split from ip.c , see ip_input.c for
+ * history.
+ * Dave Gregorich : NULL ip_rt_put fix for multicast
+ * routing.
+ * Jos Vos : Add call_out_firewall before sending,
+ * use output device for accounting.
+ * Jos Vos : Call forward firewall after routing
+ * (always use output device).
+ * Mike McLagan : Routing by source
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/icmp.h>
+#include <linux/netdevice.h>
+#include <net/sock.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/icmp.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/firewall.h>
+#include <linux/ip_fw.h>
+#ifdef CONFIG_IP_MASQUERADE
+#include <net/ip_masq.h>
+#endif
+#include <net/checksum.h>
+#include <linux/route.h>
+#include <net/route.h>
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ * Check the packet against our socket administration to see
+ * if it is related to a connection on our system.
+ * Needed for transparent proxying.
+ */
+
+int ip_chksock(struct sk_buff *skb)
+{
+ switch (skb->nh.iph->protocol) {
+ case IPPROTO_ICMP:
+ return icmp_chkaddr(skb);
+ case IPPROTO_TCP:
+ return tcp_chkaddr(skb);
+ case IPPROTO_UDP:
+ return udp_chkaddr(skb);
+ default:
+ return 0;
+ }
+}
+#endif
+
+
+int ip_forward(struct sk_buff *skb)
+{
+ struct device *dev2; /* Output device */
+ struct iphdr *iph; /* Our header */
+ struct rtable *rt; /* Route we use */
+ struct ip_options * opt = &(IPCB(skb)->opt);
+ unsigned short mtu;
+#if defined(CONFIG_FIREWALL) || defined(CONFIG_IP_MASQUERADE)
+ int fw_res = 0;
+#endif
+
+ if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
+ return 0;
+
+ if (skb->pkt_type != PACKET_HOST)
+ goto drop;
+
+ /*
+ * According to the RFC, we must first decrease the TTL field. If
+ * that reaches zero, we must reply an ICMP control message telling
+ * that the packet's lifetime expired.
+ */
+
+ iph = skb->nh.iph;
+ rt = (struct rtable*)skb->dst;
+
+#ifdef CONFIG_CPU_IS_SLOW
+ if (net_cpu_congestion > 1 && !(iph->tos&IPTOS_RELIABILITY) &&
+ IPTOS_PREC(iph->tos) < IPTOS_PREC_INTERNETCONTROL) {
+ if (((xtime.tv_usec&0xF)<<net_cpu_congestion) > 0x1C)
+ goto drop;
+ }
+#endif
+
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (ip_chksock(skb))
+ goto local_pkt;
+#endif
+
+ if (iph->ttl <= 1)
+ goto too_many_hops;
+
+ if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
+ goto sr_failed;
+
+ /*
+ * Having picked a route we can now send the frame out
+ * after asking the firewall permission to do so.
+ */
+
+ skb->priority = rt_tos2priority(iph->tos);
+ dev2 = rt->u.dst.dev;
+ mtu = rt->u.dst.pmtu;
+
+#ifdef CONFIG_NET_SECURITY
+ call_fw_firewall(PF_SECURITY, dev2, NULL, &mtu, NULL);
+#endif
+
+ /*
+ * We now generate an ICMP HOST REDIRECT giving the route
+ * we calculated.
+ */
+ if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr)
+ ip_rt_send_redirect(skb);
+
+ /* We are about to mangle packet. Copy it! */
+ if ((skb = skb_cow(skb, dev2->hard_header_len)) == NULL)
+ return -1;
+ iph = skb->nh.iph;
+ opt = &(IPCB(skb)->opt);
+
+ /* Decrease ttl after skb cow done */
+ ip_decrease_ttl(iph);
+
+ /*
+ * We now may allocate a new buffer, and copy the datagram into it.
+ * If the indicated interface is up and running, kick it.
+ */
+
+ if (skb->len > mtu && (ntohs(iph->frag_off) & IP_DF))
+ goto frag_needed;
+
+#ifdef CONFIG_IP_ROUTE_NAT
+ if (rt->rt_flags & RTCF_NAT) {
+ if (ip_do_nat(skb)) {
+ kfree_skb(skb);
+ return -1;
+ }
+ }
+#endif
+
+#ifdef CONFIG_IP_MASQUERADE
+ if(!(IPCB(skb)->flags&IPSKB_MASQUERADED)) {
+ /*
+ * Check that any ICMP packets are not for a
+ * masqueraded connection. If so rewrite them
+ * and skip the firewall checks
+ */
+ if (iph->protocol == IPPROTO_ICMP) {
+ __u32 maddr;
+#ifdef CONFIG_IP_MASQUERADE_ICMP
+ struct icmphdr *icmph = (struct icmphdr *)((char*)iph + (iph->ihl << 2));
+ if ((icmph->type==ICMP_DEST_UNREACH)||
+ (icmph->type==ICMP_SOURCE_QUENCH)||
+ (icmph->type==ICMP_TIME_EXCEEDED))
+ {
+#endif
+ maddr = inet_select_addr(dev2, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+ fw_res = ip_fw_masq_icmp(&skb, maddr);
+ if (fw_res < 0) {
+ kfree_skb(skb);
+ return -1;
+ }
+
+ if (fw_res)
+ /* ICMP matched - skip firewall */
+ goto skip_call_fw_firewall;
+#ifdef CONFIG_IP_MASQUERADE_ICMP
+ }
+#endif
+ }
+ if (rt->rt_flags&RTCF_MASQ)
+ goto skip_call_fw_firewall;
+#endif /* CONFIG_IP_MASQUERADE */
+
+#ifdef CONFIG_FIREWALL
+ fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL, &skb);
+ switch (fw_res) {
+ case FW_ACCEPT:
+ case FW_MASQUERADE:
+ break;
+ case FW_REJECT:
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+ /* fall thru */
+ default:
+ kfree_skb(skb);
+ return -1;
+ }
+#endif
+
+#ifdef CONFIG_IP_MASQUERADE
+ }
+
+skip_call_fw_firewall:
+ /*
+ * If this fragment needs masquerading, make it so...
+ * (Don't masquerade de-masqueraded fragments)
+ */
+ if (!(IPCB(skb)->flags&IPSKB_MASQUERADED) &&
+ (fw_res==FW_MASQUERADE || rt->rt_flags&RTCF_MASQ)) {
+ u32 maddr;
+
+#ifdef CONFIG_IP_ROUTE_NAT
+ maddr = (rt->rt_flags&RTCF_MASQ) ? rt->rt_src_map : 0;
+
+ if (maddr == 0)
+#endif
+ maddr = inet_select_addr(dev2, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+
+ if (ip_fw_masquerade(&skb, maddr) < 0) {
+ kfree_skb(skb);
+ return -1;
+ } else {
+ /*
+ * Masquerader may have changed skb
+ */
+ iph = skb->nh.iph;
+ opt = &(IPCB(skb)->opt);
+ }
+ }
+#endif
+
+
+#ifdef CONFIG_FIREWALL
+ if ((fw_res = call_out_firewall(PF_INET, dev2, iph, NULL,&skb)) < FW_ACCEPT) {
+ /* FW_ACCEPT and FW_MASQUERADE are treated equal:
+ masquerading is only supported via forward rules */
+ if (fw_res == FW_REJECT)
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+ kfree_skb(skb);
+ return -1;
+ }
+#endif
+
+ ip_statistics.IpForwDatagrams++;
+
+ if (opt->optlen == 0) {
+#ifdef CONFIG_NET_FASTROUTE
+ if (rt->rt_flags&RTCF_FAST && !netdev_fastroute_obstacles) {
+ unsigned h = ((*(u8*)&rt->key.dst)^(*(u8*)&rt->key.src))&NETDEV_FASTROUTE_HMASK;
+ /* Time to switch to functional programming :-) */
+ dst_release_irqwait(xchg(&skb->dev->fastpath[h], dst_clone(&rt->u.dst)));
+ }
+#endif
+ ip_send(skb);
+ return 0;
+ }
+
+ ip_forward_options(skb);
+ ip_send(skb);
+ return 0;
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+local_pkt:
+ return ip_local_deliver(skb);
+#endif
+
+frag_needed:
+ ip_statistics.IpFragFails++;
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+ goto drop;
+
+sr_failed:
+ /*
+ * Strict routing permits no gatewaying
+ */
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
+ goto drop;
+
+too_many_hops:
+ /* Tell the sender its packet died... */
+ icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
+drop:
+ kfree_skb(skb);
+ return -1;
+}
diff --git a/pfinet/linux-src/net/ipv4/ip_fragment.c b/pfinet/linux-src/net/ipv4/ip_fragment.c
new file mode 100644
index 00000000..f066e607
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_fragment.c
@@ -0,0 +1,593 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * The IP fragmentation functionality.
+ *
+ * Version: $Id: ip_fragment.c,v 1.40 1999/03/20 23:58:34 davem Exp $
+ *
+ * Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
+ * Alan Cox <Alan.Cox@linux.org>
+ *
+ * Fixes:
+ * Alan Cox : Split from ip.c , see ip_input.c for history.
+ * David S. Miller : Begin massive cleanup...
+ * Andi Kleen : Add sysctls.
+ * xxxx : Overlapfrag bug.
+ * Ultima : ip_expire() kernel panic.
+ * Bill Hawes : Frag accounting and evictor fixes.
+ * John McDonald : 0 length frag bug.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/icmp.h>
+#include <linux/netdevice.h>
+#include <net/sock.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/inet.h>
+#include <linux/firewall.h>
+#include <linux/ip_fw.h>
+
+/* Fragment cache limits. We will commit 256K at one time. Should we
+ * cross that limit we will prune down to 192K. This should cope with
+ * even the most extreme cases without allowing an attacker to measurably
+ * harm machine performance.
+ */
+int sysctl_ipfrag_high_thresh = 256*1024;
+int sysctl_ipfrag_low_thresh = 192*1024;
+
+int sysctl_ipfrag_time = IP_FRAG_TIME;
+
+/* Describe an IP fragment. */
+struct ipfrag {
+ int offset; /* offset of fragment in IP datagram */
+ int end; /* last byte of data in datagram */
+ int len; /* length of this fragment */
+ struct sk_buff *skb; /* complete received fragment */
+ unsigned char *ptr; /* pointer into real fragment data */
+ struct ipfrag *next; /* linked list pointers */
+ struct ipfrag *prev;
+};
+
+/* Describe an entry in the "incomplete datagrams" queue. */
+struct ipq {
+ struct iphdr *iph; /* pointer to IP header */
+ struct ipq *next; /* linked list pointers */
+ struct ipfrag *fragments; /* linked list of received fragments */
+ int len; /* total length of original datagram */
+ short ihlen; /* length of the IP header */
+ struct timer_list timer; /* when will this queue expire? */
+ struct ipq **pprev;
+ struct device *dev; /* Device - for icmp replies */
+};
+
+#define IPQ_HASHSZ 64
+
+struct ipq *ipq_hash[IPQ_HASHSZ];
+
+#define ipqhashfn(id, saddr, daddr, prot) \
+ ((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
+
+atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
+
+/* Memory Tracking Functions. */
+extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
+{
+ atomic_sub(skb->truesize, &ip_frag_mem);
+ kfree_skb(skb);
+}
+
+extern __inline__ void frag_kfree_s(void *ptr, int len)
+{
+ atomic_sub(len, &ip_frag_mem);
+ kfree(ptr);
+}
+
+extern __inline__ void *frag_kmalloc(int size, int pri)
+{
+ void *vp = kmalloc(size, pri);
+
+ if(!vp)
+ return NULL;
+ atomic_add(size, &ip_frag_mem);
+ return vp;
+}
+
+/* Create a new fragment entry. */
+static struct ipfrag *ip_frag_create(int offset, int end,
+ struct sk_buff *skb, unsigned char *ptr)
+{
+ struct ipfrag *fp;
+
+ fp = (struct ipfrag *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);
+ if (fp == NULL)
+ goto out_nomem;
+
+ /* Fill in the structure. */
+ fp->offset = offset;
+ fp->end = end;
+ fp->len = end - offset;
+ fp->skb = skb;
+ fp->ptr = ptr;
+ fp->next = fp->prev = NULL;
+
+ /* Charge for the SKB as well. */
+ atomic_add(skb->truesize, &ip_frag_mem);
+
+ return(fp);
+
+out_nomem:
+ NETDEBUG(printk(KERN_ERR "IP: frag_create: no memory left !\n"));
+ return(NULL);
+}
+
+/* Find the correct entry in the "incomplete datagrams" queue for
+ * this IP datagram, and return the queue entry address if found.
+ */
+static inline struct ipq *ip_find(struct iphdr *iph, struct dst_entry *dst)
+{
+ __u16 id = iph->id;
+ __u32 saddr = iph->saddr;
+ __u32 daddr = iph->daddr;
+ __u8 protocol = iph->protocol;
+ unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
+ struct ipq *qp;
+
+ /* Always, we are in a BH context, so no locking. -DaveM */
+ for(qp = ipq_hash[hash]; qp; qp = qp->next) {
+ if(qp->iph->id == id &&
+ qp->iph->saddr == saddr &&
+ qp->iph->daddr == daddr &&
+ qp->iph->protocol == protocol) {
+ del_timer(&qp->timer);
+ break;
+ }
+ }
+ return qp;
+}
+
+/* Remove an entry from the "incomplete datagrams" queue, either
+ * because we completed, reassembled and processed it, or because
+ * it timed out.
+ *
+ * This is called _only_ from BH contexts, on packet reception
+ * processing and from frag queue expiration timers. -DaveM
+ */
+static void ip_free(struct ipq *qp)
+{
+ struct ipfrag *fp;
+
+ /* Stop the timer for this entry. */
+ del_timer(&qp->timer);
+
+ /* Remove this entry from the "incomplete datagrams" queue. */
+ if(qp->next)
+ qp->next->pprev = qp->pprev;
+ *qp->pprev = qp->next;
+
+ /* Release all fragment data. */
+ fp = qp->fragments;
+ while (fp) {
+ struct ipfrag *xp = fp->next;
+
+ frag_kfree_skb(fp->skb);
+ frag_kfree_s(fp, sizeof(struct ipfrag));
+ fp = xp;
+ }
+
+ /* Release the IP header. */
+ frag_kfree_s(qp->iph, 64 + 8);
+
+ /* Finally, release the queue descriptor itself. */
+ frag_kfree_s(qp, sizeof(struct ipq));
+}
+
+/*
+ * Oops, a fragment queue timed out. Kill it and send an ICMP reply.
+ */
+static void ip_expire(unsigned long arg)
+{
+ struct ipq *qp = (struct ipq *) arg;
+
+ if(!qp->fragments)
+ {
+#ifdef IP_EXPIRE_DEBUG
+ printk("warning: possible ip-expire attack\n");
+#endif
+ goto out;
+ }
+
+ /* Send an ICMP "Fragment Reassembly Timeout" message. */
+ ip_statistics.IpReasmTimeout++;
+ ip_statistics.IpReasmFails++;
+ icmp_send(qp->fragments->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+
+out:
+ /* Nuke the fragment queue. */
+ ip_free(qp);
+}
+
+/* Memory limiting on fragments. Evictor trashes the oldest
+ * fragment queue until we are back under the low threshold.
+ */
+static void ip_evictor(void)
+{
+ int i, progress;
+
+restart:
+ progress = 0;
+ /* FIXME: Make LRU queue of frag heads. -DaveM */
+ for (i = 0; i < IPQ_HASHSZ; i++) {
+ struct ipq *qp;
+ if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
+ return;
+ /* We are in a BH context, so these queue
+ * accesses are safe. -DaveM
+ */
+ qp = ipq_hash[i];
+ if (qp) {
+ /* find the oldest queue for this hash bucket */
+ while (qp->next)
+ qp = qp->next;
+ ip_free(qp);
+ progress = 1;
+ }
+ }
+ if (progress)
+ goto restart;
+ panic("ip_evictor: memcount");
+}
+
+/* Add an entry to the 'ipq' queue for a newly received IP datagram.
+ * We will (hopefully :-) receive all other fragments of this datagram
+ * in time, so we just create a queue for this datagram, in which we
+ * will insert the received fragments at their respective positions.
+ */
+static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph)
+{
+ struct ipq *qp;
+ unsigned int hash;
+ int ihlen;
+
+ qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC);
+ if (qp == NULL)
+ goto out_nomem;
+
+ /* Allocate memory for the IP header (plus 8 octets for ICMP). */
+ ihlen = iph->ihl * 4;
+
+ qp->iph = (struct iphdr *) frag_kmalloc(64 + 8, GFP_ATOMIC);
+ if (qp->iph == NULL)
+ goto out_free;
+
+ memcpy(qp->iph, iph, ihlen + 8);
+ qp->len = 0;
+ qp->ihlen = ihlen;
+ qp->fragments = NULL;
+ qp->dev = skb->dev;
+
+ /* Initialize a timer for this entry. */
+ init_timer(&qp->timer);
+ qp->timer.expires = 0; /* (to be set later) */
+ qp->timer.data = (unsigned long) qp; /* pointer to queue */
+ qp->timer.function = ip_expire; /* expire function */
+
+ /* Add this entry to the queue. */
+ hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
+
+ /* We are in a BH context, no locking necessary. -DaveM */
+ if((qp->next = ipq_hash[hash]) != NULL)
+ qp->next->pprev = &qp->next;
+ ipq_hash[hash] = qp;
+ qp->pprev = &ipq_hash[hash];
+
+ return qp;
+
+out_free:
+ frag_kfree_s(qp, sizeof(struct ipq));
+out_nomem:
+ NETDEBUG(printk(KERN_ERR "IP: create: no memory left !\n"));
+ return(NULL);
+}
+
+/* See if a fragment queue is complete. */
+static int ip_done(struct ipq *qp)
+{
+ struct ipfrag *fp;
+ int offset;
+
+ /* Only possible if we received the final fragment. */
+ if (qp->len == 0)
+ return 0;
+
+ /* Check all fragment offsets to see if they connect. */
+ fp = qp->fragments;
+ offset = 0;
+ while (fp) {
+ if (fp->offset > offset)
+ return(0); /* fragment(s) missing */
+ offset = fp->end;
+ fp = fp->next;
+ }
+
+ /* All fragments are present. */
+ return 1;
+}
+
+/* Build a new IP datagram from all its fragments.
+ *
+ * FIXME: We copy here because we lack an effective way of handling lists
+ * of bits on input. Until the new skb data handling is in I'm not going
+ * to touch this with a bargepole.
+ */
+static struct sk_buff *ip_glue(struct ipq *qp)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct ipfrag *fp;
+ unsigned char *ptr;
+ int count, len;
+
+ /* Allocate a new buffer for the datagram. */
+ len = qp->ihlen + qp->len;
+
+ if(len > 65535)
+ goto out_oversize;
+
+ skb = dev_alloc_skb(len);
+ if (!skb)
+ goto out_nomem;
+
+ /* Fill in the basic details. */
+ skb->mac.raw = ptr = skb->data;
+ skb->nh.iph = iph = (struct iphdr *) skb_put(skb, len);
+
+ /* Copy the original IP headers into the new buffer. */
+ memcpy(ptr, qp->iph, qp->ihlen);
+ ptr += qp->ihlen;
+
+ /* Copy the data portions of all fragments into the new buffer. */
+ fp = qp->fragments;
+ count = qp->ihlen;
+ while(fp) {
+ if ((fp->len <= 0) || ((count + fp->len) > skb->len))
+ goto out_invalid;
+ memcpy((ptr + fp->offset), fp->ptr, fp->len);
+ if (count == qp->ihlen) {
+ skb->dst = dst_clone(fp->skb->dst);
+ skb->dev = fp->skb->dev;
+ }
+ count += fp->len;
+ fp = fp->next;
+ }
+
+ skb->pkt_type = qp->fragments->skb->pkt_type;
+ skb->protocol = qp->fragments->skb->protocol;
+ /*
+ * Clearly bogus, because security markings of the individual
+ * fragments should have been checked for consistency before
+ * gluing, and intermediate coalescing of fragments may have
+ * taken place in ip_defrag() before ip_glue() ever got called.
+ * If we're not going to do the consistency checking, we might
+ * as well take the value associated with the first fragment.
+ * --rct
+ */
+ skb->security = qp->fragments->skb->security;
+
+ /* Done with all fragments. Fixup the new IP header. */
+ iph = skb->nh.iph;
+ iph->frag_off = 0;
+ iph->tot_len = htons(count);
+ ip_statistics.IpReasmOKs++;
+ return skb;
+
+out_invalid:
+ NETDEBUG(printk(KERN_ERR
+ "Invalid fragment list: Fragment over size.\n"));
+ kfree_skb(skb);
+ goto out_fail;
+out_nomem:
+ NETDEBUG(printk(KERN_ERR
+ "IP: queue_glue: no memory for gluing queue %p\n",
+ qp));
+ goto out_fail;
+out_oversize:
+ if (net_ratelimit())
+ printk(KERN_INFO
+ "Oversized IP packet from %d.%d.%d.%d.\n",
+ NIPQUAD(qp->iph->saddr));
+out_fail:
+ ip_statistics.IpReasmFails++;
+ return NULL;
+}
+
+/* Process an incoming IP datagram fragment. */
+struct sk_buff *ip_defrag(struct sk_buff *skb)
+{
+ struct iphdr *iph = skb->nh.iph;
+ struct ipfrag *prev, *next, *tmp, *tfp;
+ struct ipq *qp;
+ unsigned char *ptr;
+ int flags, offset;
+ int i, ihl, end;
+
+ ip_statistics.IpReasmReqds++;
+
+ /* Start by cleaning up the memory. */
+ if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
+ ip_evictor();
+
+ /*
+ * Look for the entry for this IP datagram in the
+ * "incomplete datagrams" queue. If found, the
+ * timer is removed.
+ */
+ qp = ip_find(iph, skb->dst);
+
+ /* Is this a non-fragmented datagram? */
+ offset = ntohs(iph->frag_off);
+ flags = offset & ~IP_OFFSET;
+ offset &= IP_OFFSET;
+
+ offset <<= 3; /* offset is in 8-byte chunks */
+ ihl = iph->ihl * 4;
+
+ /*
+ * Check whether to create a fresh queue entry. If the
+ * queue already exists, its timer will be restarted as
+ * long as we continue to receive fragments.
+ */
+ if (qp) {
+ /* ANK. If the first fragment is received,
+ * we should remember the correct IP header (with options)
+ */
+ if (offset == 0) {
+ /* Fragmented frame replaced by unfragmented copy? */
+ if ((flags & IP_MF) == 0)
+ goto out_freequeue;
+ qp->ihlen = ihl;
+ memcpy(qp->iph, iph, (ihl + 8));
+ }
+ } else {
+ /* Fragmented frame replaced by unfragmented copy? */
+ if ((offset == 0) && ((flags & IP_MF) == 0))
+ goto out_skb;
+
+ /* If we failed to create it, then discard the frame. */
+ qp = ip_create(skb, iph);
+ if (!qp)
+ goto out_freeskb;
+ }
+
+ /* Attempt to construct an oversize packet. */
+ if((ntohs(iph->tot_len) + ((int) offset)) > 65535)
+ goto out_oversize;
+
+ /* Determine the position of this fragment. */
+ end = offset + ntohs(iph->tot_len) - ihl;
+
+ /* Is this the final fragment? */
+ if ((flags & IP_MF) == 0)
+ qp->len = end;
+
+ /* Find out which fragments are in front and at the back of us
+ * in the chain of fragments so far. We must know where to put
+ * this fragment, right?
+ */
+ prev = NULL;
+ for(next = qp->fragments; next != NULL; next = next->next) {
+ if (next->offset >= offset)
+ break; /* bingo! */
+ prev = next;
+ }
+
+ /* Point into the IP datagram 'data' part. */
+ ptr = skb->data + ihl;
+
+ /* We found where to put this one. Check for overlap with
+ * preceding fragment, and, if needed, align things so that
+ * any overlaps are eliminated.
+ */
+ if ((prev != NULL) && (offset < prev->end)) {
+ i = prev->end - offset;
+ offset += i; /* ptr into datagram */
+ ptr += i; /* ptr into fragment data */
+ }
+
+ /* Look for overlap with succeeding segments.
+ * If we can merge fragments, do it.
+ */
+ for (tmp = next; tmp != NULL; tmp = tfp) {
+ tfp = tmp->next;
+ if (tmp->offset >= end)
+ break; /* no overlaps at all */
+
+ i = end - next->offset; /* overlap is 'i' bytes */
+ tmp->len -= i; /* so reduce size of */
+ tmp->offset += i; /* next fragment */
+ tmp->ptr += i;
+
+ /* If we get a frag size of <= 0, remove it and the packet
+ * that it goes with.
+ */
+ if (tmp->len <= 0) {
+ if (tmp->prev != NULL)
+ tmp->prev->next = tmp->next;
+ else
+ qp->fragments = tmp->next;
+
+ if (tmp->next != NULL)
+ tmp->next->prev = tmp->prev;
+
+ /* We have killed the original next frame. */
+ next = tfp;
+
+ frag_kfree_skb(tmp->skb);
+ frag_kfree_s(tmp, sizeof(struct ipfrag));
+ }
+ }
+
+ /*
+ * Create a fragment to hold this skb.
+ * No memory to save the fragment? throw the lot ...
+ */
+ tfp = ip_frag_create(offset, end, skb, ptr);
+ if (!tfp)
+ goto out_freeskb;
+
+ /* Insert this fragment in the chain of fragments. */
+ tfp->prev = prev;
+ tfp->next = next;
+ if (prev != NULL)
+ prev->next = tfp;
+ else
+ qp->fragments = tfp;
+
+ if (next != NULL)
+ next->prev = tfp;
+
+ /* OK, so we inserted this new fragment into the chain.
+ * Check if we now have a full IP datagram which we can
+ * bump up to the IP layer...
+ */
+ if (ip_done(qp)) {
+ /* Glue together the fragments. */
+ skb = ip_glue(qp);
+ /* Free the queue entry. */
+out_freequeue:
+ ip_free(qp);
+out_skb:
+ return skb;
+ }
+
+ /*
+ * The queue is still active ... reset its timer.
+ */
+out_timer:
+ mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time); /* ~ 30 seconds */
+out:
+ return NULL;
+
+ /*
+ * Error exits ... we need to reset the timer if there's a queue.
+ */
+out_oversize:
+ if (net_ratelimit())
+ printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n",
+ NIPQUAD(iph->saddr));
+ /* the skb isn't in a fragment, so fall through to free it */
+out_freeskb:
+ kfree_skb(skb);
+ ip_statistics.IpReasmFails++;
+ if (qp)
+ goto out_timer;
+ goto out;
+}
diff --git a/pfinet/linux-src/net/ipv4/ip_fw.c b/pfinet/linux-src/net/ipv4/ip_fw.c
new file mode 100644
index 00000000..99a91d53
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_fw.c
@@ -0,0 +1,1759 @@
+/*
+ * This code is heavily based on the code on the old ip_fw.c code; see below for
+ * copyrights and attributions of the old code. This code is basically GPL.
+ *
+ * 15-Aug-1997: Major changes to allow graphs for firewall rules.
+ * Paul Russell <Paul.Russell@rustcorp.com.au> and
+ * Michael Neuling <Michael.Neuling@rustcorp.com.au>
+ * 24-Aug-1997: Generalised protocol handling (not just TCP/UDP/ICMP).
+ * Added explicit RETURN from chains.
+ * Removed TOS mangling (done in ipchains 1.0.1).
+ * Fixed read & reset bug by reworking proc handling.
+ * Paul Russell <Paul.Russell@rustcorp.com.au>
+ * 28-Sep-1997: Added packet marking for net sched code.
+ * Removed fw_via comparisons: all done on device name now,
+ * similar to changes in ip_fw.c in DaveM's CVS970924 tree.
+ * Paul Russell <Paul.Russell@rustcorp.com.au>
+ * 2-Nov-1997: Moved types across to __u16, etc.
+ * Added inverse flags.
+ * Fixed fragment bug (in args to port_match).
+ * Changed mark to only one flag (MARKABS).
+ * 21-Nov-1997: Added ability to test ICMP code.
+ * 19-Jan-1998: Added wildcard interfaces.
+ * 6-Feb-1998: Merged 2.0 and 2.1 versions.
+ * Initialised ip_masq for 2.0.x version.
+ * Added explicit NETLINK option for 2.1.x version.
+ * Added packet and byte counters for policy matches.
+ * 26-Feb-1998: Fixed race conditions, added SMP support.
+ * 18-Mar-1998: Fix SMP, fix race condition fix.
+ * 1-May-1998: Remove caching of device pointer.
+ * 12-May-1998: Allow tiny fragment case for TCP/UDP.
+ * 15-May-1998: Treat short packets as fragments, don't just block.
+ * 3-Jan-1999: Fixed serious procfs security hole -- users should never
+ * be allowed to view the chains!
+ * Marc Santoro <ultima@snicker.emoti.com>
+ * 29-Jan-1999: Locally generated bogus IPs dealt with, rather than crash
+ * during dump_packet. --RR.
+ * 19-May-1999: Star Wars: The Phantom Menace opened. Rule num
+ * printed in log (modified from Michael Hasenstein's patch).
+ * Added SYN in log message. --RR
+ * 23-Jul-1999: Fixed small fragment security exposure opened on 15-May-1998.
+ * John McDonald <jm@dataprotect.com>
+ * Thomas Lopatic <tl@dataprotect.com>
+ */
+
+/*
+ *
+ * The origina Linux port was done Alan Cox, with changes/fixes from
+ * Pauline Middlelink, Jos Vos, Thomas Quinot, Wouter Gadeyne, Juan
+ * Jose Ciarlante, Bernd Eckenfels, Keith Owens and others.
+ *
+ * Copyright from the original FreeBSD version follows:
+ *
+ * Copyright (c) 1993 Daniel Boulet
+ * Copyright (c) 1994 Ugen J.S.Antsilevich
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind. */
+
+
+#include <linux/config.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/icmp.h>
+#include <linux/udp.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <linux/netlink.h>
+#include <linux/init.h>
+#include <linux/firewall.h>
+#include <linux/ip_fw.h>
+
+#ifdef CONFIG_IP_MASQUERADE
+#include <net/ip_masq.h>
+#endif
+
+#include <net/checksum.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+
+/* Understanding locking in this code: (thanks to Alan Cox for using
+ * little words to explain this to me). -- PR
+ *
+ * In UP, there can be two packets traversing the chains:
+ * 1) A packet from the current userspace context
+ * 2) A packet off the bh handlers (timer or net).
+ *
+ * For SMP (kernel v2.1+), multiply this by # CPUs.
+ *
+ * [Note that this in not correct for 2.2 - because the socket code always
+ * uses lock_kernel() to serialize, and bottom halves (timers and net_bhs)
+ * only run on one CPU at a time. This will probably change for 2.3.
+ * It is still good to use spinlocks because that avoids the global cli()
+ * for updating the tables, which is rather costly in SMP kernels -AK]
+ *
+ * This means counters and backchains can get corrupted if no precautions
+ * are taken.
+ *
+ * To actually alter a chain on UP, we need only do a cli(), as this will
+ * stop a bh handler firing, as we are in the current userspace context
+ * (coming from a setsockopt()).
+ *
+ * On SMP, we need a write_lock_irqsave(), which is a simple cli() in
+ * UP.
+ *
+ * For backchains and counters, we use an array, indexed by
+ * [cpu_number_map[smp_processor_id()]*2 + !in_interrupt()]; the array is of
+ * size [smp_num_cpus*2]. For v2.0, smp_num_cpus is effectively 1. So,
+ * confident of uniqueness, we modify counters even though we only
+ * have a read lock (to read the counters, you need a write lock,
+ * though). */
+
+/* Why I didn't use straight locking... -- PR
+ *
+ * The backchains can be separated out of the ip_chains structure, and
+ * allocated as needed inside ip_fw_check().
+ *
+ * The counters, however, can't. Trying to lock these means blocking
+ * interrupts every time we want to access them. This would suck HARD
+ * performance-wise. Not locking them leads to possible corruption,
+ * made worse on 32-bit machines (counters are 64-bit). */
+
+/*#define DEBUG_IP_FIREWALL*/
+/*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
+/*#define DEBUG_IP_FIREWALL_USER*/
+/*#define DEBUG_IP_FIREWALL_LOCKING*/
+
+#ifdef CONFIG_IP_FIREWALL_NETLINK
+static struct sock *ipfwsk;
+#endif
+
+#ifdef __SMP__
+#define SLOT_NUMBER() (cpu_number_map[smp_processor_id()]*2 + !in_interrupt())
+#else
+#define SLOT_NUMBER() (!in_interrupt())
+#endif
+#define NUM_SLOTS (smp_num_cpus*2)
+
+#define SIZEOF_STRUCT_IP_CHAIN (sizeof(struct ip_chain) \
+ + NUM_SLOTS*sizeof(struct ip_reent))
+#define SIZEOF_STRUCT_IP_FW_KERNEL (sizeof(struct ip_fwkernel) \
+ + NUM_SLOTS*sizeof(struct ip_counters))
+
+#ifdef DEBUG_IP_FIREWALL_LOCKING
+static unsigned int fwc_rlocks, fwc_wlocks;
+#define FWC_DEBUG_LOCK(d) \
+do { \
+ FWC_DONT_HAVE_LOCK(d); \
+ d |= (1 << SLOT_NUMBER()); \
+} while (0)
+
+#define FWC_DEBUG_UNLOCK(d) \
+do { \
+ FWC_HAVE_LOCK(d); \
+ d &= ~(1 << SLOT_NUMBER()); \
+} while (0)
+
+#define FWC_DONT_HAVE_LOCK(d) \
+do { \
+ if ((d) & (1 << SLOT_NUMBER())) \
+ printk("%s:%i: Got lock on %i already!\n", \
+ __FILE__, __LINE__, SLOT_NUMBER()); \
+} while(0)
+
+#define FWC_HAVE_LOCK(d) \
+do { \
+ if (!((d) & (1 << SLOT_NUMBER()))) \
+ printk("%s:%i:No lock on %i!\n", \
+ __FILE__, __LINE__, SLOT_NUMBER()); \
+} while (0)
+
+#else
+#define FWC_DEBUG_LOCK(d) do { } while(0)
+#define FWC_DEBUG_UNLOCK(d) do { } while(0)
+#define FWC_DONT_HAVE_LOCK(d) do { } while(0)
+#define FWC_HAVE_LOCK(d) do { } while(0)
+#endif /*DEBUG_IP_FIRWALL_LOCKING*/
+
+#define FWC_READ_LOCK(l) do { FWC_DEBUG_LOCK(fwc_rlocks); read_lock(l); } while (0)
+#define FWC_WRITE_LOCK(l) do { FWC_DEBUG_LOCK(fwc_wlocks); write_lock(l); } while (0)
+#define FWC_READ_LOCK_IRQ(l,f) do { FWC_DEBUG_LOCK(fwc_rlocks); read_lock_irqsave(l,f); } while (0)
+#define FWC_WRITE_LOCK_IRQ(l,f) do { FWC_DEBUG_LOCK(fwc_wlocks); write_lock_irqsave(l,f); } while (0)
+#define FWC_READ_UNLOCK(l) do { FWC_DEBUG_UNLOCK(fwc_rlocks); read_unlock(l); } while (0)
+#define FWC_WRITE_UNLOCK(l) do { FWC_DEBUG_UNLOCK(fwc_wlocks); write_unlock(l); } while (0)
+#define FWC_READ_UNLOCK_IRQ(l,f) do { FWC_DEBUG_UNLOCK(fwc_rlocks); read_unlock_irqrestore(l,f); } while (0)
+#define FWC_WRITE_UNLOCK_IRQ(l,f) do { FWC_DEBUG_UNLOCK(fwc_wlocks); write_unlock_irqrestore(l,f); } while (0)
+
+struct ip_chain;
+
+struct ip_counters
+{
+ __u64 pcnt, bcnt; /* Packet and byte counters */
+};
+
+struct ip_fwkernel
+{
+ struct ip_fw ipfw;
+ struct ip_fwkernel *next; /* where to go next if current
+ * rule doesn't match */
+ struct ip_chain *branch; /* which branch to jump to if
+ * current rule matches */
+ int simplebranch; /* Use this if branch == NULL */
+ struct ip_counters counters[0]; /* Actually several of these */
+};
+
+struct ip_reent
+{
+ struct ip_chain *prevchain; /* Pointer to referencing chain */
+ struct ip_fwkernel *prevrule; /* Pointer to referencing rule */
+ struct ip_counters counters;
+};
+
+struct ip_chain
+{
+ ip_chainlabel label; /* Defines the label for each block */
+ struct ip_chain *next; /* Pointer to next block */
+ struct ip_fwkernel *chain; /* Pointer to first rule in block */
+ __u32 refcount; /* Number of refernces to block */
+ int policy; /* Default rule for chain. Only *
+ * used in built in chains */
+ struct ip_reent reent[0]; /* Actually several of these */
+};
+
+/*
+ * Implement IP packet firewall
+ */
+
+#ifdef DEBUG_IP_FIREWALL
+#define dprintf(format, args...) printk(format , ## args)
+#else
+#define dprintf(format, args...)
+#endif
+
+#ifdef DEBUG_IP_FIREWALL_USER
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Lock around ip_fw_chains linked list structure */
+rwlock_t ip_fw_lock = RW_LOCK_UNLOCKED;
+
+/* Head of linked list of fw rules */
+static struct ip_chain *ip_fw_chains;
+
+#define IP_FW_INPUT_CHAIN ip_fw_chains
+#define IP_FW_FORWARD_CHAIN (ip_fw_chains->next)
+#define IP_FW_OUTPUT_CHAIN (ip_fw_chains->next->next)
+
+/* Returns 1 if the port is matched by the range, 0 otherwise */
+extern inline int port_match(__u16 min, __u16 max, __u16 port,
+ int frag, int invert)
+{
+ if (frag) /* Fragments fail ANY port test. */
+ return (min == 0 && max == 0xFFFF);
+ else return (port >= min && port <= max) ^ invert;
+}
+
+/* Returns whether matches rule or not. */
+static int ip_rule_match(struct ip_fwkernel *f,
+ const char *ifname,
+ struct iphdr *ip,
+ char tcpsyn,
+ __u16 src_port, __u16 dst_port,
+ char isfrag)
+{
+#define FWINV(bool,invflg) ((bool) ^ !!(f->ipfw.fw_invflg & invflg))
+ /*
+ * This is a bit simpler as we don't have to walk
+ * an interface chain as you do in BSD - same logic
+ * however.
+ */
+
+ if (FWINV((ip->saddr&f->ipfw.fw_smsk.s_addr) != f->ipfw.fw_src.s_addr,
+ IP_FW_INV_SRCIP)
+ || FWINV((ip->daddr&f->ipfw.fw_dmsk.s_addr)!=f->ipfw.fw_dst.s_addr,
+ IP_FW_INV_DSTIP)) {
+ dprintf("Source or dest mismatch.\n");
+
+ dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
+ f->ipfw.fw_smsk.s_addr, f->ipfw.fw_src.s_addr,
+ f->ipfw.fw_invflg & IP_FW_INV_SRCIP ? " (INV)" : "");
+ dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
+ f->ipfw.fw_dmsk.s_addr, f->ipfw.fw_dst.s_addr,
+ f->ipfw.fw_invflg & IP_FW_INV_DSTIP ? " (INV)" : "");
+ return 0;
+ }
+
+ /*
+ * Look for a VIA device match
+ */
+ if (f->ipfw.fw_flg & IP_FW_F_WILDIF) {
+ if (FWINV(strncmp(ifname, f->ipfw.fw_vianame,
+ strlen(f->ipfw.fw_vianame)) != 0,
+ IP_FW_INV_VIA)) {
+ dprintf("Wildcard interface mismatch.%s\n",
+ f->ipfw.fw_invflg & IP_FW_INV_VIA ? " (INV)" : "");
+ return 0; /* Mismatch */
+ }
+ }
+ else if (FWINV(strcmp(ifname, f->ipfw.fw_vianame) != 0,
+ IP_FW_INV_VIA)) {
+ dprintf("Interface name does not match.%s\n",
+ f->ipfw.fw_invflg & IP_FW_INV_VIA
+ ? " (INV)" : "");
+ return 0; /* Mismatch */
+ }
+
+ /*
+ * Ok the chain addresses match.
+ */
+
+ /* If we have a fragment rule but the packet is not a fragment
+ * the we return zero */
+ if (FWINV((f->ipfw.fw_flg&IP_FW_F_FRAG) && !isfrag, IP_FW_INV_FRAG)) {
+ dprintf("Fragment rule but not fragment.%s\n",
+ f->ipfw.fw_invflg & IP_FW_INV_FRAG ? " (INV)" : "");
+ return 0;
+ }
+
+ /* Fragment NEVER passes a SYN test, even an inverted one. */
+ if (FWINV((f->ipfw.fw_flg&IP_FW_F_TCPSYN) && !tcpsyn, IP_FW_INV_SYN)
+ || (isfrag && (f->ipfw.fw_flg&IP_FW_F_TCPSYN))) {
+ dprintf("Rule requires SYN and packet has no SYN.%s\n",
+ f->ipfw.fw_invflg & IP_FW_INV_SYN ? " (INV)" : "");
+ return 0;
+ }
+
+ if (f->ipfw.fw_proto) {
+ /*
+ * Specific firewall - packet's protocol
+ * must match firewall's.
+ */
+
+ if (FWINV(ip->protocol!=f->ipfw.fw_proto, IP_FW_INV_PROTO)) {
+ dprintf("Packet protocol %hi does not match %hi.%s\n",
+ ip->protocol, f->ipfw.fw_proto,
+ f->ipfw.fw_invflg&IP_FW_INV_PROTO ? " (INV)":"");
+ return 0;
+ }
+
+ /* For non TCP/UDP/ICMP, port range is max anyway. */
+ if (!port_match(f->ipfw.fw_spts[0],
+ f->ipfw.fw_spts[1],
+ src_port, isfrag,
+ !!(f->ipfw.fw_invflg&IP_FW_INV_SRCPT))
+ || !port_match(f->ipfw.fw_dpts[0],
+ f->ipfw.fw_dpts[1],
+ dst_port, isfrag,
+ !!(f->ipfw.fw_invflg
+ &IP_FW_INV_DSTPT))) {
+ dprintf("Port match failed.\n");
+ return 0;
+ }
+ }
+
+ dprintf("Match succeeded.\n");
+ return 1;
+}
+
+static const char *branchname(struct ip_chain *branch,int simplebranch)
+{
+ if (branch)
+ return branch->label;
+ switch (simplebranch)
+ {
+ case FW_BLOCK: return IP_FW_LABEL_BLOCK;
+ case FW_ACCEPT: return IP_FW_LABEL_ACCEPT;
+ case FW_REJECT: return IP_FW_LABEL_REJECT;
+ case FW_REDIRECT: return IP_FW_LABEL_REDIRECT;
+ case FW_MASQUERADE: return IP_FW_LABEL_MASQUERADE;
+ case FW_SKIP: return "-";
+ case FW_SKIP+1: return IP_FW_LABEL_RETURN;
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/*
+ * VERY ugly piece of code which actually
+ * makes kernel printf for matching packets...
+ */
+static void dump_packet(const struct iphdr *ip,
+ const char *ifname,
+ struct ip_fwkernel *f,
+ const ip_chainlabel chainlabel,
+ __u16 src_port,
+ __u16 dst_port,
+ unsigned int count,
+ int syn)
+{
+ __u32 *opt = (__u32 *) (ip + 1);
+ int opti;
+
+ if (f)
+ {
+ printk(KERN_INFO "Packet log: %s ",chainlabel);
+
+ printk("%s ",branchname(f->branch,f->simplebranch));
+ if (f->simplebranch==FW_REDIRECT)
+ printk("%d ",f->ipfw.fw_redirpt);
+ }
+
+ printk("%s PROTO=%d %ld.%ld.%ld.%ld:%hu %ld.%ld.%ld.%ld:%hu"
+ " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
+ ifname, ip->protocol,
+ (ntohl(ip->saddr)>>24)&0xFF,
+ (ntohl(ip->saddr)>>16)&0xFF,
+ (ntohl(ip->saddr)>>8)&0xFF,
+ (ntohl(ip->saddr))&0xFF,
+ src_port,
+ (ntohl(ip->daddr)>>24)&0xFF,
+ (ntohl(ip->daddr)>>16)&0xFF,
+ (ntohl(ip->daddr)>>8)&0xFF,
+ (ntohl(ip->daddr))&0xFF,
+ dst_port,
+ ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
+ ntohs(ip->frag_off), ip->ttl);
+
+ for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
+ printk(" O=0x%8.8X", *opt++);
+ printk(" %s(#%d)\n", syn ? "SYN " : /* "PENANCE" */ "", count);
+}
+
+/* function for checking chain labels for user space. */
+static int check_label(ip_chainlabel label)
+{
+ unsigned int i;
+ /* strlen must be < IP_FW_MAX_LABEL_LENGTH. */
+ for (i = 0; i < IP_FW_MAX_LABEL_LENGTH + 1; i++)
+ if (label[i] == '\0') return 1;
+
+ return 0;
+}
+
+/* This function returns a pointer to the first chain with a label
+ * that matches the one given. */
+static struct ip_chain *find_label(ip_chainlabel label)
+{
+ struct ip_chain *tmp;
+ FWC_HAVE_LOCK(fwc_rlocks | fwc_wlocks);
+ for (tmp = ip_fw_chains; tmp; tmp = tmp->next)
+ if (strcmp(tmp->label,label) == 0)
+ break;
+ return tmp;
+}
+
+/* This function returns a boolean which when true sets answer to one
+ of the FW_*. */
+static int find_special(ip_chainlabel label, int *answer)
+{
+ if (label[0] == '\0') {
+ *answer = FW_SKIP; /* => pass-through rule */
+ return 1;
+ } else if (strcmp(label,IP_FW_LABEL_ACCEPT) == 0) {
+ *answer = FW_ACCEPT;
+ return 1;
+ } else if (strcmp(label,IP_FW_LABEL_BLOCK) == 0) {
+ *answer = FW_BLOCK;
+ return 1;
+ } else if (strcmp(label,IP_FW_LABEL_REJECT) == 0) {
+ *answer = FW_REJECT;
+ return 1;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ } else if (strcmp(label,IP_FW_LABEL_REDIRECT) == 0) {
+ *answer = FW_REDIRECT;
+ return 1;
+#endif
+#ifdef CONFIG_IP_MASQUERADE
+ } else if (strcmp(label,IP_FW_LABEL_MASQUERADE) == 0) {
+ *answer = FW_MASQUERADE;
+ return 1;
+#endif
+ } else if (strcmp(label, IP_FW_LABEL_RETURN) == 0) {
+ *answer = FW_SKIP+1;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* This function cleans up the prevchain and prevrule. If the verbose
+ * flag is set then he names of the chains will be printed as it
+ * cleans up. */
+static void cleanup(struct ip_chain *chain,
+ const int verbose,
+ unsigned int slot)
+{
+ struct ip_chain *tmpchain = chain->reent[slot].prevchain;
+ if (verbose)
+ printk(KERN_ERR "Chain backtrace: ");
+ while (tmpchain) {
+ if (verbose)
+ printk("%s<-",chain->label);
+ chain->reent[slot].prevchain = NULL;
+ chain = tmpchain;
+ tmpchain = chain->reent[slot].prevchain;
+ }
+ if (verbose)
+ printk("%s\n",chain->label);
+}
+
+static inline int
+ip_fw_domatch(struct ip_fwkernel *f,
+ struct iphdr *ip,
+ const char *rif,
+ const ip_chainlabel label,
+ struct sk_buff *skb,
+ unsigned int slot,
+ __u16 src_port, __u16 dst_port,
+ unsigned int count,
+ int tcpsyn)
+{
+ f->counters[slot].bcnt+=ntohs(ip->tot_len);
+ f->counters[slot].pcnt++;
+ if (f->ipfw.fw_flg & IP_FW_F_PRN) {
+ dump_packet(ip,rif,f,label,src_port,dst_port,count,tcpsyn);
+ }
+ ip->tos = (ip->tos & f->ipfw.fw_tosand) ^ f->ipfw.fw_tosxor;
+
+/* This functionality is useless in stock 2.0.x series, but we don't
+ * discard the mark thing altogether, to avoid breaking ipchains (and,
+ * more importantly, the ipfwadm wrapper) --PR */
+ if (f->ipfw.fw_flg & IP_FW_F_MARKABS)
+ skb->fwmark = f->ipfw.fw_mark;
+ else
+ skb->fwmark+=f->ipfw.fw_mark;
+#ifdef CONFIG_IP_FIREWALL_NETLINK
+ if (f->ipfw.fw_flg & IP_FW_F_NETLINK) {
+ size_t len = min(f->ipfw.fw_outputsize, ntohs(ip->tot_len))
+ + sizeof(__u32) + sizeof(skb->fwmark) + IFNAMSIZ;
+ struct sk_buff *outskb=alloc_skb(len, GFP_ATOMIC);
+
+ duprintf("Sending packet out NETLINK (length = %u).\n",
+ (unsigned int)len);
+ if (outskb) {
+ /* Prepend length, mark & interface */
+ skb_put(outskb, len);
+ *((__u32 *)outskb->data) = (__u32)len;
+ *((__u32 *)(outskb->data+sizeof(__u32))) = skb->fwmark;
+ strcpy(outskb->data+sizeof(__u32)*2, rif);
+ memcpy(outskb->data+sizeof(__u32)*2+IFNAMSIZ, ip,
+ len-(sizeof(__u32)*2+IFNAMSIZ));
+ netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_KERNEL);
+ }
+ else {
+ if (net_ratelimit())
+ printk(KERN_WARNING "ip_fw: packet drop due to "
+ "netlink failure\n");
+ return 0;
+ }
+ }
+#endif
+ return 1;
+}
+
+/*
+ * Returns one of the generic firewall policies, like FW_ACCEPT.
+ *
+ * The testing is either false for normal firewall mode or true for
+ * user checking mode (counters are not updated, TOS & mark not done).
+ */
+static int
+ip_fw_check(struct iphdr *ip,
+ const char *rif,
+ __u16 *redirport,
+ struct ip_chain *chain,
+ struct sk_buff *skb,
+ unsigned int slot,
+ int testing)
+{
+ struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
+ struct udphdr *udp=(struct udphdr *)((__u32 *)ip+ip->ihl);
+ struct icmphdr *icmp=(struct icmphdr *)((__u32 *)ip+ip->ihl);
+ __u32 src, dst;
+ __u16 src_port = 0xFFFF, dst_port = 0xFFFF;
+ char tcpsyn=0;
+ __u16 offset;
+ unsigned char oldtos;
+ struct ip_fwkernel *f;
+ int ret = FW_SKIP+2;
+ unsigned int count;
+
+ /* We handle fragments by dealing with the first fragment as
+ * if it was a normal packet. All other fragments are treated
+ * normally, except that they will NEVER match rules that ask
+ * things we don't know, ie. tcp syn flag or ports). If the
+ * rule is also a fragment-specific rule, non-fragments won't
+ * match it. */
+
+ offset = ntohs(ip->frag_off) & IP_OFFSET;
+
+ /*
+ * Don't allow a fragment of TCP 8 bytes in. Nobody
+ * normal causes this. Its a cracker trying to break
+ * in by doing a flag overwrite to pass the direction
+ * checks.
+ */
+
+ if (offset == 1 && ip->protocol == IPPROTO_TCP) {
+ if (!testing && net_ratelimit()) {
+ printk("Suspect TCP fragment.\n");
+ dump_packet(ip,rif,NULL,NULL,0,0,0,0);
+ }
+ return FW_BLOCK;
+ }
+
+ /* If we can't investigate ports, treat as fragment. It's
+ * either a trucated whole packet, or a truncated first
+ * fragment, or a TCP first fragment of length 8-15, in which
+ * case the above rule stops reassembly.
+ */
+ if (offset == 0) {
+ unsigned int size_req;
+ switch (ip->protocol) {
+ case IPPROTO_TCP:
+ /* Don't care about things past flags word */
+ size_req = 16;
+ break;
+
+ case IPPROTO_UDP:
+ case IPPROTO_ICMP:
+ size_req = 8;
+ break;
+
+ default:
+ size_req = 0;
+ }
+ offset = (ntohs(ip->tot_len) < (ip->ihl<<2)+size_req);
+
+ /* If it is a truncated first fragment then it can be
+ * used to rewrite port information, and thus should
+ * be blocked.
+ */
+ if (offset && (ntohs(ip->frag_off) & IP_MF)) {
+ if (!testing && net_ratelimit()) {
+ printk("Suspect short first fragment.\n");
+ dump_packet(ip,rif,NULL,NULL,0,0,0,0);
+ }
+ return FW_BLOCK;
+ }
+ }
+
+ src = ip->saddr;
+ dst = ip->daddr;
+ oldtos = ip->tos;
+
+ /*
+ * If we got interface from which packet came
+ * we can use the address directly. Linux 2.1 now uses address
+ * chains per device too, but unlike BSD we first check if the
+ * incoming packet matches a device address and the routing
+ * table before calling the firewall.
+ */
+
+ dprintf("Packet ");
+ switch(ip->protocol)
+ {
+ case IPPROTO_TCP:
+ dprintf("TCP ");
+ if (!offset) {
+ src_port=ntohs(tcp->source);
+ dst_port=ntohs(tcp->dest);
+
+ /* Connection initilisation can only
+ * be made when the syn bit is set and
+ * neither of the ack or reset is
+ * set. */
+ if(tcp->syn && !(tcp->ack || tcp->rst))
+ tcpsyn=1;
+ }
+ break;
+ case IPPROTO_UDP:
+ dprintf("UDP ");
+ if (!offset) {
+ src_port=ntohs(udp->source);
+ dst_port=ntohs(udp->dest);
+ }
+ break;
+ case IPPROTO_ICMP:
+ if (!offset) {
+ src_port=(__u16)icmp->type;
+ dst_port=(__u16)icmp->code;
+ }
+ dprintf("ICMP ");
+ break;
+ default:
+ dprintf("p=%d ",ip->protocol);
+ break;
+ }
+#ifdef DEBUG_IP_FIREWALL
+ print_ip(ip->saddr);
+
+ if (offset)
+ dprintf(":fragment (%i) ", ((int)offset)<<2);
+ else if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP
+ || ip->protocol==IPPROTO_ICMP)
+ dprintf(":%hu:%hu", src_port, dst_port);
+ dprintf("\n");
+#endif
+
+ if (!testing) FWC_READ_LOCK(&ip_fw_lock);
+ else FWC_HAVE_LOCK(fwc_rlocks);
+
+ f = chain->chain;
+ do {
+ count = 0;
+ for (; f; f = f->next) {
+ count++;
+ if (ip_rule_match(f,rif,ip,
+ tcpsyn,src_port,dst_port,offset)) {
+ if (!testing
+ && !ip_fw_domatch(f, ip, rif, chain->label,
+ skb, slot,
+ src_port, dst_port,
+ count, tcpsyn)) {
+ ret = FW_BLOCK;
+ goto out;
+ }
+ break;
+ }
+ }
+ if (f) {
+ if (f->branch) {
+ /* Do sanity check to see if we have
+ * already set prevchain and if so we
+ * must be in a loop */
+ if (f->branch->reent[slot].prevchain) {
+ if (!testing) {
+ printk(KERN_ERR
+ "IP firewall: "
+ "Loop detected "
+ "at `%s'.\n",
+ f->branch->label);
+ cleanup(chain, 1, slot);
+ ret = FW_BLOCK;
+ } else {
+ cleanup(chain, 0, slot);
+ ret = FW_SKIP+1;
+ }
+ }
+ else {
+ f->branch->reent[slot].prevchain
+ = chain;
+ f->branch->reent[slot].prevrule
+ = f->next;
+ chain = f->branch;
+ f = chain->chain;
+ }
+ }
+ else if (f->simplebranch == FW_SKIP)
+ f = f->next;
+ else if (f->simplebranch == FW_SKIP+1) {
+ /* Just like falling off the chain */
+ goto fall_off_chain;
+ }
+ else {
+ cleanup(chain, 0, slot);
+ ret = f->simplebranch;
+ }
+ } /* f == NULL */
+ else {
+ fall_off_chain:
+ if (chain->reent[slot].prevchain) {
+ struct ip_chain *tmp = chain;
+ f = chain->reent[slot].prevrule;
+ chain = chain->reent[slot].prevchain;
+ tmp->reent[slot].prevchain = NULL;
+ }
+ else {
+ ret = chain->policy;
+ if (!testing) {
+ chain->reent[slot].counters.pcnt++;
+ chain->reent[slot].counters.bcnt
+ += ntohs(ip->tot_len);
+ }
+ }
+ }
+ } while (ret == FW_SKIP+2);
+
+ out:
+ if (!testing) FWC_READ_UNLOCK(&ip_fw_lock);
+
+ /* Recalculate checksum if not going to reject, and TOS changed. */
+ if (ip->tos != oldtos
+ && ret != FW_REJECT && ret != FW_BLOCK
+ && !testing)
+ ip_send_check(ip);
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (ret == FW_REDIRECT && redirport) {
+ if ((*redirport = htons(f->ipfw.fw_redirpt)) == 0) {
+ /* Wildcard redirection.
+ * Note that redirport will become
+ * 0xFFFF for non-TCP/UDP packets.
+ */
+ *redirport = htons(dst_port);
+ }
+ }
+#endif
+
+#ifdef DEBUG_ALLOW_ALL
+ return (testing ? ret : FW_ACCEPT);
+#else
+ return ret;
+#endif
+}
+
+/* Must have write lock & interrupts off for any of these */
+
+/* This function sets all the byte counters in a chain to zero. The
+ * input is a pointer to the chain required for zeroing */
+static int zero_fw_chain(struct ip_chain *chainptr)
+{
+ struct ip_fwkernel *i;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+ for (i = chainptr->chain; i; i = i->next)
+ memset(i->counters, 0, sizeof(struct ip_counters)*NUM_SLOTS);
+ return 0;
+}
+
+static int clear_fw_chain(struct ip_chain *chainptr)
+{
+ struct ip_fwkernel *i= chainptr->chain;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+ chainptr->chain=NULL;
+
+ while (i) {
+ struct ip_fwkernel *tmp = i->next;
+ if (i->branch)
+ i->branch->refcount--;
+ kfree(i);
+ i = tmp;
+ }
+ return 0;
+}
+
+static int replace_in_chain(struct ip_chain *chainptr,
+ struct ip_fwkernel *frwl,
+ __u32 position)
+{
+ struct ip_fwkernel *f = chainptr->chain;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+
+ while (--position && f != NULL) f = f->next;
+ if (f == NULL)
+ return EINVAL;
+
+ if (f->branch) f->branch->refcount--;
+ if (frwl->branch) frwl->branch->refcount++;
+
+ frwl->next = f->next;
+ memcpy(f,frwl,sizeof(struct ip_fwkernel));
+ kfree(frwl);
+ return 0;
+}
+
+static int append_to_chain(struct ip_chain *chainptr, struct ip_fwkernel *rule)
+{
+ struct ip_fwkernel *i;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+ /* Special case if no rules already present */
+ if (chainptr->chain == NULL) {
+
+ /* If pointer writes are atomic then turning off
+ * interupts is not necessary. */
+ chainptr->chain = rule;
+ if (rule->branch) rule->branch->refcount++;
+ return 0;
+ }
+
+ /* Find the rule before the end of the chain */
+ for (i = chainptr->chain; i->next; i = i->next);
+ i->next = rule;
+ if (rule->branch) rule->branch->refcount++;
+ return 0;
+}
+
+/* This function inserts a rule at the position of position in the
+ * chain refenced by chainptr. If position is 1 then this rule will
+ * become the new rule one. */
+static int insert_in_chain(struct ip_chain *chainptr,
+ struct ip_fwkernel *frwl,
+ __u32 position)
+{
+ struct ip_fwkernel *f = chainptr->chain;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+ /* special case if the position is number 1 */
+ if (position == 1) {
+ frwl->next = chainptr->chain;
+ if (frwl->branch) frwl->branch->refcount++;
+ chainptr->chain = frwl;
+ return 0;
+ }
+ position--;
+ while (--position && f != NULL) f = f->next;
+ if (f == NULL)
+ return EINVAL;
+ if (frwl->branch) frwl->branch->refcount++;
+ frwl->next = f->next;
+
+ f->next = frwl;
+ return 0;
+}
+
+/* This function deletes the a rule from a given rulenum and chain.
+ * With rulenum = 1 is the first rule is deleted. */
+
+static int del_num_from_chain(struct ip_chain *chainptr, __u32 rulenum)
+{
+ struct ip_fwkernel *i=chainptr->chain,*tmp;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+
+ if (!chainptr->chain)
+ return ENOENT;
+
+ /* Need a special case for the first rule */
+ if (rulenum == 1) {
+ /* store temp to allow for freeing up of memory */
+ tmp = chainptr->chain;
+ if (chainptr->chain->branch) chainptr->chain->branch->refcount--;
+ chainptr->chain = chainptr->chain->next;
+ kfree(tmp); /* free memory that is now unused */
+ } else {
+ rulenum--;
+ while (--rulenum && i->next ) i = i->next;
+ if (!i->next)
+ return ENOENT;
+ tmp = i->next;
+ if (i->next->branch)
+ i->next->branch->refcount--;
+ i->next = i->next->next;
+ kfree(tmp);
+ }
+ return 0;
+}
+
+
+/* This function deletes the a rule from a given rule and chain.
+ * The rule that is deleted is the first occursance of that rule. */
+static int del_rule_from_chain(struct ip_chain *chainptr,
+ struct ip_fwkernel *frwl)
+{
+ struct ip_fwkernel *ltmp,*ftmp = chainptr->chain ;
+ int was_found;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+
+ /* Sure, we should compare marks, but since the `ipfwadm'
+ * script uses it for an unholy hack... well, life is easier
+ * this way. We also mask it out of the flags word. --PR */
+ for (ltmp=NULL, was_found=0;
+ !was_found && ftmp != NULL;
+ ltmp = ftmp,ftmp = ftmp->next) {
+ if (ftmp->ipfw.fw_src.s_addr!=frwl->ipfw.fw_src.s_addr
+ || ftmp->ipfw.fw_dst.s_addr!=frwl->ipfw.fw_dst.s_addr
+ || ftmp->ipfw.fw_smsk.s_addr!=frwl->ipfw.fw_smsk.s_addr
+ || ftmp->ipfw.fw_dmsk.s_addr!=frwl->ipfw.fw_dmsk.s_addr
+#if 0
+ || ftmp->ipfw.fw_flg!=frwl->ipfw.fw_flg
+#else
+ || ((ftmp->ipfw.fw_flg & ~IP_FW_F_MARKABS)
+ != (frwl->ipfw.fw_flg & ~IP_FW_F_MARKABS))
+#endif
+ || ftmp->ipfw.fw_invflg!=frwl->ipfw.fw_invflg
+ || ftmp->ipfw.fw_proto!=frwl->ipfw.fw_proto
+#if 0
+ || ftmp->ipfw.fw_mark!=frwl->ipfw.fw_mark
+#endif
+ || ftmp->ipfw.fw_redirpt!=frwl->ipfw.fw_redirpt
+ || ftmp->ipfw.fw_spts[0]!=frwl->ipfw.fw_spts[0]
+ || ftmp->ipfw.fw_spts[1]!=frwl->ipfw.fw_spts[1]
+ || ftmp->ipfw.fw_dpts[0]!=frwl->ipfw.fw_dpts[0]
+ || ftmp->ipfw.fw_dpts[1]!=frwl->ipfw.fw_dpts[1]
+ || ftmp->ipfw.fw_outputsize!=frwl->ipfw.fw_outputsize) {
+ duprintf("del_rule_from_chain: mismatch:"
+ "src:%u/%u dst:%u/%u smsk:%u/%u dmsk:%u/%u "
+ "flg:%hX/%hX invflg:%hX/%hX proto:%u/%u "
+ "mark:%u/%u "
+ "ports:%hu-%hu/%hu-%hu %hu-%hu/%hu-%hu "
+ "outputsize:%hu-%hu\n",
+ ftmp->ipfw.fw_src.s_addr,
+ frwl->ipfw.fw_src.s_addr,
+ ftmp->ipfw.fw_dst.s_addr,
+ frwl->ipfw.fw_dst.s_addr,
+ ftmp->ipfw.fw_smsk.s_addr,
+ frwl->ipfw.fw_smsk.s_addr,
+ ftmp->ipfw.fw_dmsk.s_addr,
+ frwl->ipfw.fw_dmsk.s_addr,
+ ftmp->ipfw.fw_flg,
+ frwl->ipfw.fw_flg,
+ ftmp->ipfw.fw_invflg,
+ frwl->ipfw.fw_invflg,
+ ftmp->ipfw.fw_proto,
+ frwl->ipfw.fw_proto,
+ ftmp->ipfw.fw_mark,
+ frwl->ipfw.fw_mark,
+ ftmp->ipfw.fw_spts[0],
+ frwl->ipfw.fw_spts[0],
+ ftmp->ipfw.fw_spts[1],
+ frwl->ipfw.fw_spts[1],
+ ftmp->ipfw.fw_dpts[0],
+ frwl->ipfw.fw_dpts[0],
+ ftmp->ipfw.fw_dpts[1],
+ frwl->ipfw.fw_dpts[1],
+ ftmp->ipfw.fw_outputsize,
+ frwl->ipfw.fw_outputsize);
+ continue;
+ }
+
+ if (strncmp(ftmp->ipfw.fw_vianame,
+ frwl->ipfw.fw_vianame,
+ IFNAMSIZ)) {
+ duprintf("del_rule_from_chain: if mismatch: %s/%s\n",
+ ftmp->ipfw.fw_vianame,
+ frwl->ipfw.fw_vianame);
+ continue;
+ }
+ if (ftmp->branch != frwl->branch) {
+ duprintf("del_rule_from_chain: branch mismatch: "
+ "%s/%s\n",
+ ftmp->branch?ftmp->branch->label:"(null)",
+ frwl->branch?frwl->branch->label:"(null)");
+ continue;
+ }
+ if (ftmp->branch == NULL
+ && ftmp->simplebranch != frwl->simplebranch) {
+ duprintf("del_rule_from_chain: simplebranch mismatch: "
+ "%i/%i\n",
+ ftmp->simplebranch, frwl->simplebranch);
+ continue;
+ }
+ was_found = 1;
+ if (ftmp->branch)
+ ftmp->branch->refcount--;
+ if (ltmp)
+ ltmp->next = ftmp->next;
+ else
+ chainptr->chain = ftmp->next;
+ kfree(ftmp);
+ break;
+ }
+
+ if (was_found)
+ return 0;
+ else {
+ duprintf("del_rule_from_chain: no matching rule found\n");
+ return EINVAL;
+ }
+}
+
+/* This function takes the label of a chain and deletes the first
+ * chain with that name. No special cases required for the built in
+ * chains as they have their refcount initilised to 1 so that they are
+ * never deleted. */
+static int del_chain(ip_chainlabel label)
+{
+ struct ip_chain *tmp,*tmp2;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+ /* Corner case: return EBUSY not ENOENT for first elem ("input") */
+ if (strcmp(label, ip_fw_chains->label) == 0)
+ return EBUSY;
+
+ for (tmp = ip_fw_chains; tmp->next; tmp = tmp->next)
+ if(strcmp(tmp->next->label,label) == 0)
+ break;
+
+ tmp2 = tmp->next;
+ if (!tmp2)
+ return ENOENT;
+
+ if (tmp2->refcount)
+ return EBUSY;
+
+ if (tmp2->chain)
+ return ENOTEMPTY;
+
+ tmp->next = tmp2->next;
+ kfree(tmp2);
+ return 0;
+}
+
+/* This is a function to initilise a chain. Built in rules start with
+ * refcount = 1 so that they cannot be deleted. User defined rules
+ * start with refcount = 0 so they can be deleted. */
+static struct ip_chain *ip_init_chain(ip_chainlabel name,
+ __u32 ref,
+ int policy)
+{
+ unsigned int i;
+ struct ip_chain *label
+ = kmalloc(SIZEOF_STRUCT_IP_CHAIN, GFP_KERNEL);
+ if (label == NULL)
+ panic("Can't kmalloc for firewall chains.\n");
+ strcpy(label->label,name);
+ label->next = NULL;
+ label->chain = NULL;
+ label->refcount = ref;
+ label->policy = policy;
+ for (i = 0; i < smp_num_cpus*2; i++) {
+ label->reent[i].counters.pcnt = label->reent[i].counters.bcnt
+ = 0;
+ label->reent[i].prevchain = NULL;
+ label->reent[i].prevrule = NULL;
+ }
+
+ return label;
+}
+
+/* This is a function for reating a new chain. The chains is not
+ * created if a chain of the same name already exists */
+static int create_chain(ip_chainlabel label)
+{
+ struct ip_chain *tmp;
+
+ if (!check_label(label))
+ return EINVAL;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+ for (tmp = ip_fw_chains; tmp->next; tmp = tmp->next)
+ if (strcmp(tmp->label,label) == 0)
+ return EEXIST;
+
+ if (strcmp(tmp->label,label) == 0)
+ return EEXIST;
+
+ tmp->next = ip_init_chain(label, 0, FW_SKIP); /* refcount is
+ * zero since this is a
+ * user defined chain *
+ * and therefore can be
+ * deleted */
+ return 0;
+}
+
+/* This function simply changes the policy on one of the built in
+ * chains. checking must be done before this is call to ensure that
+ * chainptr is pointing to one of the three possible chains */
+static int change_policy(struct ip_chain *chainptr, int policy)
+{
+ FWC_HAVE_LOCK(fwc_wlocks);
+ chainptr->policy = policy;
+ return 0;
+}
+
+/* This function takes an ip_fwuser and converts it to a ip_fwkernel. It also
+ * performs some checks in the structure. */
+static struct ip_fwkernel *convert_ipfw(struct ip_fwuser *fwuser, int *errno)
+{
+ struct ip_fwkernel *fwkern;
+
+ if ( (fwuser->ipfw.fw_flg & ~IP_FW_F_MASK) != 0 ) {
+ duprintf("convert_ipfw: undefined flag bits set (flags=%x)\n",
+ fwuser->ipfw.fw_flg);
+ *errno = EINVAL;
+ return NULL;
+ }
+
+#ifdef DEBUG_IP_FIREWALL_USER
+ /* These are sanity checks that don't really matter.
+ * We can get rid of these once testing is complete.
+ */
+ if ((fwuser->ipfw.fw_flg & IP_FW_F_TCPSYN)
+ && ((fwuser->ipfw.fw_invflg & IP_FW_INV_PROTO)
+ || fwuser->ipfw.fw_proto != IPPROTO_TCP)) {
+ duprintf("convert_ipfw: TCP SYN flag set but proto != TCP!\n");
+ *errno = EINVAL;
+ return NULL;
+ }
+
+ if (strcmp(fwuser->label, IP_FW_LABEL_REDIRECT) != 0
+ && fwuser->ipfw.fw_redirpt != 0) {
+ duprintf("convert_ipfw: Target not REDIR but redirpt != 0!\n");
+ *errno = EINVAL;
+ return NULL;
+ }
+
+ if ((!(fwuser->ipfw.fw_flg & IP_FW_F_FRAG)
+ && (fwuser->ipfw.fw_invflg & IP_FW_INV_FRAG))
+ || (!(fwuser->ipfw.fw_flg & IP_FW_F_TCPSYN)
+ && (fwuser->ipfw.fw_invflg & IP_FW_INV_SYN))) {
+ duprintf("convert_ipfw: Can't have INV flag if flag unset!\n");
+ *errno = EINVAL;
+ return NULL;
+ }
+
+ if (((fwuser->ipfw.fw_invflg & IP_FW_INV_SRCPT)
+ && fwuser->ipfw.fw_spts[0] == 0
+ && fwuser->ipfw.fw_spts[1] == 0xFFFF)
+ || ((fwuser->ipfw.fw_invflg & IP_FW_INV_DSTPT)
+ && fwuser->ipfw.fw_dpts[0] == 0
+ && fwuser->ipfw.fw_dpts[1] == 0xFFFF)
+ || ((fwuser->ipfw.fw_invflg & IP_FW_INV_VIA)
+ && (fwuser->ipfw.fw_vianame)[0] == '\0')
+ || ((fwuser->ipfw.fw_invflg & IP_FW_INV_SRCIP)
+ && fwuser->ipfw.fw_smsk.s_addr == 0)
+ || ((fwuser->ipfw.fw_invflg & IP_FW_INV_DSTIP)
+ && fwuser->ipfw.fw_dmsk.s_addr == 0)) {
+ duprintf("convert_ipfw: INV flag makes rule unmatchable!\n");
+ *errno = EINVAL;
+ return NULL;
+ }
+
+ if ((fwuser->ipfw.fw_flg & IP_FW_F_FRAG)
+ && !(fwuser->ipfw.fw_invflg & IP_FW_INV_FRAG)
+ && (fwuser->ipfw.fw_spts[0] != 0
+ || fwuser->ipfw.fw_spts[1] != 0xFFFF
+ || fwuser->ipfw.fw_dpts[0] != 0
+ || fwuser->ipfw.fw_dpts[1] != 0xFFFF
+ || (fwuser->ipfw.fw_flg & IP_FW_F_TCPSYN))) {
+ duprintf("convert_ipfw: Can't test ports or SYN with frag!\n");
+ *errno = EINVAL;
+ return NULL;
+ }
+#endif
+
+ if ((fwuser->ipfw.fw_spts[0] != 0
+ || fwuser->ipfw.fw_spts[1] != 0xFFFF
+ || fwuser->ipfw.fw_dpts[0] != 0
+ || fwuser->ipfw.fw_dpts[1] != 0xFFFF)
+ && ((fwuser->ipfw.fw_invflg & IP_FW_INV_PROTO)
+ || (fwuser->ipfw.fw_proto != IPPROTO_TCP
+ && fwuser->ipfw.fw_proto != IPPROTO_UDP
+ && fwuser->ipfw.fw_proto != IPPROTO_ICMP))) {
+ duprintf("convert_ipfw: Can only test ports for TCP/UDP/ICMP!\n");
+ *errno = EINVAL;
+ return NULL;
+ }
+
+ fwkern = kmalloc(SIZEOF_STRUCT_IP_FW_KERNEL, GFP_KERNEL);
+ if (!fwkern) {
+ duprintf("convert_ipfw: kmalloc failed!\n");
+ *errno = ENOMEM;
+ return NULL;
+ }
+ memcpy(&fwkern->ipfw,&fwuser->ipfw,sizeof(struct ip_fw));
+
+ if (!find_special(fwuser->label, &fwkern->simplebranch)) {
+ fwkern->branch = find_label(fwuser->label);
+ if (!fwkern->branch) {
+ duprintf("convert_ipfw: chain doesn't exist `%s'.\n",
+ fwuser->label);
+ kfree(fwkern);
+ *errno = ENOENT;
+ return NULL;
+ } else if (fwkern->branch == IP_FW_INPUT_CHAIN
+ || fwkern->branch == IP_FW_FORWARD_CHAIN
+ || fwkern->branch == IP_FW_OUTPUT_CHAIN) {
+ duprintf("convert_ipfw: Can't branch to builtin chain `%s'.\n",
+ fwuser->label);
+ kfree(fwkern);
+ *errno = ENOENT;
+ return NULL;
+ }
+ } else
+ fwkern->branch = NULL;
+ memset(fwkern->counters, 0, sizeof(struct ip_counters)*NUM_SLOTS);
+
+ /* Handle empty vianame by making it a wildcard */
+ if ((fwkern->ipfw.fw_vianame)[0] == '\0')
+ fwkern->ipfw.fw_flg |= IP_FW_F_WILDIF;
+
+ fwkern->next = NULL;
+ return fwkern;
+}
+
+int ip_fw_ctl(int cmd, void *m, int len)
+{
+ int ret;
+ struct ip_chain *chain;
+ unsigned long flags;
+
+ FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
+
+ switch (cmd) {
+ case IP_FW_FLUSH:
+ if (len != sizeof(ip_chainlabel) || !check_label(m))
+ ret = EINVAL;
+ else if ((chain = find_label(m)) == NULL)
+ ret = ENOENT;
+ else ret = clear_fw_chain(chain);
+ break;
+
+ case IP_FW_ZERO:
+ if (len != sizeof(ip_chainlabel) || !check_label(m))
+ ret = EINVAL;
+ else if ((chain = find_label(m)) == NULL)
+ ret = ENOENT;
+ else ret = zero_fw_chain(chain);
+ break;
+
+ case IP_FW_CHECK: {
+ struct ip_fwtest *new = m;
+ struct iphdr *ip;
+
+ /* Don't need write lock. */
+ FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
+
+ if (len != sizeof(struct ip_fwtest) || !check_label(m))
+ return EINVAL;
+
+ /* Need readlock to do find_label */
+ FWC_READ_LOCK(&ip_fw_lock);
+
+ if ((chain = find_label(new->fwt_label)) == NULL)
+ ret = ENOENT;
+ else {
+ ip = &(new->fwt_packet.fwp_iph);
+
+ if (ip->ihl != sizeof(struct iphdr) / sizeof(int)) {
+ duprintf("ip_fw_ctl: ip->ihl=%d, want %d\n",
+ ip->ihl,
+ sizeof(struct iphdr) / sizeof(int));
+ ret = EINVAL;
+ }
+ else {
+ ret = ip_fw_check(ip, new->fwt_packet.fwp_vianame,
+ NULL, chain,
+ NULL, SLOT_NUMBER(), 1);
+ switch (ret) {
+ case FW_ACCEPT:
+ ret = 0; break;
+ case FW_REDIRECT:
+ ret = ECONNABORTED; break;
+ case FW_MASQUERADE:
+ ret = ECONNRESET; break;
+ case FW_REJECT:
+ ret = ECONNREFUSED; break;
+ /* Hack to help diag; these only get
+ returned when testing. */
+ case FW_SKIP+1:
+ ret = ELOOP; break;
+ case FW_SKIP:
+ ret = ENFILE; break;
+ default: /* FW_BLOCK */
+ ret = ETIMEDOUT; break;
+ }
+ }
+ }
+ FWC_READ_UNLOCK(&ip_fw_lock);
+ return ret;
+ }
+
+ case IP_FW_MASQ_TIMEOUTS: {
+#ifdef CONFIG_IP_MASQUERADE
+ ret = ip_fw_masq_timeouts(m, len);
+#else
+ ret = EINVAL;
+#endif
+ }
+ break;
+
+ case IP_FW_REPLACE: {
+ struct ip_fwkernel *ip_fwkern;
+ struct ip_fwnew *new = m;
+
+ if (len != sizeof(struct ip_fwnew)
+ || !check_label(new->fwn_label))
+ ret = EINVAL;
+ else if ((chain = find_label(new->fwn_label)) == NULL)
+ ret = ENOENT;
+ else if ((ip_fwkern = convert_ipfw(&new->fwn_rule, &ret))
+ != NULL)
+ ret = replace_in_chain(chain, ip_fwkern,
+ new->fwn_rulenum);
+ }
+ break;
+
+ case IP_FW_APPEND: {
+ struct ip_fwchange *new = m;
+ struct ip_fwkernel *ip_fwkern;
+
+ if (len != sizeof(struct ip_fwchange)
+ || !check_label(new->fwc_label))
+ ret = EINVAL;
+ else if ((chain = find_label(new->fwc_label)) == NULL)
+ ret = ENOENT;
+ else if ((ip_fwkern = convert_ipfw(&new->fwc_rule, &ret))
+ != NULL)
+ ret = append_to_chain(chain, ip_fwkern);
+ }
+ break;
+
+ case IP_FW_INSERT: {
+ struct ip_fwkernel *ip_fwkern;
+ struct ip_fwnew *new = m;
+
+ if (len != sizeof(struct ip_fwnew)
+ || !check_label(new->fwn_label))
+ ret = EINVAL;
+ else if ((chain = find_label(new->fwn_label)) == NULL)
+ ret = ENOENT;
+ else if ((ip_fwkern = convert_ipfw(&new->fwn_rule, &ret))
+ != NULL)
+ ret = insert_in_chain(chain, ip_fwkern,
+ new->fwn_rulenum);
+ }
+ break;
+
+ case IP_FW_DELETE: {
+ struct ip_fwchange *new = m;
+ struct ip_fwkernel *ip_fwkern;
+
+ if (len != sizeof(struct ip_fwchange)
+ || !check_label(new->fwc_label))
+ ret = EINVAL;
+ else if ((chain = find_label(new->fwc_label)) == NULL)
+ ret = ENOENT;
+ else if ((ip_fwkern = convert_ipfw(&new->fwc_rule, &ret))
+ != NULL) {
+ ret = del_rule_from_chain(chain, ip_fwkern);
+ kfree(ip_fwkern);
+ }
+ }
+ break;
+
+ case IP_FW_DELETE_NUM: {
+ struct ip_fwdelnum *new = m;
+
+ if (len != sizeof(struct ip_fwdelnum)
+ || !check_label(new->fwd_label))
+ ret = EINVAL;
+ else if ((chain = find_label(new->fwd_label)) == NULL)
+ ret = ENOENT;
+ else ret = del_num_from_chain(chain, new->fwd_rulenum);
+ }
+ break;
+
+ case IP_FW_CREATECHAIN: {
+ if (len != sizeof(ip_chainlabel)) {
+ duprintf("create_chain: bad size %i\n", len);
+ ret = EINVAL;
+ }
+ else ret = create_chain(m);
+ }
+ break;
+
+ case IP_FW_DELETECHAIN: {
+ if (len != sizeof(ip_chainlabel)) {
+ duprintf("delete_chain: bad size %i\n", len);
+ ret = EINVAL;
+ }
+ else ret = del_chain(m);
+ }
+ break;
+
+ case IP_FW_POLICY: {
+ struct ip_fwpolicy *new = m;
+
+ if (len != sizeof(struct ip_fwpolicy)
+ || !check_label(new->fwp_label))
+ ret = EINVAL;
+ else if ((chain = find_label(new->fwp_label)) == NULL)
+ ret = ENOENT;
+ else if (chain != IP_FW_INPUT_CHAIN
+ && chain != IP_FW_FORWARD_CHAIN
+ && chain != IP_FW_OUTPUT_CHAIN) {
+ duprintf("change_policy: can't change policy on user"
+ " defined chain.\n");
+ ret = EINVAL;
+ }
+ else {
+ int pol = FW_SKIP;
+ find_special(new->fwp_policy, &pol);
+
+ switch(pol) {
+ case FW_MASQUERADE:
+ if (chain != IP_FW_FORWARD_CHAIN) {
+ ret = EINVAL;
+ break;
+ }
+ /* Fall thru... */
+ case FW_BLOCK:
+ case FW_ACCEPT:
+ case FW_REJECT:
+ ret = change_policy(chain, pol);
+ break;
+ default:
+ duprintf("change_policy: bad policy `%s'\n",
+ new->fwp_policy);
+ ret = EINVAL;
+ }
+ }
+ break;
+
+ }
+ default:
+ duprintf("ip_fw_ctl: unknown request %d\n",cmd);
+ ret = EINVAL;
+ }
+
+ FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
+ return ret;
+}
+
+/* Returns bytes used - doesn't NUL terminate */
+static int dump_rule(char *buffer,
+ const char *chainlabel,
+ const struct ip_fwkernel *rule)
+{
+ int len;
+ unsigned int i;
+ __u64 packets = 0, bytes = 0;
+
+ FWC_HAVE_LOCK(fwc_wlocks);
+ for (i = 0; i < NUM_SLOTS; i++) {
+ packets += rule->counters[i].pcnt;
+ bytes += rule->counters[i].bcnt;
+ }
+
+ len=sprintf(buffer,
+ "%9s " /* Chain name */
+ "%08lX/%08lX->%08lX/%08lX " /* Source & Destination IPs */
+ "%.16s " /* Interface */
+ "%X %X " /* fw_flg and fw_invflg fields */
+ "%u " /* Protocol */
+ "%-9u %-9u %-9u %-9u " /* Packet & byte counters */
+ "%u-%u %u-%u " /* Source & Dest port ranges */
+ "A%02X X%02X " /* TOS and and xor masks */
+ "%08X " /* Redirection port */
+ "%u " /* fw_mark field */
+ "%u " /* output size */
+ "%9s\n", /* Target */
+ chainlabel,
+ ntohl(rule->ipfw.fw_src.s_addr),
+ ntohl(rule->ipfw.fw_smsk.s_addr),
+ ntohl(rule->ipfw.fw_dst.s_addr),
+ ntohl(rule->ipfw.fw_dmsk.s_addr),
+ (rule->ipfw.fw_vianame)[0] ? rule->ipfw.fw_vianame : "-",
+ rule->ipfw.fw_flg,
+ rule->ipfw.fw_invflg,
+ rule->ipfw.fw_proto,
+ (__u32)(packets >> 32), (__u32)packets,
+ (__u32)(bytes >> 32), (__u32)bytes,
+ rule->ipfw.fw_spts[0], rule->ipfw.fw_spts[1],
+ rule->ipfw.fw_dpts[0], rule->ipfw.fw_dpts[1],
+ rule->ipfw.fw_tosand, rule->ipfw.fw_tosxor,
+ rule->ipfw.fw_redirpt,
+ rule->ipfw.fw_mark,
+ rule->ipfw.fw_outputsize,
+ branchname(rule->branch,rule->simplebranch));
+
+ duprintf("dump_rule: %i bytes done.\n", len);
+ return len;
+}
+
+/* File offset is actually in records, not bytes. */
+static int ip_chain_procinfo(char *buffer, char **start,
+ off_t offset, int length, int reset)
+{
+ struct ip_chain *i;
+ struct ip_fwkernel *j = ip_fw_chains->chain;
+ unsigned long flags;
+ int len = 0;
+ int last_len = 0;
+ off_t upto = 0;
+
+ duprintf("Offset starts at %lu\n", offset);
+ duprintf("ip_fw_chains is 0x%0lX\n", (unsigned long int)ip_fw_chains);
+
+ /* Need a write lock to lock out ``readers'' which update counters. */
+ FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
+
+ for (i = ip_fw_chains; i; i = i->next) {
+ for (j = i->chain; j; j = j->next) {
+ if (upto == offset) break;
+ duprintf("Skipping rule in chain `%s'\n",
+ i->label);
+ upto++;
+ }
+ if (upto == offset) break;
+ }
+
+ /* Don't init j first time, or once i = NULL */
+ for (; i; (void)((i = i->next) && (j = i->chain))) {
+ duprintf("Dumping chain `%s'\n", i->label);
+ for (; j; j = j->next, upto++, last_len = len)
+ {
+ len += dump_rule(buffer+len, i->label, j);
+ if (len > length) {
+ duprintf("Dumped to %i (past %i). "
+ "Moving back to %i.\n",
+ len, length, last_len);
+ len = last_len;
+ goto outside;
+ }
+ else if (reset)
+ memset(j->counters, 0,
+ sizeof(struct ip_counters)*NUM_SLOTS);
+ }
+ }
+outside:
+ FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
+ buffer[len] = '\0';
+
+ duprintf("ip_chain_procinfo: Length = %i (of %i). Offset = %li.\n",
+ len, length, upto);
+ /* `start' hack - see fs/proc/generic.c line ~165 */
+ *start=(char *)((unsigned int)upto-offset);
+ return len;
+}
+
+static int ip_chain_name_procinfo(char *buffer, char **start,
+ off_t offset, int length, int reset)
+{
+ struct ip_chain *i;
+ int len = 0,last_len = 0;
+ off_t pos = 0,begin = 0;
+ unsigned long flags;
+
+ /* Need a write lock to lock out ``readers'' which update counters. */
+ FWC_WRITE_LOCK_IRQ(&ip_fw_lock, flags);
+
+ for (i = ip_fw_chains; i; i = i->next)
+ {
+ unsigned int j;
+ __u32 packetsHi = 0, packetsLo = 0, bytesHi = 0, bytesLo = 0;
+
+ for (j = 0; j < NUM_SLOTS; j++) {
+ packetsLo += i->reent[j].counters.pcnt & 0xFFFFFFFF;
+ packetsHi += ((i->reent[j].counters.pcnt >> 32)
+ & 0xFFFFFFFF);
+ bytesLo += i->reent[j].counters.bcnt & 0xFFFFFFFF;
+ bytesHi += ((i->reent[j].counters.bcnt >> 32)
+ & 0xFFFFFFFF);
+ }
+
+ /* print the label and the policy */
+ len+=sprintf(buffer+len,"%s %s %i %u %u %u %u\n",
+ i->label,branchname(NULL, i->policy),i->refcount,
+ packetsHi, packetsLo, bytesHi, bytesLo);
+ pos=begin+len;
+ if(pos<offset) {
+ len=0;
+ begin=pos;
+ }
+ else if(pos>offset+length) {
+ len = last_len;
+ break;
+ }
+
+ last_len = len;
+ }
+ FWC_WRITE_UNLOCK_IRQ(&ip_fw_lock, flags);
+
+ *start = buffer+(offset-begin);
+ len-=(offset-begin);
+ if(len>length)
+ len=length;
+ return len;
+}
+
+/*
+ * Interface to the generic firewall chains.
+ */
+int ipfw_input_check(struct firewall_ops *this, int pf, struct device *dev,
+ void *phdr, void *arg, struct sk_buff **pskb)
+{
+ return ip_fw_check(phdr, dev->name,
+ arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
+}
+
+int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev,
+ void *phdr, void *arg, struct sk_buff **pskb)
+{
+ /* Locally generated bogus packets by root. <SIGH>. */
+ if (((struct iphdr *)phdr)->ihl * 4 < sizeof(struct iphdr)
+ || (*pskb)->len < sizeof(struct iphdr))
+ return FW_ACCEPT;
+ return ip_fw_check(phdr, dev->name,
+ arg, IP_FW_OUTPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
+}
+
+int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev,
+ void *phdr, void *arg, struct sk_buff **pskb)
+{
+ return ip_fw_check(phdr, dev->name,
+ arg, IP_FW_FORWARD_CHAIN, *pskb, SLOT_NUMBER(), 0);
+}
+
+struct firewall_ops ipfw_ops=
+{
+ NULL,
+ ipfw_forward_check,
+ ipfw_input_check,
+ ipfw_output_check,
+ PF_INET,
+ 0 /* We don't even allow a fall through so we are last */
+};
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_ipfwchains_chain = {
+ PROC_NET_IPFW_CHAINS, sizeof(IP_FW_PROC_CHAINS)-1,
+ IP_FW_PROC_CHAINS, S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
+ 0, &proc_net_inode_operations, ip_chain_procinfo
+};
+
+static struct proc_dir_entry proc_net_ipfwchains_chainnames = {
+ PROC_NET_IPFW_CHAIN_NAMES, sizeof(IP_FW_PROC_CHAIN_NAMES)-1,
+ IP_FW_PROC_CHAIN_NAMES, S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
+ 0, &proc_net_inode_operations, ip_chain_name_procinfo
+};
+
+#endif
+
+__initfunc(void ip_fw_init(void))
+{
+#ifdef DEBUG_IP_FIRWALL_LOCKING
+ fwc_wlocks = fwc_rlocks = 0;
+#endif
+
+ IP_FW_INPUT_CHAIN = ip_init_chain(IP_FW_LABEL_INPUT, 1, FW_ACCEPT);
+ IP_FW_FORWARD_CHAIN = ip_init_chain(IP_FW_LABEL_FORWARD, 1, FW_ACCEPT);
+ IP_FW_OUTPUT_CHAIN = ip_init_chain(IP_FW_LABEL_OUTPUT, 1, FW_ACCEPT);
+
+ if(register_firewall(PF_INET,&ipfw_ops)<0)
+ panic("Unable to register IP firewall.\n");
+
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&proc_net_ipfwchains_chain);
+ proc_net_register(&proc_net_ipfwchains_chainnames);
+#endif
+
+#ifdef CONFIG_IP_FIREWALL_NETLINK
+ ipfwsk = netlink_kernel_create(NETLINK_FIREWALL, NULL);
+ if (ipfwsk == NULL)
+ panic("ip_fw_init: cannot initialize netlink\n");
+#endif
+#if defined(DEBUG_IP_FIREWALL) || defined(DEBUG_IP_FIREWALL_USER)
+ printk("Firewall graphs enabled! Untested kernel coming thru. \n");
+#endif
+}
diff --git a/pfinet/linux-src/net/ipv4/ip_gre.c b/pfinet/linux-src/net/ipv4/ip_gre.c
new file mode 100644
index 00000000..6a7546fd
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_gre.c
@@ -0,0 +1,1223 @@
+/*
+ * Linux NET3: GRE over IP protocol decoder.
+ *
+ * Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/if_arp.h>
+#include <linux/mroute.h>
+#include <linux/init.h>
+#include <linux/in6.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+
+#include <net/sock.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/protocol.h>
+#include <net/ipip.h>
+#include <net/arp.h>
+#include <net/checksum.h>
+
+#ifdef CONFIG_IPV6
+#include <net/ipv6.h>
+#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
+#endif
+
+/*
+ Problems & solutions
+ --------------------
+
+ 1. The most important issue is detecting local dead loops.
+ They would cause complete host lockup in transmit, which
+ would be "resolved" by stack overflow or, if queueing is enabled,
+ with infinite looping in net_bh.
+
+ We cannot track such dead loops during route installation,
+ it is infeasible task. The most general solutions would be
+ to keep skb->encapsulation counter (sort of local ttl),
+ and silently drop packet when it expires. It is the best
+ solution, but it supposes maintaing new variable in ALL
+ skb, even if no tunneling is used.
+
+ Current solution: t->recursion lock breaks dead loops. It looks
+ like dev->tbusy flag, but I preferred new variable, because
+ the semantics is different. One day, when hard_start_xmit
+ will be multithreaded we will have to use skb->encapsulation.
+
+
+
+ 2. Networking dead loops would not kill routers, but would really
+ kill network. IP hop limit plays role of "t->recursion" in this case,
+ if we copy it from packet being encapsulated to upper header.
+ It is very good solution, but it introduces two problems:
+
+ - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
+ do not work over tunnels.
+ - traceroute does not work. I planned to relay ICMP from tunnel,
+ so that this problem would be solved and traceroute output
+ would even more informative. This idea appeared to be wrong:
+ only Linux complies to rfc1812 now (yes, guys, Linux is the only
+ true router now :-)), all routers (at least, in neighbourhood of mine)
+ return only 8 bytes of payload. It is the end.
+
+ Hence, if we want that OSPF worked or traceroute said something reasonable,
+ we should search for another solution.
+
+ One of them is to parse packet trying to detect inner encapsulation
+ made by our node. It is difficult or even impossible, especially,
+ taking into account fragmentation. TO be short, tt is not solution at all.
+
+ Current solution: The solution was UNEXPECTEDLY SIMPLE.
+ We force DF flag on tunnels with preconfigured hop limit,
+ that is ALL. :-) Well, it does not remove the problem completely,
+ but exponential growth of network traffic is changed to linear
+ (branches, that exceed pmtu are pruned) and tunnel mtu
+ fastly degrades to value <68, where looping stops.
+ Yes, it is not good if there exists a router in the loop,
+ which does not force DF, even when encapsulating packets have DF set.
+ But it is not our problem! Nobody could accuse us, we made
+ all that we could make. Even if it is your gated who injected
+ fatal route to network, even if it were you who configured
+ fatal static route: you are innocent. :-)
+
+
+
+ 3. Really, ipv4/ipip.c, ipv4/ip_gre.c and ipv6/sit.c contain
+ practically identical code. It would be good to glue them
+ together, but it is not very evident, how to make them modular.
+ sit is integral part of IPv6, ipip and gre are naturally modular.
+ We could extract common parts (hash table, ioctl etc)
+ to a separate module (ip_tunnel.c).
+
+ Alexey Kuznetsov.
+ */
+
+static int ipgre_tunnel_init(struct device *dev);
+
+/* Fallback tunnel: no source, no destination, no key, no options */
+
+static int ipgre_fb_tunnel_init(struct device *dev);
+
+static struct device ipgre_fb_tunnel_dev = {
+ NULL, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipgre_fb_tunnel_init,
+};
+
+static struct ip_tunnel ipgre_fb_tunnel = {
+ NULL, &ipgre_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"gre0", }
+};
+
+/* Tunnel hash table */
+
+/*
+ 4 hash tables:
+
+ 3: (remote,local)
+ 2: (remote,*)
+ 1: (*,local)
+ 0: (*,*)
+
+ We require exact key match i.e. if a key is present in packet
+ it will match only tunnel with the same key; if it is not present,
+ it will match only keyless tunnel.
+
+ All keysless packets, if not matched configured keyless tunnels
+ will match fallback tunnel.
+ */
+
+#define HASH_SIZE 16
+#define HASH(addr) ((addr^(addr>>4))&0xF)
+
+static struct ip_tunnel *tunnels[4][HASH_SIZE];
+
+#define tunnels_r_l (tunnels[3])
+#define tunnels_r (tunnels[2])
+#define tunnels_l (tunnels[1])
+#define tunnels_wc (tunnels[0])
+
+/* Given src, dst and key, find approriate for input tunnel. */
+
+static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key)
+{
+ unsigned h0 = HASH(remote);
+ unsigned h1 = HASH(key);
+ struct ip_tunnel *t;
+
+ for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
+ if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ }
+ for (t = tunnels_r[h0^h1]; t; t = t->next) {
+ if (remote == t->parms.iph.daddr) {
+ if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ }
+ for (t = tunnels_l[h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr ||
+ (local == t->parms.iph.daddr && MULTICAST(local))) {
+ if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ }
+ for (t = tunnels_wc[h1]; t; t = t->next) {
+ if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ if (ipgre_fb_tunnel_dev.flags&IFF_UP)
+ return &ipgre_fb_tunnel;
+ return NULL;
+}
+
+static struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t)
+{
+ u32 remote = t->parms.iph.daddr;
+ u32 local = t->parms.iph.saddr;
+ u32 key = t->parms.i_key;
+ unsigned h = HASH(key);
+ int prio = 0;
+
+ if (local)
+ prio |= 1;
+ if (remote && !MULTICAST(remote)) {
+ prio |= 2;
+ h ^= HASH(remote);
+ }
+
+ return &tunnels[prio][h];
+}
+
+static void ipgre_tunnel_link(struct ip_tunnel *t)
+{
+ struct ip_tunnel **tp = ipgre_bucket(t);
+
+ t->next = *tp;
+ wmb();
+ *tp = t;
+}
+
+static void ipgre_tunnel_unlink(struct ip_tunnel *t)
+{
+ struct ip_tunnel **tp;
+
+ for (tp = ipgre_bucket(t); *tp; tp = &(*tp)->next) {
+ if (t == *tp) {
+ *tp = t->next;
+ synchronize_bh();
+ break;
+ }
+ }
+}
+
+static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create)
+{
+ u32 remote = parms->iph.daddr;
+ u32 local = parms->iph.saddr;
+ u32 key = parms->i_key;
+ struct ip_tunnel *t, **tp, *nt;
+ struct device *dev;
+ unsigned h = HASH(key);
+ int prio = 0;
+
+ if (local)
+ prio |= 1;
+ if (remote && !MULTICAST(remote)) {
+ prio |= 2;
+ h ^= HASH(remote);
+ }
+ for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) {
+ if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
+ if (key == t->parms.i_key)
+ return t;
+ }
+ }
+ if (!create)
+ return NULL;
+
+ MOD_INC_USE_COUNT;
+ dev = kmalloc(sizeof(*dev) + sizeof(*t), GFP_KERNEL);
+ if (dev == NULL) {
+ MOD_DEC_USE_COUNT;
+ return NULL;
+ }
+ memset(dev, 0, sizeof(*dev) + sizeof(*t));
+ dev->priv = (void*)(dev+1);
+ nt = (struct ip_tunnel*)dev->priv;
+ nt->dev = dev;
+ dev->name = nt->parms.name;
+ dev->init = ipgre_tunnel_init;
+ memcpy(&nt->parms, parms, sizeof(*parms));
+ if (dev->name[0] == 0) {
+ int i;
+ for (i=1; i<100; i++) {
+ sprintf(dev->name, "gre%d", i);
+ if (dev_get(dev->name) == NULL)
+ break;
+ }
+ if (i==100)
+ goto failed;
+ memcpy(parms->name, dev->name, IFNAMSIZ);
+ }
+ if (register_netdevice(dev) < 0)
+ goto failed;
+
+ ipgre_tunnel_link(nt);
+ /* Do not decrement MOD_USE_COUNT here. */
+ return nt;
+
+failed:
+ kfree(dev);
+ MOD_DEC_USE_COUNT;
+ return NULL;
+}
+
+static void ipgre_tunnel_destroy(struct device *dev)
+{
+ ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv);
+
+ if (dev != &ipgre_fb_tunnel_dev) {
+ kfree(dev);
+ MOD_DEC_USE_COUNT;
+ }
+}
+
+
+void ipgre_err(struct sk_buff *skb, unsigned char *dp, int len)
+{
+#ifndef I_WISH_WORLD_WERE_PERFECT
+
+/* It is not :-( All the routers (except for Linux) return only
+ 8 bytes of packet payload. It means, that precise relaying of
+ ICMP in the real Internet is absolutely infeasible.
+
+ Moreover, Cisco "wise men" put GRE key to the third word
+ in GRE header. It makes impossible maintaining even soft state for keyed
+ GRE tunnels with enabled checksum. Tell them "thank you".
+
+ Well, I wonder, rfc1812 was written by Cisco employee,
+ what the hell these idiots break standrads established
+ by themself???
+ */
+
+ struct iphdr *iph = (struct iphdr*)dp;
+ u16 *p = (u16*)(dp+(iph->ihl<<2));
+ int grehlen = (iph->ihl<<2) + 4;
+ int type = skb->h.icmph->type;
+ int code = skb->h.icmph->code;
+ struct ip_tunnel *t;
+ u16 flags;
+
+ flags = p[0];
+ if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
+ if (flags&(GRE_VERSION|GRE_ROUTING))
+ return;
+ if (flags&GRE_KEY) {
+ grehlen += 4;
+ if (flags&GRE_CSUM)
+ grehlen += 4;
+ }
+ }
+
+ /* If only 8 bytes returned, keyed message will be dropped here */
+ if (len < grehlen)
+ return;
+
+ switch (type) {
+ default:
+ case ICMP_PARAMETERPROB:
+ return;
+
+ case ICMP_DEST_UNREACH:
+ switch (code) {
+ case ICMP_SR_FAILED:
+ case ICMP_PORT_UNREACH:
+ /* Impossible event. */
+ return;
+ case ICMP_FRAG_NEEDED:
+ /* Soft state for pmtu is maintained by IP core. */
+ return;
+ default:
+ /* All others are translated to HOST_UNREACH.
+ rfc2003 contains "deep thoughts" about NET_UNREACH,
+ I believe they are just ether pollution. --ANK
+ */
+ break;
+ }
+ break;
+ case ICMP_TIME_EXCEEDED:
+ if (code != ICMP_EXC_TTL)
+ return;
+ break;
+ }
+
+ t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((u32*)p) + (grehlen>>2) - 1) : 0);
+ if (t == NULL || t->parms.iph.daddr == 0 || MULTICAST(t->parms.iph.daddr))
+ return;
+
+ if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
+ return;
+
+ if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO)
+ t->err_count++;
+ else
+ t->err_count = 1;
+ t->err_time = jiffies;
+ return;
+#else
+ struct iphdr *iph = (struct iphdr*)dp;
+ struct iphdr *eiph;
+ u16 *p = (u16*)(dp+(iph->ihl<<2));
+ int type = skb->h.icmph->type;
+ int code = skb->h.icmph->code;
+ int rel_type = 0;
+ int rel_code = 0;
+ int rel_info = 0;
+ u16 flags;
+ int grehlen = (iph->ihl<<2) + 4;
+ struct sk_buff *skb2;
+ struct rtable *rt;
+
+ if (p[1] != __constant_htons(ETH_P_IP))
+ return;
+
+ flags = p[0];
+ if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
+ if (flags&(GRE_VERSION|GRE_ROUTING))
+ return;
+ if (flags&GRE_CSUM)
+ grehlen += 4;
+ if (flags&GRE_KEY)
+ grehlen += 4;
+ if (flags&GRE_SEQ)
+ grehlen += 4;
+ }
+ if (len < grehlen + sizeof(struct iphdr))
+ return;
+ eiph = (struct iphdr*)(dp + grehlen);
+
+ switch (type) {
+ default:
+ return;
+ case ICMP_PARAMETERPROB:
+ if (skb->h.icmph->un.gateway < (iph->ihl<<2))
+ return;
+
+ /* So... This guy found something strange INSIDE encapsulated
+ packet. Well, he is fool, but what can we do ?
+ */
+ rel_type = ICMP_PARAMETERPROB;
+ rel_info = skb->h.icmph->un.gateway - grehlen;
+ break;
+
+ case ICMP_DEST_UNREACH:
+ switch (code) {
+ case ICMP_SR_FAILED:
+ case ICMP_PORT_UNREACH:
+ /* Impossible event. */
+ return;
+ case ICMP_FRAG_NEEDED:
+ /* And it is the only really necesary thing :-) */
+ rel_info = ntohs(skb->h.icmph->un.frag.mtu);
+ if (rel_info < grehlen+68)
+ return;
+ rel_info -= grehlen;
+ /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
+ if (rel_info > ntohs(eiph->tot_len))
+ return;
+ break;
+ default:
+ /* All others are translated to HOST_UNREACH.
+ rfc2003 contains "deep thoughts" about NET_UNREACH,
+ I believe, it is just ether pollution. --ANK
+ */
+ rel_type = ICMP_DEST_UNREACH;
+ rel_code = ICMP_HOST_UNREACH;
+ break;
+ }
+ break;
+ case ICMP_TIME_EXCEEDED:
+ if (code != ICMP_EXC_TTL)
+ return;
+ break;
+ }
+
+ /* Prepare fake skb to feed it to icmp_send */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2 == NULL)
+ return;
+ dst_release(skb2->dst);
+ skb2->dst = NULL;
+ skb_pull(skb2, skb->data - (u8*)eiph);
+ skb2->nh.raw = skb2->data;
+
+ /* Try to guess incoming interface */
+ if (ip_route_output(&rt, eiph->saddr, 0, RT_TOS(eiph->tos), 0)) {
+ kfree_skb(skb2);
+ return;
+ }
+ skb2->dev = rt->u.dst.dev;
+
+ /* route "incoming" packet */
+ if (rt->rt_flags&RTCF_LOCAL) {
+ ip_rt_put(rt);
+ rt = NULL;
+ if (ip_route_output(&rt, eiph->daddr, eiph->saddr, eiph->tos, 0) ||
+ rt->u.dst.dev->type != ARPHRD_IPGRE) {
+ ip_rt_put(rt);
+ kfree_skb(skb2);
+ return;
+ }
+ } else {
+ ip_rt_put(rt);
+ if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) ||
+ skb2->dst->dev->type != ARPHRD_IPGRE) {
+ kfree_skb(skb2);
+ return;
+ }
+ }
+
+ /* change mtu on this route */
+ if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
+ if (rel_info > skb2->dst->pmtu) {
+ kfree_skb(skb2);
+ return;
+ }
+ skb2->dst->pmtu = rel_info;
+ rel_info = htonl(rel_info);
+ } else if (type == ICMP_TIME_EXCEEDED) {
+ struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv;
+ if (t->parms.iph.ttl) {
+ rel_type = ICMP_DEST_UNREACH;
+ rel_code = ICMP_HOST_UNREACH;
+ }
+ }
+
+ icmp_send(skb2, rel_type, rel_code, rel_info);
+ kfree_skb(skb2);
+#endif
+}
+
+int ipgre_rcv(struct sk_buff *skb, unsigned short len)
+{
+ struct iphdr *iph = skb->nh.iph;
+ u8 *h = skb->h.raw;
+ u16 flags = *(u16*)h;
+ u16 csum = 0;
+ u32 key = 0;
+ u32 seqno = 0;
+ struct ip_tunnel *tunnel;
+ int offset = 4;
+
+ if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) {
+ /* - Version must be 0.
+ - We do not support routing headers.
+ */
+ if (flags&(GRE_VERSION|GRE_ROUTING))
+ goto drop;
+
+ if (flags&GRE_CSUM) {
+ csum = ip_compute_csum(h, len);
+ offset += 4;
+ }
+ if (flags&GRE_KEY) {
+ key = *(u32*)(h + offset);
+ offset += 4;
+ }
+ if (flags&GRE_SEQ) {
+ seqno = ntohl(*(u32*)(h + offset));
+ offset += 4;
+ }
+ }
+
+ if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
+ skb->mac.raw = skb->nh.raw;
+ skb->nh.raw = skb_pull(skb, h + offset - skb->data);
+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+ skb->ip_summed = 0;
+ skb->protocol = *(u16*)(h + 2);
+ skb->pkt_type = PACKET_HOST;
+#ifdef CONFIG_NET_IPGRE_BROADCAST
+ if (MULTICAST(iph->daddr)) {
+ /* Looped back packet, drop it! */
+ if (((struct rtable*)skb->dst)->key.iif == 0)
+ goto drop;
+ tunnel->stat.multicast++;
+ skb->pkt_type = PACKET_BROADCAST;
+ }
+#endif
+
+ if (((flags&GRE_CSUM) && csum) ||
+ (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
+ tunnel->stat.rx_crc_errors++;
+ tunnel->stat.rx_errors++;
+ goto drop;
+ }
+ if (tunnel->parms.i_flags&GRE_SEQ) {
+ if (!(flags&GRE_SEQ) ||
+ (tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
+ tunnel->stat.rx_fifo_errors++;
+ tunnel->stat.rx_errors++;
+ goto drop;
+ }
+ tunnel->i_seqno = seqno + 1;
+ }
+ tunnel->stat.rx_packets++;
+ tunnel->stat.rx_bytes += skb->len;
+ skb->dev = tunnel->dev;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ netif_rx(skb);
+ return(0);
+ }
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+
+drop:
+ kfree_skb(skb);
+ return(0);
+}
+
+static int ipgre_tunnel_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ struct net_device_stats *stats = &tunnel->stat;
+ struct iphdr *old_iph = skb->nh.iph;
+ struct iphdr *tiph;
+ u8 tos;
+ u16 df;
+ struct rtable *rt; /* Route to the other host */
+ struct device *tdev; /* Device to other host */
+ struct iphdr *iph; /* Our new IP header */
+ int max_headroom; /* The extra header space needed */
+ int gre_hlen;
+ u32 dst;
+ int mtu;
+
+ if (tunnel->recursion++) {
+ tunnel->stat.collisions++;
+ goto tx_error;
+ }
+
+ if (dev->hard_header) {
+ gre_hlen = 0;
+ tiph = (struct iphdr*)skb->data;
+ } else {
+ gre_hlen = tunnel->hlen;
+ tiph = &tunnel->parms.iph;
+ }
+
+ if ((dst = tiph->daddr) == 0) {
+ /* NBMA tunnel */
+
+ if (skb->dst == NULL) {
+ tunnel->stat.tx_fifo_errors++;
+ goto tx_error;
+ }
+
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
+ rt = (struct rtable*)skb->dst;
+ if ((dst = rt->rt_gateway) == 0)
+ goto tx_error_icmp;
+ }
+#ifdef CONFIG_IPV6
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+ struct in6_addr *addr6;
+ int addr_type;
+ struct neighbour *neigh = skb->dst->neighbour;
+
+ if (neigh == NULL)
+ goto tx_error;
+
+ addr6 = (struct in6_addr*)&neigh->primary_key;
+ addr_type = ipv6_addr_type(addr6);
+
+ if (addr_type == IPV6_ADDR_ANY) {
+ addr6 = &skb->nh.ipv6h->daddr;
+ addr_type = ipv6_addr_type(addr6);
+ }
+
+ if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
+ goto tx_error_icmp;
+
+ dst = addr6->s6_addr32[3];
+ }
+#endif
+ else
+ goto tx_error;
+ }
+
+ tos = tiph->tos;
+ if (tos&1) {
+ if (skb->protocol == __constant_htons(ETH_P_IP))
+ tos = old_iph->tos;
+ tos &= ~1;
+ }
+
+ if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) {
+ tunnel->stat.tx_carrier_errors++;
+ goto tx_error;
+ }
+ tdev = rt->u.dst.dev;
+
+ if (tdev == dev) {
+ ip_rt_put(rt);
+ tunnel->stat.collisions++;
+ goto tx_error;
+ }
+
+ df = tiph->frag_off;
+ mtu = rt->u.dst.pmtu - tunnel->hlen;
+
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
+ if (skb->dst && mtu < skb->dst->pmtu && mtu >= 68)
+ skb->dst->pmtu = mtu;
+
+ df |= (old_iph->frag_off&__constant_htons(IP_DF));
+
+ if ((old_iph->frag_off&__constant_htons(IP_DF)) &&
+ mtu < ntohs(old_iph->tot_len)) {
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+ ip_rt_put(rt);
+ goto tx_error;
+ }
+ }
+#ifdef CONFIG_IPV6
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+ struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
+
+ if (rt6 && mtu < rt6->u.dst.pmtu && mtu >= IPV6_MIN_MTU) {
+ if ((tunnel->parms.iph.daddr && !MULTICAST(tunnel->parms.iph.daddr)) ||
+ rt6->rt6i_dst.plen == 128) {
+ rt6->rt6i_flags |= RTF_MODIFIED;
+ skb->dst->pmtu = mtu;
+ }
+ }
+
+ if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) {
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
+ ip_rt_put(rt);
+ goto tx_error;
+ }
+ }
+#endif
+
+ if (tunnel->err_count > 0) {
+ if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) {
+ tunnel->err_count--;
+
+ dst_link_failure(skb);
+ } else
+ tunnel->err_count = 0;
+ }
+
+ skb->h.raw = skb->nh.raw;
+
+ max_headroom = ((tdev->hard_header_len+15)&~15)+ gre_hlen;
+
+ if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+ struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
+ if (!new_skb) {
+ ip_rt_put(rt);
+ stats->tx_dropped++;
+ dev_kfree_skb(skb);
+ tunnel->recursion--;
+ return 0;
+ }
+ if (skb->sk)
+ skb_set_owner_w(new_skb, skb->sk);
+ dev_kfree_skb(skb);
+ skb = new_skb;
+ }
+
+ skb->nh.raw = skb_push(skb, gre_hlen);
+ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+
+ /*
+ * Push down and install the IPIP header.
+ */
+
+ iph = skb->nh.iph;
+ iph->version = 4;
+ iph->ihl = sizeof(struct iphdr) >> 2;
+ iph->frag_off = df;
+ iph->protocol = IPPROTO_GRE;
+ iph->tos = tos;
+ iph->daddr = rt->rt_dst;
+ iph->saddr = rt->rt_src;
+
+ if ((iph->ttl = tiph->ttl) == 0) {
+ if (skb->protocol == __constant_htons(ETH_P_IP))
+ iph->ttl = old_iph->ttl;
+#ifdef CONFIG_IPV6
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6))
+ iph->ttl = ((struct ipv6hdr*)old_iph)->hop_limit;
+#endif
+ else
+ iph->ttl = ip_statistics.IpDefaultTTL;
+ }
+
+ ((u16*)(iph+1))[0] = tunnel->parms.o_flags;
+ ((u16*)(iph+1))[1] = skb->protocol;
+
+ if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
+ u32 *ptr = (u32*)(((u8*)iph) + tunnel->hlen - 4);
+
+ if (tunnel->parms.o_flags&GRE_SEQ) {
+ ++tunnel->o_seqno;
+ *ptr = htonl(tunnel->o_seqno);
+ ptr--;
+ }
+ if (tunnel->parms.o_flags&GRE_KEY) {
+ *ptr = tunnel->parms.o_key;
+ ptr--;
+ }
+ if (tunnel->parms.o_flags&GRE_CSUM) {
+ *ptr = 0;
+ *(__u16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
+ }
+ }
+
+ iph->tot_len = htons(skb->len);
+ iph->id = htons(ip_id_count++);
+ ip_send_check(iph);
+
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+ ip_send(skb);
+ tunnel->recursion--;
+ return 0;
+
+tx_error_icmp:
+ dst_link_failure(skb);
+
+tx_error:
+ stats->tx_errors++;
+ dev_kfree_skb(skb);
+ tunnel->recursion--;
+ return 0;
+}
+
+static int
+ipgre_tunnel_ioctl (struct device *dev, struct ifreq *ifr, int cmd)
+{
+ int err = 0;
+ struct ip_tunnel_parm p;
+ struct ip_tunnel *t;
+
+ MOD_INC_USE_COUNT;
+
+ switch (cmd) {
+ case SIOCGETTUNNEL:
+ t = NULL;
+ if (dev == &ipgre_fb_tunnel_dev) {
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
+ err = -EFAULT;
+ break;
+ }
+ t = ipgre_tunnel_locate(&p, 0);
+ }
+ if (t == NULL)
+ t = (struct ip_tunnel*)dev->priv;
+ memcpy(&p, &t->parms, sizeof(p));
+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
+ err = -EFAULT;
+ break;
+
+ case SIOCADDTUNNEL:
+ case SIOCCHGTUNNEL:
+ err = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ goto done;
+
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ goto done;
+
+ err = -EINVAL;
+ if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE ||
+ p.iph.ihl != 5 || (p.iph.frag_off&__constant_htons(~IP_DF)) ||
+ ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)))
+ goto done;
+ if (p.iph.ttl)
+ p.iph.frag_off |= __constant_htons(IP_DF);
+
+ if (!(p.i_flags&GRE_KEY))
+ p.i_key = 0;
+ if (!(p.o_flags&GRE_KEY))
+ p.o_key = 0;
+
+ t = ipgre_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
+
+ if (dev != &ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL &&
+ t != &ipgre_fb_tunnel) {
+ if (t != NULL) {
+ if (t->dev != dev) {
+ err = -EEXIST;
+ break;
+ }
+ } else {
+ unsigned nflags=0;
+
+ t = (struct ip_tunnel*)dev->priv;
+
+ if (MULTICAST(p.iph.daddr))
+ nflags = IFF_BROADCAST;
+ else if (p.iph.daddr)
+ nflags = IFF_POINTOPOINT;
+
+ if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) {
+ err = -EINVAL;
+ break;
+ }
+ start_bh_atomic();
+ ipgre_tunnel_unlink(t);
+ t->parms.iph.saddr = p.iph.saddr;
+ t->parms.iph.daddr = p.iph.daddr;
+ t->parms.i_key = p.i_key;
+ t->parms.o_key = p.o_key;
+ memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ memcpy(dev->broadcast, &p.iph.daddr, 4);
+ ipgre_tunnel_link(t);
+ end_bh_atomic();
+ netdev_state_change(dev);
+ }
+ }
+
+ if (t) {
+ err = 0;
+ if (cmd == SIOCCHGTUNNEL) {
+ t->parms.iph.ttl = p.iph.ttl;
+ t->parms.iph.tos = p.iph.tos;
+ t->parms.iph.frag_off = p.iph.frag_off;
+ }
+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
+ err = -EFAULT;
+ } else
+ err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
+ break;
+
+ case SIOCDELTUNNEL:
+ err = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ goto done;
+
+ if (dev == &ipgre_fb_tunnel_dev) {
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ goto done;
+ err = -ENOENT;
+ if ((t = ipgre_tunnel_locate(&p, 0)) == NULL)
+ goto done;
+ err = -EPERM;
+ if (t == &ipgre_fb_tunnel)
+ goto done;
+ }
+ err = unregister_netdevice(dev);
+ break;
+
+ default:
+ err = -EINVAL;
+ }
+
+done:
+ MOD_DEC_USE_COUNT;
+ return err;
+}
+
+static struct net_device_stats *ipgre_tunnel_get_stats(struct device *dev)
+{
+ return &(((struct ip_tunnel*)dev->priv)->stat);
+}
+
+static int ipgre_tunnel_change_mtu(struct device *dev, int new_mtu)
+{
+ struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen)
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+#ifdef CONFIG_NET_IPGRE_BROADCAST
+/* Nice toy. Unfortunately, useless in real life :-)
+ It allows to construct virtual multiprotocol broadcast "LAN"
+ over the Internet, provided multicast routing is tuned.
+
+
+ I have no idea was this bicycle invented before me,
+ so that I had to set ARPHRD_IPGRE to a random value.
+ I have an impression, that Cisco could make something similar,
+ but this feature is apparently missing in IOS<=11.2(8).
+
+ I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
+ with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
+
+ ping -t 255 224.66.66.66
+
+ If nobody answers, mbone does not work.
+
+ ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
+ ip addr add 10.66.66.<somewhat>/24 dev Universe
+ ifconfig Universe up
+ ifconfig Universe add fe80::<Your_real_addr>/10
+ ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
+ ftp 10.66.66.66
+ ...
+ ftp fec0:6666:6666::193.233.7.65
+ ...
+
+ */
+
+static int ipgre_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+ void *daddr, void *saddr, unsigned len)
+{
+ struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
+ struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
+ u16 *p = (u16*)(iph+1);
+
+ memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
+ p[0] = t->parms.o_flags;
+ p[1] = htons(type);
+
+ /*
+ * Set the source hardware address.
+ */
+
+ if (saddr)
+ memcpy(&iph->saddr, saddr, 4);
+
+ if (daddr) {
+ memcpy(&iph->daddr, daddr, 4);
+ return t->hlen;
+ }
+ if (iph->daddr && !MULTICAST(iph->daddr))
+ return t->hlen;
+
+ return -t->hlen;
+}
+
+static int ipgre_open(struct device *dev)
+{
+ struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
+
+ MOD_INC_USE_COUNT;
+ if (MULTICAST(t->parms.iph.daddr)) {
+ struct rtable *rt;
+ if (ip_route_output(&rt, t->parms.iph.daddr,
+ t->parms.iph.saddr, RT_TOS(t->parms.iph.tos),
+ t->parms.link)) {
+ MOD_DEC_USE_COUNT;
+ return -EADDRNOTAVAIL;
+ }
+ dev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ if (dev->ip_ptr == NULL) {
+ MOD_DEC_USE_COUNT;
+ return -EADDRNOTAVAIL;
+ }
+ t->mlink = dev->ifindex;
+ ip_mc_inc_group(dev->ip_ptr, t->parms.iph.daddr);
+ }
+ return 0;
+}
+
+static int ipgre_close(struct device *dev)
+{
+ struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
+ if (MULTICAST(t->parms.iph.daddr) && t->mlink) {
+ dev = dev_get_by_index(t->mlink);
+ if (dev && dev->ip_ptr)
+ ip_mc_dec_group(dev->ip_ptr, t->parms.iph.daddr);
+ }
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+#endif
+
+static void ipgre_tunnel_init_gen(struct device *dev)
+{
+ struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
+
+ dev->destructor = ipgre_tunnel_destroy;
+ dev->hard_start_xmit = ipgre_tunnel_xmit;
+ dev->get_stats = ipgre_tunnel_get_stats;
+ dev->do_ioctl = ipgre_tunnel_ioctl;
+ dev->change_mtu = ipgre_tunnel_change_mtu;
+
+ dev_init_buffers(dev);
+
+ dev->type = ARPHRD_IPGRE;
+ dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr) + 4;
+ dev->mtu = 1500 - sizeof(struct iphdr) - 4;
+ dev->flags = IFF_NOARP;
+ dev->iflink = 0;
+ dev->addr_len = 4;
+ memcpy(dev->dev_addr, &t->parms.iph.saddr, 4);
+ memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
+}
+
+static int ipgre_tunnel_init(struct device *dev)
+{
+ struct device *tdev = NULL;
+ struct ip_tunnel *tunnel;
+ struct iphdr *iph;
+ int hlen = LL_MAX_HEADER;
+ int mtu = 1500;
+ int addend = sizeof(struct iphdr) + 4;
+
+ tunnel = (struct ip_tunnel*)dev->priv;
+ iph = &tunnel->parms.iph;
+
+ ipgre_tunnel_init_gen(dev);
+
+ /* Guess output device to choose reasonable mtu and hard_header_len */
+
+ if (iph->daddr) {
+ struct rtable *rt;
+ if (!ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), tunnel->parms.link)) {
+ tdev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ }
+
+ dev->flags |= IFF_POINTOPOINT;
+
+#ifdef CONFIG_NET_IPGRE_BROADCAST
+ if (MULTICAST(iph->daddr)) {
+ if (!iph->saddr)
+ return -EINVAL;
+ dev->flags = IFF_BROADCAST;
+ dev->hard_header = ipgre_header;
+ dev->open = ipgre_open;
+ dev->stop = ipgre_close;
+ }
+#endif
+ }
+
+ if (!tdev && tunnel->parms.link)
+ tdev = dev_get_by_index(tunnel->parms.link);
+
+ if (tdev) {
+ hlen = tdev->hard_header_len;
+ mtu = tdev->mtu;
+ }
+ dev->iflink = tunnel->parms.link;
+
+ /* Precalculate GRE options length */
+ if (tunnel->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
+ if (tunnel->parms.o_flags&GRE_CSUM)
+ addend += 4;
+ if (tunnel->parms.o_flags&GRE_KEY)
+ addend += 4;
+ if (tunnel->parms.o_flags&GRE_SEQ)
+ addend += 4;
+ }
+ dev->hard_header_len = hlen + addend;
+ dev->mtu = mtu - addend;
+ tunnel->hlen = addend;
+ return 0;
+}
+
+#ifdef MODULE
+static int ipgre_fb_tunnel_open(struct device *dev)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int ipgre_fb_tunnel_close(struct device *dev)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+#endif
+
+__initfunc(int ipgre_fb_tunnel_init(struct device *dev))
+{
+ struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ struct iphdr *iph;
+
+ ipgre_tunnel_init_gen(dev);
+#ifdef MODULE
+ dev->open = ipgre_fb_tunnel_open;
+ dev->stop = ipgre_fb_tunnel_close;
+#endif
+
+ iph = &ipgre_fb_tunnel.parms.iph;
+ iph->version = 4;
+ iph->protocol = IPPROTO_GRE;
+ iph->ihl = 5;
+ tunnel->hlen = sizeof(struct iphdr) + 4;
+
+ tunnels_wc[0] = &ipgre_fb_tunnel;
+ return 0;
+}
+
+
+static struct inet_protocol ipgre_protocol = {
+ ipgre_rcv, /* GRE handler */
+ ipgre_err, /* TUNNEL error control */
+ 0, /* next */
+ IPPROTO_GRE, /* protocol ID */
+ 0, /* copy */
+ NULL, /* data */
+ "GRE" /* name */
+};
+
+
+/*
+ * And now the modules code and kernel interface.
+ */
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int ipgre_init(void))
+#endif
+{
+ printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
+
+ ipgre_fb_tunnel_dev.priv = (void*)&ipgre_fb_tunnel;
+ ipgre_fb_tunnel_dev.name = ipgre_fb_tunnel.parms.name;
+#ifdef MODULE
+ register_netdev(&ipgre_fb_tunnel_dev);
+#else
+ register_netdevice(&ipgre_fb_tunnel_dev);
+#endif
+
+ inet_add_protocol(&ipgre_protocol);
+ return 0;
+}
+
+#ifdef MODULE
+
+void cleanup_module(void)
+{
+ if ( inet_del_protocol(&ipgre_protocol) < 0 )
+ printk(KERN_INFO "ipgre close: can't remove protocol\n");
+
+ unregister_netdev(&ipgre_fb_tunnel_dev);
+}
+
+#endif
diff --git a/pfinet/linux-src/net/ipv4/ip_input.c b/pfinet/linux-src/net/ipv4/ip_input.c
new file mode 100644
index 00000000..7a3e2618
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_input.c
@@ -0,0 +1,549 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * The Internet Protocol (IP) module.
+ *
+ * Version: $Id: ip_input.c,v 1.37 1999/04/22 10:38:36 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Donald Becker, <becker@super.org>
+ * Alan Cox, <Alan.Cox@linux.org>
+ * Richard Underwood
+ * Stefan Becker, <stefanb@yello.ping.de>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *
+ *
+ * Fixes:
+ * Alan Cox : Commented a couple of minor bits of surplus code
+ * Alan Cox : Undefining IP_FORWARD doesn't include the code
+ * (just stops a compiler warning).
+ * Alan Cox : Frames with >=MAX_ROUTE record routes, strict routes or loose routes
+ * are junked rather than corrupting things.
+ * Alan Cox : Frames to bad broadcast subnets are dumped
+ * We used to process them non broadcast and
+ * boy could that cause havoc.
+ * Alan Cox : ip_forward sets the free flag on the
+ * new frame it queues. Still crap because
+ * it copies the frame but at least it
+ * doesn't eat memory too.
+ * Alan Cox : Generic queue code and memory fixes.
+ * Fred Van Kempen : IP fragment support (borrowed from NET2E)
+ * Gerhard Koerting: Forward fragmented frames correctly.
+ * Gerhard Koerting: Fixes to my fix of the above 8-).
+ * Gerhard Koerting: IP interface addressing fix.
+ * Linus Torvalds : More robustness checks
+ * Alan Cox : Even more checks: Still not as robust as it ought to be
+ * Alan Cox : Save IP header pointer for later
+ * Alan Cox : ip option setting
+ * Alan Cox : Use ip_tos/ip_ttl settings
+ * Alan Cox : Fragmentation bogosity removed
+ * (Thanks to Mark.Bush@prg.ox.ac.uk)
+ * Dmitry Gorodchanin : Send of a raw packet crash fix.
+ * Alan Cox : Silly ip bug when an overlength
+ * fragment turns up. Now frees the
+ * queue.
+ * Linus Torvalds/ : Memory leakage on fragmentation
+ * Alan Cox : handling.
+ * Gerhard Koerting: Forwarding uses IP priority hints
+ * Teemu Rantanen : Fragment problems.
+ * Alan Cox : General cleanup, comments and reformat
+ * Alan Cox : SNMP statistics
+ * Alan Cox : BSD address rule semantics. Also see
+ * UDP as there is a nasty checksum issue
+ * if you do things the wrong way.
+ * Alan Cox : Always defrag, moved IP_FORWARD to the config.in file
+ * Alan Cox : IP options adjust sk->priority.
+ * Pedro Roque : Fix mtu/length error in ip_forward.
+ * Alan Cox : Avoid ip_chk_addr when possible.
+ * Richard Underwood : IP multicasting.
+ * Alan Cox : Cleaned up multicast handlers.
+ * Alan Cox : RAW sockets demultiplex in the BSD style.
+ * Gunther Mayer : Fix the SNMP reporting typo
+ * Alan Cox : Always in group 224.0.0.1
+ * Pauline Middelink : Fast ip_checksum update when forwarding
+ * Masquerading support.
+ * Alan Cox : Multicast loopback error for 224.0.0.1
+ * Alan Cox : IP_MULTICAST_LOOP option.
+ * Alan Cox : Use notifiers.
+ * Bjorn Ekwall : Removed ip_csum (from slhc.c too)
+ * Bjorn Ekwall : Moved ip_fast_csum to ip.h (inline!)
+ * Stefan Becker : Send out ICMP HOST REDIRECT
+ * Arnt Gulbrandsen : ip_build_xmit
+ * Alan Cox : Per socket routing cache
+ * Alan Cox : Fixed routing cache, added header cache.
+ * Alan Cox : Loopback didn't work right in original ip_build_xmit - fixed it.
+ * Alan Cox : Only send ICMP_REDIRECT if src/dest are the same net.
+ * Alan Cox : Incoming IP option handling.
+ * Alan Cox : Set saddr on raw output frames as per BSD.
+ * Alan Cox : Stopped broadcast source route explosions.
+ * Alan Cox : Can disable source routing
+ * Takeshi Sone : Masquerading didn't work.
+ * Dave Bonn,Alan Cox : Faster IP forwarding whenever possible.
+ * Alan Cox : Memory leaks, tramples, misc debugging.
+ * Alan Cox : Fixed multicast (by popular demand 8))
+ * Alan Cox : Fixed forwarding (by even more popular demand 8))
+ * Alan Cox : Fixed SNMP statistics [I think]
+ * Gerhard Koerting : IP fragmentation forwarding fix
+ * Alan Cox : Device lock against page fault.
+ * Alan Cox : IP_HDRINCL facility.
+ * Werner Almesberger : Zero fragment bug
+ * Alan Cox : RAW IP frame length bug
+ * Alan Cox : Outgoing firewall on build_xmit
+ * A.N.Kuznetsov : IP_OPTIONS support throughout the kernel
+ * Alan Cox : Multicast routing hooks
+ * Jos Vos : Do accounting *before* call_in_firewall
+ * Willy Konynenberg : Transparent proxying support
+ *
+ *
+ *
+ * To Fix:
+ * IP fragmentation wants rewriting cleanly. The RFC815 algorithm is much more efficient
+ * and could be made very efficient with the addition of some virtual memory hacks to permit
+ * the allocation of a buffer that can then be 'grown' by twiddling page tables.
+ * Output fragmentation wants updating along with the buffer management to use a single
+ * interleaved copy algorithm so that fragmenting has a one copy overhead. Actual packet
+ * output should probably do its own fragmentation at the UDP/RAW layer. TCP shouldn't cause
+ * fragmentation anyway.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+
+#include <linux/net.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/arp.h>
+#include <net/icmp.h>
+#include <net/raw.h>
+#include <net/checksum.h>
+#include <linux/ip_fw.h>
+#ifdef CONFIG_IP_MASQUERADE
+#include <net/ip_masq.h>
+#endif
+#include <linux/firewall.h>
+#include <linux/mroute.h>
+#include <linux/netlink.h>
+
+/*
+ * SNMP management statistics
+ */
+
+struct ip_mib ip_statistics={2,IPDEFTTL,}; /* Forwarding=No, Default TTL=64 */
+
+
+/*
+ * Handle the issuing of an ioctl() request
+ * for the ip device. This is scheduled to
+ * disappear
+ */
+
+int ip_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+ switch(cmd)
+ {
+ default:
+ return(-EINVAL);
+ }
+}
+
+
+#if defined(CONFIG_IP_TRANSPARENT_PROXY) && !defined(CONFIG_IP_ALWAYS_DEFRAG)
+#define CONFIG_IP_ALWAYS_DEFRAG 1
+#endif
+
+/*
+ * 0 - deliver
+ * 1 - block
+ */
+static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
+{
+ int type;
+
+ type = skb->h.icmph->type;
+ if (type < 32)
+ return test_bit(type, &sk->tp_pinfo.tp_raw4.filter);
+
+ /* Do not block unknown ICMP types */
+ return 0;
+}
+
+/*
+ * Process Router Attention IP option
+ */
+int ip_call_ra_chain(struct sk_buff *skb)
+{
+ struct ip_ra_chain *ra;
+ u8 protocol = skb->nh.iph->protocol;
+ struct sock *last = NULL;
+
+ for (ra = ip_ra_chain; ra; ra = ra->next) {
+ struct sock *sk = ra->sk;
+ if (sk && sk->num == protocol) {
+ if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+ skb = ip_defrag(skb);
+ if (skb == NULL)
+ return 1;
+ }
+ if (last) {
+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2)
+ raw_rcv(last, skb2);
+ }
+ last = sk;
+ }
+ }
+
+ if (last) {
+ raw_rcv(last, skb);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Deliver IP Packets to the higher protocol layers.
+ */
+int ip_local_deliver(struct sk_buff *skb)
+{
+ struct iphdr *iph = skb->nh.iph;
+ struct inet_protocol *ipprot;
+ struct sock *raw_sk=NULL;
+ unsigned char hash;
+ int flag = 0;
+
+#ifndef CONFIG_IP_ALWAYS_DEFRAG
+ /*
+ * Reassemble IP fragments.
+ */
+
+ if (iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+ skb = ip_defrag(skb);
+ if (!skb)
+ return 0;
+ iph = skb->nh.iph;
+ }
+#endif
+
+#ifdef CONFIG_IP_MASQUERADE
+ /*
+ * Do we need to de-masquerade this packet?
+ */
+ {
+ int ret;
+ /*
+ * Some masq modules can re-inject packets if
+ * bad configured.
+ */
+
+ if((IPCB(skb)->flags&IPSKB_MASQUERADED)) {
+ printk(KERN_DEBUG "ip_input(): demasq recursion detected. Check masq modules configuration\n");
+ kfree_skb(skb);
+ return 0;
+ }
+
+ ret = ip_fw_demasquerade(&skb);
+ if (ret < 0) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ if (ret) {
+ iph=skb->nh.iph;
+ IPCB(skb)->flags |= IPSKB_MASQUERADED;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, skb->dev)) {
+ kfree_skb(skb);
+ return 0;
+ }
+ return skb->dst->input(skb);
+ }
+ }
+#endif
+
+ /*
+ * Point into the IP datagram, just past the header.
+ */
+
+ skb->h.raw = skb->nh.raw + iph->ihl*4;
+
+ /*
+ * Deliver to raw sockets. This is fun as to avoid copies we want to make no
+ * surplus copies.
+ *
+ * RFC 1122: SHOULD pass TOS value up to the transport layer.
+ * -> It does. And not only TOS, but all IP header.
+ */
+
+ /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */
+ hash = iph->protocol & (MAX_INET_PROTOS - 1);
+
+ /*
+ * If there maybe a raw socket we must check - if not we don't care less
+ */
+
+ if((raw_sk = raw_v4_htable[hash]) != NULL) {
+ struct sock *sknext = NULL;
+ struct sk_buff *skb1;
+ raw_sk = raw_v4_lookup(raw_sk, iph->protocol, iph->saddr, iph->daddr, skb->dev->ifindex);
+ if(raw_sk) { /* Any raw sockets */
+ do {
+ /* Find the next */
+ sknext = raw_v4_lookup(raw_sk->next, iph->protocol,
+ iph->saddr, iph->daddr, skb->dev->ifindex);
+ if (iph->protocol != IPPROTO_ICMP || !icmp_filter(raw_sk, skb)) {
+ if (sknext == NULL)
+ break;
+ skb1 = skb_clone(skb, GFP_ATOMIC);
+ if(skb1)
+ {
+ raw_rcv(raw_sk, skb1);
+ }
+ }
+ raw_sk = sknext;
+ } while(raw_sk!=NULL);
+
+ /* Here either raw_sk is the last raw socket, or NULL if
+ * none. We deliver to the last raw socket AFTER the
+ * protocol checks as it avoids a surplus copy.
+ */
+ }
+ }
+
+ /*
+ * skb->h.raw now points at the protocol beyond the IP header.
+ */
+
+ for (ipprot = (struct inet_protocol *)inet_protos[hash];ipprot != NULL;ipprot=(struct inet_protocol *)ipprot->next)
+ {
+ struct sk_buff *skb2;
+
+ if (ipprot->protocol != iph->protocol)
+ continue;
+ /*
+ * See if we need to make a copy of it. This will
+ * only be set if more than one protocol wants it.
+ * and then not for the last one. If there is a pending
+ * raw delivery wait for that
+ */
+
+ if (ipprot->copy || raw_sk)
+ {
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if(skb2==NULL)
+ continue;
+ }
+ else
+ {
+ skb2 = skb;
+ }
+ flag = 1;
+
+ /*
+ * Pass on the datagram to each protocol that wants it,
+ * based on the datagram protocol. We should really
+ * check the protocol handler's return values here...
+ */
+
+ ipprot->handler(skb2, ntohs(iph->tot_len) - (iph->ihl * 4));
+ }
+
+ /*
+ * All protocols checked.
+ * If this packet was a broadcast, we may *not* reply to it, since that
+ * causes (proven, grin) ARP storms and a leakage of memory (i.e. all
+ * ICMP reply messages get queued up for transmission...)
+ */
+
+ if(raw_sk!=NULL) /* Shift to last raw user */
+ {
+ raw_rcv(raw_sk, skb);
+
+ }
+ else if (!flag) /* Free and report errors */
+ {
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+ kfree_skb(skb);
+ }
+
+ return(0);
+}
+
+/*
+ * Main IP Receive routine.
+ */
+int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+{
+ struct iphdr *iph = skb->nh.iph;
+#ifdef CONFIG_FIREWALL
+ int fwres;
+ u16 rport;
+#endif /* CONFIG_FIREWALL */
+
+ /*
+ * When the interface is in promisc. mode, drop all the crap
+ * that it receives, do not try to analyse it.
+ */
+ if (skb->pkt_type == PACKET_OTHERHOST)
+ goto drop;
+
+ ip_statistics.IpInReceives++;
+
+ /*
+ * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
+ *
+ * Is the datagram acceptable?
+ *
+ * 1. Length at least the size of an ip header
+ * 2. Version of 4
+ * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums]
+ * 4. Doesn't have a bogus length
+ */
+
+ if (skb->len < sizeof(struct iphdr))
+ goto inhdr_error;
+ if (iph->ihl < 5 || iph->version != 4 || ip_fast_csum((u8 *)iph, iph->ihl) != 0)
+ goto inhdr_error;
+
+ {
+ __u32 len = ntohs(iph->tot_len);
+ if (skb->len < len)
+ goto inhdr_error;
+
+ /*
+ * Our transport medium may have padded the buffer out. Now we know it
+ * is IP we can trim to the true length of the frame.
+ * Note this now means skb->len holds ntohs(iph->tot_len).
+ */
+
+ __skb_trim(skb, len);
+ }
+
+#ifdef CONFIG_IP_ALWAYS_DEFRAG
+ /* Won't send ICMP reply, since skb->dst == NULL. --RR */
+ if (iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+ skb = ip_defrag(skb);
+ if (!skb)
+ return 0;
+ iph = skb->nh.iph;
+ ip_send_check(iph);
+ }
+#endif
+
+#ifdef CONFIG_FIREWALL
+ /*
+ * See if the firewall wants to dispose of the packet.
+ *
+ * We can't do ICMP reply or local delivery before routing,
+ * so we delay those decisions until after route. --RR
+ */
+ fwres = call_in_firewall(PF_INET, dev, iph, &rport, &skb);
+ if (fwres < FW_ACCEPT && fwres != FW_REJECT)
+ goto drop;
+ iph = skb->nh.iph;
+#endif /* CONFIG_FIREWALL */
+
+ /*
+ * Initialise the virtual path cache for the packet. It describes
+ * how the packet travels inside Linux networking.
+ */
+ if (skb->dst == NULL) {
+ if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))
+ goto drop;
+#ifdef CONFIG_CPU_IS_SLOW
+ if (net_cpu_congestion > 10 && !(iph->tos&IPTOS_RELIABILITY) &&
+ IPTOS_PREC(iph->tos) < IPTOS_PREC_INTERNETCONTROL) {
+ goto drop;
+ }
+#endif
+ }
+
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (skb->dst->tclassid) {
+ u32 idx = skb->dst->tclassid;
+ ip_rt_acct[idx&0xFF].o_packets++;
+ ip_rt_acct[idx&0xFF].o_bytes+=skb->len;
+ ip_rt_acct[(idx>>16)&0xFF].i_packets++;
+ ip_rt_acct[(idx>>16)&0xFF].i_bytes+=skb->len;
+ }
+#endif
+
+ if (iph->ihl > 5) {
+ struct ip_options *opt;
+
+ /* It looks as overkill, because not all
+ IP options require packet mangling.
+ But it is the easiest for now, especially taking
+ into account that combination of IP options
+ and running sniffer is extremely rare condition.
+ --ANK (980813)
+ */
+
+ skb = skb_cow(skb, skb_headroom(skb));
+ if (skb == NULL)
+ return 0;
+ iph = skb->nh.iph;
+
+ skb->ip_summed = 0;
+ if (ip_options_compile(NULL, skb))
+ goto inhdr_error;
+
+ opt = &(IPCB(skb)->opt);
+ if (opt->srr) {
+ struct in_device *in_dev = dev->ip_ptr;
+ if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev)) {
+ if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
+ printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n",
+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+ goto drop;
+ }
+ if (ip_options_rcv_srr(skb))
+ goto drop;
+ }
+ }
+
+#ifdef CONFIG_FIREWALL
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (fwres == FW_REDIRECT && (IPCB(skb)->redirport = rport) != 0)
+ return ip_local_deliver(skb);
+#endif /* CONFIG_IP_TRANSPARENT_PROXY */
+
+ if (fwres == FW_REJECT) {
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+ goto drop;
+ }
+#endif /* CONFIG_FIREWALL */
+
+ return skb->dst->input(skb);
+
+inhdr_error:
+ ip_statistics.IpInHdrErrors++;
+drop:
+ kfree_skb(skb);
+ return(0);
+}
+
diff --git a/pfinet/linux-src/net/ipv4/ip_masq.c b/pfinet/linux-src/net/ipv4/ip_masq.c
new file mode 100644
index 00000000..0187c58d
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq.c
@@ -0,0 +1,2545 @@
+/*
+ *
+ * Masquerading functionality
+ *
+ * Copyright (c) 1994 Pauline Middelink
+ *
+ * $Id: ip_masq.c,v 1.34.2.2 1999/08/07 10:56:28 davem Exp $
+ *
+ *
+ * See ip_fw.c for original log
+ *
+ * Fixes:
+ * Juan Jose Ciarlante : Modularized application masquerading (see ip_masq_app.c)
+ * Juan Jose Ciarlante : New struct ip_masq_seq that holds output/input delta seq.
+ * Juan Jose Ciarlante : Added hashed lookup by proto,maddr,mport and proto,saddr,sport
+ * Juan Jose Ciarlante : Fixed deadlock if free ports get exhausted
+ * Juan Jose Ciarlante : Added NO_ADDR status flag.
+ * Richard Lynch : Added IP Autoforward
+ * Nigel Metheringham : Added ICMP handling for demasquerade
+ * Nigel Metheringham : Checksum checking of masqueraded data
+ * Nigel Metheringham : Better handling of timeouts of TCP conns
+ * Delian Delchev : Added support for ICMP requests and replys
+ * Nigel Metheringham : ICMP in ICMP handling, tidy ups, bug fixes, made ICMP optional
+ * Juan Jose Ciarlante : re-assign maddr if no packet received from outside
+ * Juan Jose Ciarlante : ported to 2.1 tree
+ * Juan Jose Ciarlante : reworked control connections
+ * Steven Clarke : Added Port Forwarding
+ * Juan Jose Ciarlante : Just ONE ip_masq_new (!)
+ * Juan Jose Ciarlante : IP masq modules support
+ * Juan Jose Ciarlante : don't go into search loop if mport specified
+ * Juan Jose Ciarlante : locking
+ * Steven Clarke : IP_MASQ_S_xx state design
+ * Juan Jose Ciarlante : IP_MASQ_S state implementation
+ * Juan Jose Ciarlante : xx_get() clears timer, _put() inserts it
+ * Juan Jose Ciarlante : create /proc/net/ip_masq/
+ * Juan Jose Ciarlante : reworked checksums (save payload csum if possible)
+ * Juan Jose Ciarlante : added missing ip_fw_masquerade checksum
+ * Juan Jose Ciarlante : csum savings
+ * Juan Jose Ciarlante : added user-space tunnel creation/del, etc
+ * Juan Jose Ciarlante : (last) moved to ip_masq_user runtime module
+ * Juan Jose Ciarlante : user timeout handling again
+ * Juan Jose Ciarlante : make new modules support optional
+ * Juan Jose Ciarlante : u-space context => locks reworked
+ * Juan Jose Ciarlante : fixed stupid SMP locking bug
+ * Juan Jose Ciarlante : fixed "tap"ing in demasq path by copy-on-w
+ * Juan Jose Ciarlante : make masq_proto_doff() robust against fake sized/corrupted packets
+ * Kai Bankett : do not toss other IP protos in proto_doff()
+ * Dan Kegel : pointed correct NAT behavior for UDP streams
+ * Julian Anastasov : use daddr and dport as hash keys
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <asm/system.h>
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/inet.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/checksum.h>
+#include <net/ip_masq.h>
+
+#ifdef CONFIG_IP_MASQUERADE_MOD
+#include <net/ip_masq_mod.h>
+#endif
+
+#include <linux/sysctl.h>
+#include <linux/ip_fw.h>
+#include <linux/ip_masq.h>
+
+int sysctl_ip_masq_debug = 0;
+
+/*
+ * Exported wrapper
+ */
+int ip_masq_get_debug_level(void)
+{
+ return sysctl_ip_masq_debug;
+}
+
+struct ip_masq_hook *ip_masq_user_hook = NULL;
+
+/*
+ * Timeout table[state]
+ */
+/* static int masq_timeout_table[IP_MASQ_S_LAST+1] = { */
+static struct ip_masq_timeout_table masq_timeout_table = {
+ ATOMIC_INIT(0), /* refcnt */
+ 0, /* scale */
+ {
+ 30*60*HZ, /* IP_MASQ_S_NONE, */
+ 15*60*HZ, /* IP_MASQ_S_ESTABLISHED, */
+ 2*60*HZ, /* IP_MASQ_S_SYN_SENT, */
+ 1*60*HZ, /* IP_MASQ_S_SYN_RECV, */
+ 2*60*HZ, /* IP_MASQ_S_FIN_WAIT, */
+ 2*60*HZ, /* IP_MASQ_S_TIME_WAIT, */
+ 10*HZ, /* IP_MASQ_S_CLOSE, */
+ 60*HZ, /* IP_MASQ_S_CLOSE_WAIT, */
+ 30*HZ, /* IP_MASQ_S_LAST_ACK, */
+ 2*60*HZ, /* IP_MASQ_S_LISTEN, */
+ 5*60*HZ, /* IP_MASQ_S_UDP, */
+ 1*60*HZ, /* IP_MASQ_S_ICMP, */
+ 2*HZ,/* IP_MASQ_S_LAST */
+ }, /* timeout */
+};
+
+#define MASQUERADE_EXPIRE_RETRY masq_timeout_table.timeout[IP_MASQ_S_TIME_WAIT]
+
+static const char * state_name_table[IP_MASQ_S_LAST+1] = {
+ "NONE", /* IP_MASQ_S_NONE, */
+ "ESTABLISHED", /* IP_MASQ_S_ESTABLISHED, */
+ "SYN_SENT", /* IP_MASQ_S_SYN_SENT, */
+ "SYN_RECV", /* IP_MASQ_S_SYN_RECV, */
+ "FIN_WAIT", /* IP_MASQ_S_FIN_WAIT, */
+ "TIME_WAIT", /* IP_MASQ_S_TIME_WAIT, */
+ "CLOSE", /* IP_MASQ_S_CLOSE, */
+ "CLOSE_WAIT", /* IP_MASQ_S_CLOSE_WAIT, */
+ "LAST_ACK", /* IP_MASQ_S_LAST_ACK, */
+ "LISTEN", /* IP_MASQ_S_LISTEN, */
+ "UDP", /* IP_MASQ_S_UDP, */
+ "ICMP", /* IP_MASQ_S_ICMP, */
+ "BUG!", /* IP_MASQ_S_LAST */
+};
+
+#define mNO IP_MASQ_S_NONE
+#define mES IP_MASQ_S_ESTABLISHED
+#define mSS IP_MASQ_S_SYN_SENT
+#define mSR IP_MASQ_S_SYN_RECV
+#define mFW IP_MASQ_S_FIN_WAIT
+#define mTW IP_MASQ_S_TIME_WAIT
+#define mCL IP_MASQ_S_CLOSE
+#define mCW IP_MASQ_S_CLOSE_WAIT
+#define mLA IP_MASQ_S_LAST_ACK
+#define mLI IP_MASQ_S_LISTEN
+
+struct masq_tcp_states_t {
+ int next_state[IP_MASQ_S_LAST]; /* should be _LAST_TCP */
+};
+
+const char * ip_masq_state_name(int state)
+{
+ if (state >= IP_MASQ_S_LAST)
+ return "ERR!";
+ return state_name_table[state];
+}
+
+struct masq_tcp_states_t masq_tcp_states [] = {
+/* INPUT */
+/* mNO, mES, mSS, mSR, mFW, mTW, mCL, mCW, mLA, mLI */
+/*syn*/ {{mSR, mES, mES, mSR, mSR, mSR, mSR, mSR, mSR, mSR }},
+/*fin*/ {{mCL, mCW, mSS, mTW, mTW, mTW, mCL, mCW, mLA, mLI }},
+/*ack*/ {{mCL, mES, mSS, mSR, mFW, mTW, mCL, mCW, mCL, mLI }},
+/*rst*/ {{mCL, mCL, mCL, mSR, mCL, mCL, mCL, mCL, mLA, mLI }},
+
+/* OUTPUT */
+/* mNO, mES, mSS, mSR, mFW, mTW, mCL, mCW, mLA, mLI */
+/*syn*/ {{mSS, mES, mSS, mES, mSS, mSS, mSS, mSS, mSS, mLI }},
+/*fin*/ {{mTW, mFW, mSS, mTW, mFW, mTW, mCL, mTW, mLA, mLI }},
+/*ack*/ {{mES, mES, mSS, mSR, mFW, mTW, mCL, mCW, mLA, mES }},
+/*rst*/ {{mCL, mCL, mSS, mCL, mCL, mTW, mCL, mCL, mCL, mCL }},
+};
+
+static __inline__ int masq_tcp_state_idx(struct tcphdr *th, int output)
+{
+ /*
+ * [0-3]: input states, [4-7]: output.
+ */
+ if (output)
+ output=4;
+
+ if (th->rst)
+ return output+3;
+ if (th->syn)
+ return output+0;
+ if (th->fin)
+ return output+1;
+ if (th->ack)
+ return output+2;
+ return -1;
+}
+
+
+
+static int masq_set_state_timeout(struct ip_masq *ms, int state)
+{
+ struct ip_masq_timeout_table *mstim = ms->timeout_table;
+ int scale;
+
+ /*
+ * Use default timeout table if no specific for this entry
+ */
+ if (!mstim)
+ mstim = &masq_timeout_table;
+
+ ms->timeout = mstim->timeout[ms->state=state];
+ scale = mstim->scale;
+
+ if (scale<0)
+ ms->timeout >>= -scale;
+ else if (scale > 0)
+ ms->timeout <<= scale;
+
+ return state;
+}
+
+static int masq_tcp_state(struct ip_masq *ms, int output, struct tcphdr *th)
+{
+ int state_idx;
+ int new_state = IP_MASQ_S_CLOSE;
+
+ if ((state_idx = masq_tcp_state_idx(th, output)) < 0) {
+ IP_MASQ_DEBUG(1, "masq_state_idx(%d)=%d!!!\n",
+ output, state_idx);
+ goto tcp_state_out;
+ }
+
+ new_state = masq_tcp_states[state_idx].next_state[ms->state];
+
+tcp_state_out:
+ if (new_state!=ms->state)
+ IP_MASQ_DEBUG(1, "%s %s [%c%c%c%c] %08lX:%04X-%08lX:%04X state: %s->%s\n",
+ masq_proto_name(ms->protocol),
+ output? "output" : "input ",
+ th->syn? 'S' : '.',
+ th->fin? 'F' : '.',
+ th->ack? 'A' : '.',
+ th->rst? 'R' : '.',
+ ntohl(ms->saddr), ntohs(ms->sport),
+ ntohl(ms->daddr), ntohs(ms->dport),
+ ip_masq_state_name(ms->state),
+ ip_masq_state_name(new_state));
+ return masq_set_state_timeout(ms, new_state);
+}
+
+
+/*
+ * Handle state transitions
+ */
+static int masq_set_state(struct ip_masq *ms, int output, struct iphdr *iph, void *tp)
+{
+ switch (iph->protocol) {
+ case IPPROTO_ICMP:
+ return masq_set_state_timeout(ms, IP_MASQ_S_ICMP);
+ case IPPROTO_UDP:
+ return masq_set_state_timeout(ms, IP_MASQ_S_UDP);
+ case IPPROTO_TCP:
+ return masq_tcp_state(ms, output, tp);
+ }
+ return -1;
+}
+
+/*
+ * Set LISTEN timeout. (ip_masq_put will setup timer)
+ */
+int ip_masq_listen(struct ip_masq *ms)
+{
+ masq_set_state_timeout(ms, IP_MASQ_S_LISTEN);
+ return ms->timeout;
+}
+
+/*
+ * Dynamic address rewriting
+ */
+extern int sysctl_ip_dynaddr;
+
+/*
+ * Lookup lock
+ */
+rwlock_t __ip_masq_lock = RW_LOCK_UNLOCKED;
+
+/*
+ * Implement IP packet masquerading
+ */
+
+/*
+ * Converts an ICMP reply code into the equivalent request code
+ */
+static __inline__ const __u8 icmp_type_request(__u8 type)
+{
+ switch (type)
+ {
+ case ICMP_ECHOREPLY: return ICMP_ECHO; break;
+ case ICMP_TIMESTAMPREPLY: return ICMP_TIMESTAMP; break;
+ case ICMP_INFO_REPLY: return ICMP_INFO_REQUEST; break;
+ case ICMP_ADDRESSREPLY: return ICMP_ADDRESS; break;
+ default: return (255); break;
+ }
+}
+
+/*
+ * Helper macros - attempt to make code clearer!
+ */
+
+/* ID used in ICMP lookups */
+#define icmp_id(icmph) ((icmph->un).echo.id)
+/* (port) hash value using in ICMP lookups for requests */
+#define icmp_hv_req(icmph) ((__u16)(icmph->code+(__u16)(icmph->type<<8)))
+/* (port) hash value using in ICMP lookups for replies */
+#define icmp_hv_rep(icmph) ((__u16)(icmph->code+(__u16)(icmp_type_request(icmph->type)<<8)))
+
+/*
+ * Last masq_port number in use.
+ * Will cycle in MASQ_PORT boundaries.
+ */
+static __u16 masq_port = PORT_MASQ_BEGIN;
+static spinlock_t masq_port_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * free ports counters (UDP & TCP)
+ *
+ * Their value is _less_ or _equal_ to actual free ports:
+ * same masq port, diff masq addr (firewall iface address) allocated
+ * entries are accounted but their actually don't eat a more than 1 port.
+ *
+ * Greater values could lower MASQ_EXPIRATION setting as a way to
+ * manage 'masq_entries resource'.
+ *
+ * By default we will reuse masq.port iff (output) connection
+ * (5-upla) if not duplicated.
+ * This may break midentd and others ...
+ */
+
+#ifdef CONFIG_IP_MASQ_NREUSE
+#define PORT_MASQ_MUL 1
+#else
+#define PORT_MASQ_MUL 10
+#endif
+
+/*
+ * At the moment, hardcore in sync with masq_proto_num
+ */
+atomic_t ip_masq_free_ports[3] = {
+ ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* UDP */
+ ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* TCP */
+ ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* ICMP */
+};
+
+/*
+ * Counts entries that have been requested with specific mport.
+ * Used for incoming packets to "relax" input rule (port in MASQ range).
+ */
+atomic_t mport_count = ATOMIC_INIT(0);
+
+EXPORT_SYMBOL(ip_masq_get_debug_level);
+EXPORT_SYMBOL(ip_masq_new);
+EXPORT_SYMBOL(ip_masq_listen);
+EXPORT_SYMBOL(ip_masq_free_ports);
+EXPORT_SYMBOL(ip_masq_out_get);
+EXPORT_SYMBOL(ip_masq_in_get);
+EXPORT_SYMBOL(ip_masq_put);
+EXPORT_SYMBOL(ip_masq_control_add);
+EXPORT_SYMBOL(ip_masq_control_del);
+EXPORT_SYMBOL(ip_masq_control_get);
+EXPORT_SYMBOL(ip_masq_user_hook);
+EXPORT_SYMBOL(ip_masq_state_name);
+EXPORT_SYMBOL(ip_masq_select_addr);
+EXPORT_SYMBOL(__ip_masq_lock);
+EXPORT_SYMBOL(ip_masq_m_table);
+EXPORT_SYMBOL(ip_masq_s_table);
+EXPORT_SYMBOL(ip_masq_d_table);
+
+/*
+ * 3 ip_masq hash double linked tables:
+ * 2 for input m{addr,port} and output s{addr,port} pkts lookups.
+ * 1 for extra modules support (daddr)
+ */
+
+#define IP_MASQ_NTABLES 3
+
+struct list_head ip_masq_m_table[IP_MASQ_TAB_SIZE];
+struct list_head ip_masq_s_table[IP_MASQ_TAB_SIZE];
+struct list_head ip_masq_d_table[IP_MASQ_TAB_SIZE];
+
+/*
+ * timeouts
+ */
+
+#if 000 /* FIXED timeout handling */
+static struct ip_fw_masq ip_masq_dummy = {
+ MASQUERADE_EXPIRE_TCP,
+ MASQUERADE_EXPIRE_TCP_FIN,
+ MASQUERADE_EXPIRE_UDP
+};
+
+EXPORT_SYMBOL(ip_masq_expire);
+struct ip_fw_masq *ip_masq_expire = &ip_masq_dummy;
+#endif
+
+/*
+ * These flags enable non-strict d{addr,port} checks
+ * Given that both (in/out) lookup tables are hashed
+ * by m{addr,port} and s{addr,port} this is quite easy
+ */
+
+#define MASQ_DADDR_PASS (IP_MASQ_F_NO_DADDR|IP_MASQ_F_DLOOSE)
+#define MASQ_DPORT_PASS (IP_MASQ_F_NO_DPORT|IP_MASQ_F_DLOOSE)
+
+/*
+ * By default enable dest loose semantics
+ */
+#define CONFIG_IP_MASQ_LOOSE_DEFAULT 1
+
+
+/*
+ * Set masq expiration (deletion) and adds timer,
+ * if timeout==0 cancel expiration.
+ * Warning: it does not check/delete previous timer!
+ */
+
+static void __ip_masq_set_expire(struct ip_masq *ms, unsigned long tout)
+{
+ if (tout) {
+ ms->timer.expires = jiffies+tout;
+ add_timer(&ms->timer);
+ } else {
+ del_timer(&ms->timer);
+ }
+}
+
+
+/*
+ * Returns hash value
+ */
+
+static __inline__ unsigned
+ip_masq_hash_key(unsigned proto, __u32 addr, __u16 port)
+{
+ return (proto^ntohl(addr)^ntohs(port)) & (IP_MASQ_TAB_SIZE-1);
+}
+
+/*
+ * Hashes ip_masq by its proto,addrs,ports.
+ * should be called with locked tables.
+ * returns bool success.
+ */
+
+static int ip_masq_hash(struct ip_masq *ms)
+{
+ unsigned hash;
+
+ if (ms->flags & IP_MASQ_F_HASHED) {
+ IP_MASQ_ERR( "ip_masq_hash(): request for already hashed, called from %p\n",
+ __builtin_return_address(0));
+ return 0;
+ }
+ atomic_add(IP_MASQ_NTABLES, &ms->refcnt);
+
+ if ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS |
+ IP_MASQ_F_SIMPLE_HASH)) == 0)
+ /*
+ * Hash by proto,m{addr,port},d{addr,port}
+ */
+ hash = ip_masq_hash_key(ms->protocol,
+ ms->maddr^ms->daddr, ms->mport^ms->dport);
+ else
+ /*
+ * Hash by proto,m{addr,port}
+ */
+ hash = ip_masq_hash_key(ms->protocol, ms->maddr, ms->mport);
+
+ list_add(&ms->m_list, &ip_masq_m_table[hash]);
+
+ if ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS |
+ IP_MASQ_F_NO_SADDR | IP_MASQ_F_NO_SPORT |
+ IP_MASQ_F_SIMPLE_HASH)) == 0)
+ /*
+ * Hash by proto,s{addr,port},d{addr,port}
+ */
+ hash = ip_masq_hash_key(ms->protocol,
+ ms->saddr^ms->daddr, ms->sport^ms->dport);
+ else
+ /*
+ * Hash by proto,s{addr,port}
+ */
+ hash = ip_masq_hash_key(ms->protocol, ms->saddr, ms->sport);
+
+ list_add(&ms->s_list, &ip_masq_s_table[hash]);
+
+ /*
+ * Hash by proto,d{addr,port}
+ */
+ hash = ip_masq_hash_key(ms->protocol, ms->daddr, ms->dport);
+ list_add(&ms->d_list, &ip_masq_d_table[hash]);
+
+
+ ms->flags |= IP_MASQ_F_HASHED;
+ return 1;
+}
+
+/*
+ * UNhashes ip_masq from ip_masq_[ms]_tables.
+ * should be called with locked tables.
+ * returns bool success.
+ */
+
+static int ip_masq_unhash(struct ip_masq *ms)
+{
+ if (!(ms->flags & IP_MASQ_F_HASHED)) {
+ IP_MASQ_ERR( "ip_masq_unhash(): request for unhash flagged, called from %p\n",
+ __builtin_return_address(0));
+ return 0;
+ }
+ list_del(&ms->m_list);
+ list_del(&ms->s_list);
+ list_del(&ms->d_list);
+
+ atomic_sub(IP_MASQ_NTABLES, &ms->refcnt);
+
+ ms->flags &= ~IP_MASQ_F_HASHED;
+ return 1;
+}
+
+/*
+ * Returns ip_masq associated with supplied parameters, either
+ * broken out of the ip/tcp headers or directly supplied for those
+ * pathological protocols with address/port in the data stream
+ * (ftp, irc). addresses and ports are in network order.
+ * called for pkts coming from OUTside-to-INside the firewall.
+ *
+ * s_addr, s_port: pkt source address (foreign host)
+ * d_addr, d_port: pkt dest address (firewall)
+ *
+ * NB. Cannot check destination address, just for the incoming port.
+ * reason: archie.doc.ac.uk has 6 interfaces, you send to
+ * phoenix and get a reply from any other interface(==dst)!
+ *
+ * [Only for UDP] - AC
+ *
+ * Caller must lock tables
+ */
+
+static struct ip_masq * __ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+{
+ unsigned hash;
+ struct ip_masq *ms = NULL;
+ struct list_head *l,*e;
+
+ hash = ip_masq_hash_key(protocol, d_addr^s_addr, d_port^s_port);
+
+ l = &ip_masq_m_table[hash];
+ for (e=l->next; e!=l; e=e->next) {
+ ms = list_entry(e, struct ip_masq, m_list);
+ if (s_port==ms->dport && s_addr==ms->daddr &&
+ d_port==ms->mport && protocol==ms->protocol &&
+ d_addr==ms->maddr &&
+ ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS)) == 0)
+ ) {
+ IP_MASQ_DEBUG(2, "look/in %d %08X:%04hX->%08X:%04hX OK\n",
+ protocol,
+ s_addr,
+ s_port,
+ d_addr,
+ d_port);
+ atomic_inc(&ms->refcnt);
+ goto out;
+ }
+ }
+
+ hash = ip_masq_hash_key(protocol, d_addr, d_port);
+
+ l = &ip_masq_m_table[hash];
+ for (e=l->next; e!=l; e=e->next) {
+ ms = list_entry(e, struct ip_masq, m_list);
+ if (protocol==ms->protocol &&
+ (d_addr==ms->maddr && d_port==ms->mport) &&
+ (s_addr==ms->daddr || ms->flags & MASQ_DADDR_PASS) &&
+ (s_port==ms->dport || ms->flags & MASQ_DPORT_PASS)
+ ) {
+ IP_MASQ_DEBUG(2, "look/in %d %08X:%04hX->%08X:%04hX OK\n",
+ protocol,
+ s_addr,
+ s_port,
+ d_addr,
+ d_port);
+ atomic_inc(&ms->refcnt);
+ goto out;
+ }
+ }
+ IP_MASQ_DEBUG(2, "look/in %d %08X:%04hX->%08X:%04hX fail\n",
+ protocol,
+ s_addr,
+ s_port,
+ d_addr,
+ d_port);
+
+ ms = NULL;
+out:
+ return ms;
+}
+
+/*
+ * Returns ip_masq associated with supplied parameters, either
+ * broken out of the ip/tcp headers or directly supplied for those
+ * pathological protocols with address/port in the data stream
+ * (ftp, irc). addresses and ports are in network order.
+ * called for pkts coming from inside-to-OUTside the firewall.
+ *
+ * Normally we know the source address and port but for some protocols
+ * (e.g. ftp PASV) we do not know the source port initially. Alas the
+ * hash is keyed on source port so if the first lookup fails then try again
+ * with a zero port, this time only looking at entries marked "no source
+ * port".
+ *
+ * Caller must lock tables
+ */
+
+static struct ip_masq * __ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+{
+ unsigned hash;
+ struct ip_masq *ms = NULL;
+ struct list_head *l,*e;
+
+ /*
+ * Check for "full" addressed entries
+ */
+ hash = ip_masq_hash_key(protocol, s_addr^d_addr, s_port^d_port);
+
+ l = &ip_masq_s_table[hash];
+ for (e=l->next; e!=l; e=e->next) {
+ ms = list_entry(e, struct ip_masq, s_list);
+ if (d_addr==ms->daddr && d_port==ms->dport &&
+ s_addr==ms->saddr && s_port==ms->sport &&
+ protocol==ms->protocol &&
+ ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS |
+ IP_MASQ_F_NO_SADDR | IP_MASQ_F_NO_SPORT)) == 0)
+ ) {
+ IP_MASQ_DEBUG(2, "lk/out0 %d %08X:%04hX->%08X:%04hX OK\n",
+ protocol,
+ s_addr,
+ s_port,
+ d_addr,
+ d_port);
+
+ atomic_inc(&ms->refcnt);
+ goto out;
+ }
+
+ }
+
+ hash = ip_masq_hash_key(protocol, s_addr, s_port);
+
+ l = &ip_masq_s_table[hash];
+ for (e=l->next; e!=l; e=e->next) {
+ ms = list_entry(e, struct ip_masq, s_list);
+ if (protocol == ms->protocol &&
+ s_addr == ms->saddr && s_port == ms->sport &&
+ (d_addr==ms->daddr || ms->flags & MASQ_DADDR_PASS) &&
+ (d_port==ms->dport || ms->flags & MASQ_DPORT_PASS)
+ ) {
+ IP_MASQ_DEBUG(2, "lk/out1 %d %08X:%04hX->%08X:%04hX OK\n",
+ protocol,
+ s_addr,
+ s_port,
+ d_addr,
+ d_port);
+
+ atomic_inc(&ms->refcnt);
+ goto out;
+ }
+
+ }
+
+ /*
+ * Check for NO_SPORT entries
+ */
+ hash = ip_masq_hash_key(protocol, s_addr, 0);
+ l = &ip_masq_s_table[hash];
+ for (e=l->next; e!=l; e=e->next) {
+ ms = list_entry(e, struct ip_masq, s_list);
+ if (ms->flags & IP_MASQ_F_NO_SPORT &&
+ protocol == ms->protocol &&
+ s_addr == ms->saddr &&
+ (d_addr==ms->daddr || ms->flags & MASQ_DADDR_PASS) &&
+ (d_port==ms->dport || ms->flags & MASQ_DPORT_PASS)
+ ) {
+ IP_MASQ_DEBUG(2, "lk/out2 %d %08X:%04hX->%08X:%04hX OK\n",
+ protocol,
+ s_addr,
+ s_port,
+ d_addr,
+ d_port);
+
+ atomic_inc(&ms->refcnt);
+ goto out;
+ }
+ }
+ IP_MASQ_DEBUG(2, "lk/out1 %d %08X:%04hX->%08X:%04hX fail\n",
+ protocol,
+ s_addr,
+ s_port,
+ d_addr,
+ d_port);
+
+ ms = NULL;
+out:
+ return ms;
+}
+
+#ifdef CONFIG_IP_MASQ_NREUSE
+/*
+ * Returns ip_masq for given proto,m_addr,m_port.
+ * called by allocation routine to find an unused m_port.
+ *
+ * Caller must lock tables
+ */
+
+static struct ip_masq * __ip_masq_getbym(int protocol, __u32 m_addr, __u16 m_port)
+{
+ unsigned hash;
+ struct ip_masq *ms = NULL;
+
+ hash = ip_masq_hash_key(protocol, m_addr, m_port);
+
+ for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
+ if ( protocol==ms->protocol &&
+ (m_addr==ms->maddr && m_port==ms->mport)) {
+ atomic_inc(&ms->refcnt);
+ goto out;
+ }
+ }
+
+out:
+ return ms;
+}
+#endif
+
+struct ip_masq * ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+{
+ struct ip_masq *ms;
+
+ read_lock(&__ip_masq_lock);
+ ms = __ip_masq_out_get(protocol, s_addr, s_port, d_addr, d_port);
+ read_unlock(&__ip_masq_lock);
+
+ if (ms)
+ __ip_masq_set_expire(ms, 0);
+ return ms;
+}
+
+struct ip_masq * ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+{
+ struct ip_masq *ms;
+
+ read_lock(&__ip_masq_lock);
+ ms = __ip_masq_in_get(protocol, s_addr, s_port, d_addr, d_port);
+ read_unlock(&__ip_masq_lock);
+
+ if (ms)
+ __ip_masq_set_expire(ms, 0);
+ return ms;
+}
+
+static __inline__ void __ip_masq_put(struct ip_masq *ms)
+{
+ atomic_dec(&ms->refcnt);
+}
+
+void ip_masq_put(struct ip_masq *ms)
+{
+ /*
+ * Decrement refcnt
+ */
+ __ip_masq_put(ms);
+
+ /*
+ * if refcnt==IP_MASQ_NTABLES
+ */
+ if (atomic_read(&ms->refcnt)==IP_MASQ_NTABLES) {
+ __ip_masq_set_expire(ms, ms->timeout);
+ } else {
+ IP_MASQ_DEBUG(0, "did not set timer with refcnt=%d, called from %p\n",
+ atomic_read(&ms->refcnt),
+ __builtin_return_address(0));
+ }
+}
+
+static void masq_expire(unsigned long data)
+{
+ struct ip_masq *ms = (struct ip_masq *)data;
+ ms->timeout = MASQUERADE_EXPIRE_RETRY;
+
+ /*
+ * hey, I'm using it
+ */
+ atomic_inc(&ms->refcnt);
+
+ IP_MASQ_DEBUG(1, "Masqueraded %s %08lX:%04X expired\n",
+ masq_proto_name(ms->protocol),
+ ntohl(ms->saddr),ntohs(ms->sport));
+
+ write_lock(&__ip_masq_lock);
+
+#if 0000
+ /*
+ * Already locked, do bounce ...
+ */
+ if (ip_masq_nlocks(&__ip_masq_lock) != 1) {
+ goto masq_expire_later;
+ }
+
+#endif
+ /*
+ * do I control anybody?
+ */
+ if (atomic_read(&ms->n_control))
+ goto masq_expire_later;
+
+ /*
+ * does anybody controls me?
+ */
+
+ if (ms->control)
+ ip_masq_control_del(ms);
+
+ if (ip_masq_unhash(ms)) {
+ if (ms->flags&IP_MASQ_F_MPORT) {
+ atomic_dec(&mport_count);
+ } else {
+ atomic_inc(ip_masq_free_ports + masq_proto_num(ms->protocol));
+ }
+ ip_masq_unbind_app(ms);
+ }
+
+ /*
+ * refcnt==1 implies I'm the only one referrer
+ */
+ if (atomic_read(&ms->refcnt) == 1) {
+ kfree_s(ms,sizeof(*ms));
+ MOD_DEC_USE_COUNT;
+ goto masq_expire_out;
+ }
+
+masq_expire_later:
+ IP_MASQ_DEBUG(0, "masq_expire delayed: %s %08lX:%04X->%08lX:%04X masq.refcnt-1=%d masq.n_control=%d\n",
+ masq_proto_name(ms->protocol),
+ ntohl(ms->saddr), ntohs(ms->sport),
+ ntohl(ms->daddr), ntohs(ms->dport),
+ atomic_read(&ms->refcnt)-1,
+ atomic_read(&ms->n_control));
+
+ ip_masq_put(ms);
+
+masq_expire_out:
+ write_unlock(&__ip_masq_lock);
+}
+
+static __u16 get_next_mport(void)
+{
+ __u16 mport;
+
+ spin_lock_irq(&masq_port_lock);
+ /*
+ * Try the next available port number
+ */
+ mport = htons(masq_port++);
+ if (masq_port==PORT_MASQ_END) masq_port = PORT_MASQ_BEGIN;
+
+ spin_unlock_irq(&masq_port_lock);
+ return mport;
+}
+
+/*
+ * Create a new masquerade list entry, also allocate an
+ * unused mport, keeping the portnumber between the
+ * given boundaries MASQ_BEGIN and MASQ_END.
+ *
+ * Be careful, it can be called from u-space
+ */
+
+struct ip_masq * ip_masq_new(int proto, __u32 maddr, __u16 mport, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned mflags)
+{
+ struct ip_masq *ms, *mst;
+ int ports_tried;
+ atomic_t *free_ports_p = NULL;
+ static int n_fails = 0;
+ int prio;
+
+
+ if (masq_proto_num(proto)!=-1 && mport == 0) {
+ free_ports_p = ip_masq_free_ports + masq_proto_num(proto);
+
+ if (atomic_read(free_ports_p) == 0) {
+ if (++n_fails < 5)
+ IP_MASQ_ERR( "ip_masq_new(proto=%s): no free ports.\n",
+ masq_proto_name(proto));
+ return NULL;
+ }
+ }
+
+ prio = (mflags&IP_MASQ_F_USER) ? GFP_KERNEL : GFP_ATOMIC;
+
+ ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), prio);
+ if (ms == NULL) {
+ if (++n_fails < 5)
+ IP_MASQ_ERR("ip_masq_new(proto=%s): no memory available.\n",
+ masq_proto_name(proto));
+ return NULL;
+ }
+ MOD_INC_USE_COUNT;
+ memset(ms, 0, sizeof(*ms));
+ INIT_LIST_HEAD(&ms->s_list);
+ INIT_LIST_HEAD(&ms->m_list);
+ INIT_LIST_HEAD(&ms->d_list);
+ init_timer(&ms->timer);
+ ms->timer.data = (unsigned long)ms;
+ ms->timer.function = masq_expire;
+ ms->protocol = proto;
+ ms->saddr = saddr;
+ ms->sport = sport;
+ ms->daddr = daddr;
+ ms->dport = dport;
+ ms->flags = mflags;
+ ms->app_data = NULL;
+ ms->control = NULL;
+
+ atomic_set(&ms->n_control,0);
+ atomic_set(&ms->refcnt,0);
+
+ if (proto == IPPROTO_UDP && !mport)
+#ifdef CONFIG_IP_MASQ_LOOSE_DEFAULT
+ /*
+ * Flag this tunnel as "dest loose"
+ *
+ */
+ ms->flags |= IP_MASQ_F_DLOOSE;
+#else
+ ms->flags |= IP_MASQ_F_NO_DADDR;
+#endif
+
+
+ /* get masq address from rif */
+ ms->maddr = maddr;
+
+ /*
+ * This flag will allow masq. addr (ms->maddr)
+ * to follow forwarding interface address.
+ */
+ ms->flags |= IP_MASQ_F_NO_REPLY;
+
+ /*
+ * We want a specific mport. Be careful.
+ */
+ if (masq_proto_num(proto) == -1 || mport) {
+ ms->mport = mport;
+
+ /*
+ * Check 5-upla uniqueness
+ */
+ if (mflags & IP_MASQ_F_USER)
+ write_lock_bh(&__ip_masq_lock);
+ else
+ write_lock(&__ip_masq_lock);
+
+ mst = __ip_masq_in_get(proto, daddr, dport, maddr, mport);
+ if (mst==NULL) {
+ ms->flags |= IP_MASQ_F_MPORT;
+
+ atomic_inc(&mport_count);
+ ip_masq_hash(ms);
+
+ if (mflags & IP_MASQ_F_USER)
+ write_unlock_bh(&__ip_masq_lock);
+ else
+ write_unlock(&__ip_masq_lock);
+
+ ip_masq_bind_app(ms);
+ atomic_inc(&ms->refcnt);
+ masq_set_state_timeout(ms, IP_MASQ_S_NONE);
+ return ms;
+ }
+ if (mflags & IP_MASQ_F_USER)
+ write_unlock_bh(&__ip_masq_lock);
+ else
+ write_unlock(&__ip_masq_lock);
+
+ __ip_masq_put(mst);
+
+ IP_MASQ_ERR( "Already used connection: %s, %d.%d.%d.%d:%d => %d.%d.%d.%d:%d, called from %p\n",
+ masq_proto_name(proto),
+ NIPQUAD(maddr), ntohs(mport),
+ NIPQUAD(daddr), ntohs(dport),
+ __builtin_return_address(0));
+
+
+ goto mport_nono;
+ }
+
+
+ for (ports_tried = 0;
+ (atomic_read(free_ports_p) && (ports_tried <= (PORT_MASQ_END - PORT_MASQ_BEGIN)));
+ ports_tried++){
+
+ mport = ms->mport = get_next_mport();
+ /*
+ * lookup to find out if this connection is used.
+ */
+
+ if (mflags & IP_MASQ_F_USER)
+ write_lock_bh(&__ip_masq_lock);
+ else
+ write_lock(&__ip_masq_lock);
+
+#ifdef CONFIG_IP_MASQ_NREUSE
+ mst = __ip_masq_getbym(proto, maddr, mport);
+#else
+ mst = __ip_masq_in_get(proto, daddr, dport, maddr, mport);
+#endif
+ if (mst == NULL) {
+
+ if (atomic_read(free_ports_p) == 0) {
+ if (mflags & IP_MASQ_F_USER)
+ write_unlock_bh(&__ip_masq_lock);
+ else
+ write_unlock(&__ip_masq_lock);
+
+ break;
+ }
+ atomic_dec(free_ports_p);
+ ip_masq_hash(ms);
+
+ if (mflags & IP_MASQ_F_USER)
+ write_unlock_bh(&__ip_masq_lock);
+ else
+ write_unlock(&__ip_masq_lock);
+
+ ip_masq_bind_app(ms);
+ n_fails = 0;
+ atomic_inc(&ms->refcnt);
+ masq_set_state_timeout(ms, IP_MASQ_S_NONE);
+ return ms;
+ }
+ if (mflags & IP_MASQ_F_USER)
+ write_unlock_bh(&__ip_masq_lock);
+ else
+ write_unlock(&__ip_masq_lock);
+
+ __ip_masq_put(mst);
+ }
+
+ if (++n_fails < 5)
+ IP_MASQ_ERR( "ip_masq_new(proto=%s): could not get free masq entry (free=%d).\n",
+ masq_proto_name(ms->protocol),
+ atomic_read(free_ports_p));
+mport_nono:
+ kfree_s(ms, sizeof(*ms));
+
+ MOD_DEC_USE_COUNT;
+ return NULL;
+}
+
+/*
+ * Get transport protocol data offset, check against size
+ * return:
+ * 0 if other IP proto
+ * -1 if error
+ */
+static __inline__ int proto_doff(unsigned proto, char *th, unsigned size)
+{
+ int ret = -1;
+ switch (proto) {
+ case IPPROTO_ICMP:
+ if (size >= sizeof(struct icmphdr))
+ ret = sizeof(struct icmphdr);
+ break;
+ case IPPROTO_UDP:
+ if (size >= sizeof(struct udphdr))
+ ret = sizeof(struct udphdr);
+ break;
+ case IPPROTO_TCP:
+ /*
+ * Is this case, this check _also_ avoids
+ * touching an invalid pointer if
+ * size is invalid
+ */
+ if (size >= sizeof(struct tcphdr)) {
+ ret = ((struct tcphdr*)th)->doff << 2;
+ if (ret > size) {
+ ret = -1 ;
+ }
+ }
+
+ break;
+ default:
+ /* Other proto: nothing to say, by now :) */
+ ret = 0;
+ }
+ if (ret < 0)
+ IP_MASQ_DEBUG(0, "mess proto_doff for proto=%d, size =%d\n",
+ proto, size);
+ return ret;
+}
+
+int ip_fw_masquerade(struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb = *skb_p;
+ struct iphdr *iph = skb->nh.iph;
+ union ip_masq_tphdr h;
+ struct ip_masq *ms;
+ int size;
+
+ /*
+ * doff holds transport protocol data offset
+ * csum holds its checksum
+ * csum_ok says if csum is valid
+ */
+ int doff = 0;
+ int csum = 0;
+ int csum_ok = 0;
+
+ /*
+ * We can only masquerade protocols with ports... and hack some ICMPs
+ */
+
+ h.raw = (char*) iph + iph->ihl * 4;
+ size = ntohs(iph->tot_len) - (iph->ihl * 4);
+
+
+ doff = proto_doff(iph->protocol, h.raw, size);
+ if (doff <= 0) {
+ /*
+ * Output path: do not pass other IP protos nor
+ * invalid packets.
+ */
+ return -1;
+ }
+
+ switch (iph->protocol) {
+ case IPPROTO_ICMP:
+ return(ip_fw_masq_icmp(skb_p, maddr));
+ case IPPROTO_UDP:
+ if (h.uh->check == 0)
+ /* No UDP checksum */
+ break;
+ case IPPROTO_TCP:
+ /* Make sure packet is in the masq range */
+ IP_MASQ_DEBUG(3, "O-pkt: %s size=%d\n",
+ masq_proto_name(iph->protocol),
+ size);
+
+#ifdef CONFIG_IP_MASQ_DEBUG
+ if (ip_masq_get_debug_level() > 3) {
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+#endif
+ /* Check that the checksum is OK */
+ switch (skb->ip_summed)
+ {
+ case CHECKSUM_NONE:
+ {
+ csum = csum_partial(h.raw + doff, size - doff, 0);
+ IP_MASQ_DEBUG(3, "O-pkt: %s I-datacsum=%d\n",
+ masq_proto_name(iph->protocol),
+ csum);
+
+ skb->csum = csum_partial(h.raw , doff, csum);
+ }
+ case CHECKSUM_HW:
+ if (csum_tcpudp_magic(iph->saddr, iph->daddr,
+ size, iph->protocol, skb->csum))
+ {
+ IP_MASQ_DEBUG(0, "Outgoing failed %s checksum from %d.%d.%d.%d (size=%d)!\n",
+ masq_proto_name(iph->protocol),
+ NIPQUAD(iph->saddr),
+ size);
+ return -1;
+ }
+ default:
+ /* CHECKSUM_UNNECESSARY */
+ }
+ break;
+ default:
+ return -1;
+ }
+ /*
+ * Now hunt the list to see if we have an old entry
+ */
+
+ /* h.raw = (char*) iph + iph->ihl * 4; */
+
+ IP_MASQ_DEBUG(2, "Outgoing %s %08lX:%04X -> %08lX:%04X\n",
+ masq_proto_name(iph->protocol),
+ ntohl(iph->saddr), ntohs(h.portp[0]),
+ ntohl(iph->daddr), ntohs(h.portp[1]));
+
+ ms = ip_masq_out_get_iph(iph);
+ if (ms!=NULL) {
+
+ /*
+ * If sysctl !=0 and no pkt has been received yet
+ * in this tunnel and routing iface address has changed...
+ * "You are welcome, diald".
+ */
+ if ( sysctl_ip_dynaddr && ms->flags & IP_MASQ_F_NO_REPLY && maddr != ms->maddr) {
+
+ if (sysctl_ip_dynaddr > 1) {
+ IP_MASQ_INFO( "ip_fw_masquerade(): change masq.addr from %d.%d.%d.%d to %d.%d.%d.%d\n",
+ NIPQUAD(ms->maddr),NIPQUAD(maddr));
+ }
+
+ write_lock(&__ip_masq_lock);
+
+ ip_masq_unhash(ms);
+ ms->maddr = maddr;
+ ip_masq_hash(ms);
+
+ write_unlock(&__ip_masq_lock);
+ }
+
+ /*
+ * Set sport if not defined yet (e.g. ftp PASV). Because
+ * masq entries are hashed on sport, unhash with old value
+ * and hash with new.
+ */
+
+ if ( ms->flags & IP_MASQ_F_NO_SPORT && ms->protocol == IPPROTO_TCP ) {
+
+ write_lock(&__ip_masq_lock);
+
+ ip_masq_unhash(ms);
+ ms->flags &= ~IP_MASQ_F_NO_SPORT;
+ ms->sport = h.portp[0];
+ ip_masq_hash(ms); /* hash on new sport */
+
+ write_unlock(&__ip_masq_lock);
+
+ IP_MASQ_DEBUG(1, "ip_fw_masquerade(): filled sport=%d\n",
+ ntohs(ms->sport));
+ }
+ if (ms->flags & IP_MASQ_F_DLOOSE) {
+ /*
+ * update dest loose values
+ */
+ ms->dport = h.portp[1];
+ ms->daddr = iph->daddr;
+ }
+ } else {
+ /*
+ * Nope, not found, create a new entry for it
+ */
+
+#ifdef CONFIG_IP_MASQUERADE_MOD
+ if (!(ms = ip_masq_mod_out_create(skb, iph, maddr)))
+#endif
+ ms = ip_masq_new(iph->protocol,
+ maddr, 0,
+ iph->saddr, h.portp[0],
+ iph->daddr, h.portp[1],
+ 0);
+ if (ms == NULL)
+ return -1;
+ }
+
+ /*
+ * Call module's output update hook
+ */
+
+#ifdef CONFIG_IP_MASQUERADE_MOD
+ ip_masq_mod_out_update(skb, iph, ms);
+#endif
+
+ /*
+ * Change the fragments origin
+ */
+
+ size = skb->len - (h.raw - skb->nh.raw);
+
+ /*
+ * Set iph addr and port from ip_masq obj.
+ */
+ iph->saddr = ms->maddr;
+ h.portp[0] = ms->mport;
+
+ /*
+ * Invalidate csum saving if tunnel has masq helper
+ */
+
+ if (ms->app)
+ csum_ok = 0;
+
+ /*
+ * Attempt ip_masq_app call.
+ * will fix ip_masq and iph seq stuff
+ */
+ if (ip_masq_app_pkt_out(ms, skb_p, maddr) != 0)
+ {
+ /*
+ * skb has possibly changed, update pointers.
+ */
+ skb = *skb_p;
+ iph = skb->nh.iph;
+ h.raw = (char*) iph + iph->ihl *4;
+ size = skb->len - (h.raw - skb->nh.raw);
+ /* doff should have not changed */
+ }
+
+ /*
+ * Adjust packet accordingly to protocol
+ */
+
+ /*
+ * Transport's payload partial csum
+ */
+
+ if (!csum_ok) {
+ csum = csum_partial(h.raw + doff, size - doff, 0);
+ }
+ skb->csum = csum;
+
+ IP_MASQ_DEBUG(3, "O-pkt: %s size=%d O-datacsum=%d\n",
+ masq_proto_name(iph->protocol),
+ size,
+ csum);
+
+ /*
+ * Protocol csum
+ */
+ switch (iph->protocol) {
+ case IPPROTO_TCP:
+ h.th->check = 0;
+ h.th->check=csum_tcpudp_magic(iph->saddr, iph->daddr,
+ size, iph->protocol,
+ csum_partial(h.raw , doff, csum));
+ IP_MASQ_DEBUG(3, "O-pkt: %s O-csum=%d (+%d)\n",
+ masq_proto_name(iph->protocol),
+ h.th->check,
+ (char*) & (h.th->check) - (char*) h.raw);
+
+ break;
+ case IPPROTO_UDP:
+ h.uh->check = 0;
+ h.uh->check=csum_tcpudp_magic(iph->saddr, iph->daddr,
+ size, iph->protocol,
+ csum_partial(h.raw , doff, csum));
+ if (h.uh->check == 0)
+ h.uh->check = 0xFFFF;
+ IP_MASQ_DEBUG(3, "O-pkt: %s O-csum=%d (+%d)\n",
+ masq_proto_name(iph->protocol),
+ h.uh->check,
+ (char*) &(h.uh->check)- (char*) h.raw);
+ break;
+ }
+ ip_send_check(iph);
+
+ IP_MASQ_DEBUG(2, "O-routed from %08lX:%04X with masq.addr %08lX\n",
+ ntohl(ms->maddr),ntohs(ms->mport),ntohl(maddr));
+
+ masq_set_state(ms, 1, iph, h.portp);
+ ip_masq_put(ms);
+
+ return 0;
+ }
+
+/*
+ * Restore original addresses and ports in the original IP
+ * datagram if the failing packet has been [de]masqueraded.
+ * This is ugly in the extreme. We no longer have the original
+ * packet so we have to reconstruct it from the failing packet
+ * plus data in the masq tables. The resulting "original data"
+ * should be good enough to tell the sender which session to
+ * throttle. Relies on far too much knowledge of masq internals,
+ * there ought to be a better way - KAO 990303.
+ *
+ * Moved here from icmp.c - JJC.
+ * Already known: type == ICMP_DEST_UNREACH, IPSKB_MASQUERADED
+ * skb->nh.iph points to original header.
+ *
+ * Must try both OUT and IN tables; we could add a flag
+ * ala IPSKB_MASQUERADED to avoid 2nd tables lookup, but this is VERY
+ * unlike because routing makes mtu decision before reaching
+ * ip_fw_masquerade().
+ *
+ */
+int ip_fw_unmasq_icmp(struct sk_buff *skb) {
+ struct ip_masq *ms;
+ struct iphdr *iph = skb->nh.iph;
+ __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+
+ /*
+ * Always called from _bh context: use read_[un]lock()
+ */
+
+ /*
+ * Peek "out" table, this packet has bounced:
+ * out->in(frag_needed!)->OUT[icmp]
+ *
+ * iph->daddr is IN host
+ * iph->saddr is OUT host
+ */
+ read_lock(&__ip_masq_lock);
+ ms = __ip_masq_out_get(iph->protocol,
+ iph->daddr, portp[1],
+ iph->saddr, portp[0]);
+ read_unlock(&__ip_masq_lock);
+ if (ms) {
+ IP_MASQ_DEBUG(1, "Incoming frag_need rewrited from %d.%d.%d.%d to %d.%d.%d.%d\n",
+ NIPQUAD(iph->daddr), NIPQUAD(ms->maddr));
+ iph->daddr = ms->maddr;
+ portp[1] = ms->mport;
+ __ip_masq_put(ms);
+ return 1;
+ }
+ /*
+ * Peek "in" table
+ * in->out(frag_needed!)->IN[icmp]
+ *
+ * iph->daddr is OUT host
+ * iph->saddr is MASQ host
+ *
+ */
+ read_lock(&__ip_masq_lock);
+ ms = __ip_masq_in_get(iph->protocol,
+ iph->daddr, portp[1],
+ iph->saddr, portp[0]);
+ read_unlock(&__ip_masq_lock);
+ if (ms) {
+ IP_MASQ_DEBUG(1, "Outgoing frag_need rewrited from %d.%d.%d.%d to %d.%d.%d.%d\n",
+ NIPQUAD(iph->saddr), NIPQUAD(ms->saddr));
+ iph->saddr = ms->saddr;
+ portp[0] = ms->sport;
+ __ip_masq_put(ms);
+ return 1;
+ }
+ return 0;
+
+}
+/*
+ * Handle ICMP messages in forward direction.
+ * Find any that might be relevant, check against existing connections,
+ * forward to masqueraded host if relevant.
+ * Currently handles error types - unreachable, quench, ttl exceeded
+ */
+
+int ip_fw_masq_icmp(struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb = *skb_p;
+ struct iphdr *iph = skb->nh.iph;
+ struct icmphdr *icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
+ struct iphdr *ciph; /* The ip header contained within the ICMP */
+ __u16 *pptr; /* port numbers from TCP/UDP contained header */
+ struct ip_masq *ms;
+ unsigned short len = ntohs(iph->tot_len) - (iph->ihl * 4);
+
+ IP_MASQ_DEBUG(2, "Incoming forward ICMP (%d,%d) %lX -> %lX\n",
+ icmph->type, ntohs(icmp_id(icmph)),
+ ntohl(iph->saddr), ntohl(iph->daddr));
+
+#ifdef CONFIG_IP_MASQUERADE_ICMP
+ if ((icmph->type == ICMP_ECHO ) ||
+ (icmph->type == ICMP_TIMESTAMP ) ||
+ (icmph->type == ICMP_INFO_REQUEST ) ||
+ (icmph->type == ICMP_ADDRESS )) {
+
+ IP_MASQ_DEBUG(2, "icmp request rcv %lX->%lX id %d type %d\n",
+ ntohl(iph->saddr),
+ ntohl(iph->daddr),
+ ntohs(icmp_id(icmph)),
+ icmph->type);
+
+ ms = ip_masq_out_get(iph->protocol,
+ iph->saddr,
+ icmp_id(icmph),
+ iph->daddr,
+ icmp_hv_req(icmph));
+ if (ms == NULL) {
+ ms = ip_masq_new(iph->protocol,
+ maddr, 0,
+ iph->saddr, icmp_id(icmph),
+ iph->daddr, icmp_hv_req(icmph),
+ 0);
+ if (ms == NULL)
+ return (-1);
+ IP_MASQ_DEBUG(1, "Created new icmp entry\n");
+ }
+ /* Rewrite source address */
+
+ /*
+ * If sysctl !=0 and no pkt has been received yet
+ * in this tunnel and routing iface address has changed...
+ * "You are welcome, diald".
+ */
+ if ( sysctl_ip_dynaddr && ms->flags & IP_MASQ_F_NO_REPLY && maddr != ms->maddr) {
+
+ if (sysctl_ip_dynaddr > 1) {
+ IP_MASQ_INFO( "ip_fw_masq_icmp(): change masq.addr %d.%d.%d.%d to %d.%d.%d.%d",
+ NIPQUAD(ms->maddr), NIPQUAD(maddr));
+ }
+
+ write_lock(&__ip_masq_lock);
+
+ ip_masq_unhash(ms);
+ ms->maddr = maddr;
+ ip_masq_hash(ms);
+
+ write_unlock(&__ip_masq_lock);
+ }
+
+ iph->saddr = ms->maddr;
+ ip_send_check(iph);
+ /* Rewrite port (id) */
+ (icmph->un).echo.id = ms->mport;
+ icmph->checksum = 0;
+ icmph->checksum = ip_compute_csum((unsigned char *)icmph, len);
+
+ IP_MASQ_DEBUG(2, "icmp request rwt %lX->%lX id %d type %d\n",
+ ntohl(iph->saddr),
+ ntohl(iph->daddr),
+ ntohs(icmp_id(icmph)),
+ icmph->type);
+
+ masq_set_state(ms, 1, iph, icmph);
+ ip_masq_put(ms);
+
+ return 1;
+ }
+#endif
+
+ /*
+ * Work through seeing if this is for us.
+ * These checks are supposed to be in an order that
+ * means easy things are checked first to speed up
+ * processing.... however this means that some
+ * packets will manage to get a long way down this
+ * stack and then be rejected, but thats life
+ */
+ if ((icmph->type != ICMP_DEST_UNREACH) &&
+ (icmph->type != ICMP_SOURCE_QUENCH) &&
+ (icmph->type != ICMP_TIME_EXCEEDED))
+ return 0;
+
+ /* Now find the contained IP header */
+ ciph = (struct iphdr *) (icmph + 1);
+
+#ifdef CONFIG_IP_MASQUERADE_ICMP
+ if (ciph->protocol == IPPROTO_ICMP) {
+ /*
+ * This section handles ICMP errors for ICMP packets
+ */
+ struct icmphdr *cicmph = (struct icmphdr *)((char *)ciph +
+ (ciph->ihl<<2));
+
+
+ IP_MASQ_DEBUG(2, "fw icmp/icmp rcv %lX->%lX id %d type %d\n",
+ ntohl(ciph->saddr),
+ ntohl(ciph->daddr),
+ ntohs(icmp_id(cicmph)),
+ cicmph->type);
+
+ read_lock(&__ip_masq_lock);
+ ms = __ip_masq_out_get(ciph->protocol,
+ ciph->daddr,
+ icmp_id(cicmph),
+ ciph->saddr,
+ icmp_hv_rep(cicmph));
+ read_unlock(&__ip_masq_lock);
+
+ if (ms == NULL)
+ return 0;
+
+ /* Now we do real damage to this packet...! */
+ /* First change the source IP address, and recalc checksum */
+ iph->saddr = ms->maddr;
+ ip_send_check(iph);
+
+ /* Now change the *dest* address in the contained IP */
+ ciph->daddr = ms->maddr;
+ __ip_masq_put(ms);
+
+ ip_send_check(ciph);
+
+ /* Change the ID to the masqed one! */
+ (cicmph->un).echo.id = ms->mport;
+
+ /* And finally the ICMP checksum */
+ icmph->checksum = 0;
+ icmph->checksum = ip_compute_csum((unsigned char *) icmph, len);
+
+
+ IP_MASQ_DEBUG(2, "fw icmp/icmp rwt %lX->%lX id %d type %d\n",
+ ntohl(ciph->saddr),
+ ntohl(ciph->daddr),
+ ntohs(icmp_id(cicmph)),
+ cicmph->type);
+
+ return 1;
+ }
+#endif /* CONFIG_IP_MASQUERADE_ICMP */
+
+ /* We are only interested ICMPs generated from TCP or UDP packets */
+ if ((ciph->protocol != IPPROTO_UDP) && (ciph->protocol != IPPROTO_TCP))
+ return 0;
+
+ /*
+ * Find the ports involved - this packet was
+ * incoming so the ports are right way round
+ * (but reversed relative to outer IP header!)
+ */
+ pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);
+#if 0
+ if (ntohs(pptr[1]) < PORT_MASQ_BEGIN ||
+ ntohs(pptr[1]) > PORT_MASQ_END)
+ return 0;
+#endif
+
+ /* Ensure the checksum is correct */
+ if (ip_compute_csum((unsigned char *) icmph, len))
+ {
+ /* Failed checksum! */
+ IP_MASQ_DEBUG(0, "forward ICMP: failed checksum from %d.%d.%d.%d!\n",
+ NIPQUAD(iph->saddr));
+ return(-1);
+ }
+
+
+ IP_MASQ_DEBUG(2, "Handling forward ICMP for %08lX:%04X -> %08lX:%04X\n",
+ ntohl(ciph->saddr), ntohs(pptr[0]),
+ ntohl(ciph->daddr), ntohs(pptr[1]));
+
+
+#if 0
+ /* This is pretty much what __ip_masq_in_get_iph() does */
+ ms = __ip_masq_in_get(ciph->protocol, ciph->saddr, pptr[0], ciph->daddr, pptr[1]);
+#endif
+ read_lock(&__ip_masq_lock);
+ ms = __ip_masq_out_get(ciph->protocol,
+ ciph->daddr,
+ pptr[1],
+ ciph->saddr,
+ pptr[0]);
+ read_unlock(&__ip_masq_lock);
+
+ if (ms == NULL)
+ return 0;
+
+ /* Now we do real damage to this packet...! */
+ /* First change the source IP address, and recalc checksum */
+ iph->saddr = ms->maddr;
+ ip_send_check(iph);
+
+ /* Now change the *dest* address in the contained IP */
+ ciph->daddr = ms->maddr;
+ ip_send_check(ciph);
+
+ /* the TCP/UDP dest port - cannot redo check */
+ pptr[1] = ms->mport;
+ __ip_masq_put(ms);
+
+ /* And finally the ICMP checksum */
+ icmph->checksum = 0;
+ icmph->checksum = ip_compute_csum((unsigned char *) icmph, len);
+
+
+ IP_MASQ_DEBUG(2, "Rewrote forward ICMP to %08lX:%04X -> %08lX:%04X\n",
+ ntohl(ciph->saddr), ntohs(pptr[0]),
+ ntohl(ciph->daddr), ntohs(pptr[1]));
+
+
+ return 1;
+}
+
+
+/*
+ * Own skb_cow() beast, tweaked for rewriting commonly
+ * used pointers in masq code
+ */
+static struct sk_buff * masq_skb_cow(struct sk_buff **skb_p,
+ struct iphdr **iph_p, unsigned char **t_p) {
+ struct sk_buff *skb=(*skb_p);
+ if (skb_cloned(skb)) {
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (skb) {
+ /*
+ * skb changed, update other pointers
+ */
+ struct iphdr *iph = skb->nh.iph;
+ kfree_skb(*skb_p);
+ *skb_p = skb;
+ *iph_p = iph;
+ *t_p = (char*) iph + iph->ihl * 4;
+ }
+ }
+ return skb;
+}
+
+/*
+ * Handle ICMP messages in reverse (demasquerade) direction.
+ * Find any that might be relevant, check against existing connections,
+ * forward to masqueraded host if relevant.
+ * Currently handles error types - unreachable, quench, ttl exceeded
+ */
+
+int ip_fw_demasq_icmp(struct sk_buff **skb_p)
+{
+ struct sk_buff *skb = *skb_p;
+ struct iphdr *iph = skb->nh.iph;
+ struct icmphdr *icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
+ struct iphdr *ciph; /* The ip header contained within the ICMP */
+ __u16 *pptr; /* port numbers from TCP/UDP contained header */
+ struct ip_masq *ms;
+ unsigned short len = ntohs(iph->tot_len) - (iph->ihl * 4);
+
+
+ IP_MASQ_DEBUG(2, "icmp in/rev (%d,%d) %lX -> %lX\n",
+ icmph->type, ntohs(icmp_id(icmph)),
+ ntohl(iph->saddr), ntohl(iph->daddr));
+
+
+#ifdef CONFIG_IP_MASQUERADE_ICMP
+ if ((icmph->type == ICMP_ECHOREPLY) ||
+ (icmph->type == ICMP_TIMESTAMPREPLY) ||
+ (icmph->type == ICMP_INFO_REPLY) ||
+ (icmph->type == ICMP_ADDRESSREPLY)) {
+
+ IP_MASQ_DEBUG(2, "icmp reply rcv %lX->%lX id %d type %d, req %d\n",
+ ntohl(iph->saddr),
+ ntohl(iph->daddr),
+ ntohs(icmp_id(icmph)),
+ icmph->type,
+ icmp_type_request(icmph->type));
+
+ ms = ip_masq_in_get(iph->protocol,
+ iph->saddr,
+ icmp_hv_rep(icmph),
+ iph->daddr,
+ icmp_id(icmph));
+ if (ms == NULL)
+ return 0;
+
+ /*
+ * got reply, so clear flag
+ */
+ ms->flags &= ~IP_MASQ_F_NO_REPLY;
+
+ if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {
+ ip_masq_put(ms);
+ return -1;
+ }
+
+ /* Reset source address */
+ iph->daddr = ms->saddr;
+ /* Redo IP header checksum */
+ ip_send_check(iph);
+ /* Set ID to fake port number */
+ (icmph->un).echo.id = ms->sport;
+ /* Reset ICMP checksum and set expiry */
+ icmph->checksum=0;
+ icmph->checksum=ip_compute_csum((unsigned char *)icmph,len);
+
+
+
+ IP_MASQ_DEBUG(2, "icmp reply rwt %lX->%lX id %d type %d\n",
+ ntohl(iph->saddr),
+ ntohl(iph->daddr),
+ ntohs(icmp_id(icmph)),
+ icmph->type);
+
+ masq_set_state(ms, 0, iph, icmph);
+ ip_masq_put(ms);
+
+ return 1;
+ } else {
+#endif
+ if ((icmph->type != ICMP_DEST_UNREACH) &&
+ (icmph->type != ICMP_SOURCE_QUENCH) &&
+ (icmph->type != ICMP_TIME_EXCEEDED))
+ return 0;
+#ifdef CONFIG_IP_MASQUERADE_ICMP
+ }
+#endif
+ /*
+ * If we get here we have an ICMP error of one of the above 3 types
+ * Now find the contained IP header
+ */
+
+ ciph = (struct iphdr *) (icmph + 1);
+
+#ifdef CONFIG_IP_MASQUERADE_ICMP
+ if (ciph->protocol == IPPROTO_ICMP) {
+ /*
+ * This section handles ICMP errors for ICMP packets
+ *
+ * First get a new ICMP header structure out of the IP packet
+ */
+ struct icmphdr *cicmph = (struct icmphdr *)((char *)ciph +
+ (ciph->ihl<<2));
+
+
+ IP_MASQ_DEBUG(2, "rv icmp/icmp rcv %lX->%lX id %d type %d\n",
+ ntohl(ciph->saddr),
+ ntohl(ciph->daddr),
+ ntohs(icmp_id(cicmph)),
+ cicmph->type);
+
+ read_lock(&__ip_masq_lock);
+ ms = __ip_masq_in_get(ciph->protocol,
+ ciph->daddr,
+ icmp_hv_req(cicmph),
+ ciph->saddr,
+ icmp_id(cicmph));
+ read_unlock(&__ip_masq_lock);
+
+ if (ms == NULL)
+ return 0;
+
+ if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {
+ __ip_masq_put(ms);
+ return -1;
+ }
+ ciph = (struct iphdr *) (icmph + 1);
+ cicmph = (struct icmphdr *)((char *)ciph +
+ (ciph->ihl<<2));
+ /* Now we do real damage to this packet...! */
+ /* First change the dest IP address, and recalc checksum */
+ iph->daddr = ms->saddr;
+ ip_send_check(iph);
+
+ /* Now change the *source* address in the contained IP */
+ ciph->saddr = ms->saddr;
+ ip_send_check(ciph);
+
+ /* Change the ID to the original one! */
+ (cicmph->un).echo.id = ms->sport;
+ __ip_masq_put(ms);
+
+ /* And finally the ICMP checksum */
+ icmph->checksum = 0;
+ icmph->checksum = ip_compute_csum((unsigned char *) icmph, len);
+
+
+ IP_MASQ_DEBUG(2, "rv icmp/icmp rwt %lX->%lX id %d type %d\n",
+ ntohl(ciph->saddr),
+ ntohl(ciph->daddr),
+ ntohs(icmp_id(cicmph)),
+ cicmph->type);
+
+ return 1;
+ }
+#endif /* CONFIG_IP_MASQUERADE_ICMP */
+
+ /* We are only interested ICMPs generated from TCP or UDP packets */
+ if ((ciph->protocol != IPPROTO_UDP) &&
+ (ciph->protocol != IPPROTO_TCP))
+ return 0;
+
+ /*
+ * Find the ports involved - remember this packet was
+ * *outgoing* so the ports are reversed (and addresses)
+ */
+ pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);
+ if (ntohs(pptr[0]) < PORT_MASQ_BEGIN ||
+ ntohs(pptr[0]) > PORT_MASQ_END)
+ return 0;
+
+ /* Ensure the checksum is correct */
+ if (ip_compute_csum((unsigned char *) icmph, len))
+ {
+ /* Failed checksum! */
+ IP_MASQ_ERR( "reverse ICMP: failed checksum from %d.%d.%d.%d!\n",
+ NIPQUAD(iph->saddr));
+ return(-1);
+ }
+
+
+ IP_MASQ_DEBUG(2, "Handling reverse ICMP for %08lX:%04X -> %08lX:%04X\n",
+ ntohl(ciph->saddr), ntohs(pptr[0]),
+ ntohl(ciph->daddr), ntohs(pptr[1]));
+
+
+ /* This is pretty much what __ip_masq_in_get_iph() does, except params are wrong way round */
+ read_lock(&__ip_masq_lock);
+ ms = __ip_masq_in_get(ciph->protocol,
+ ciph->daddr,
+ pptr[1],
+ ciph->saddr,
+ pptr[0]);
+ read_unlock(&__ip_masq_lock);
+
+ if (ms == NULL)
+ return 0;
+
+ if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {
+ __ip_masq_put(ms);
+ return -1;
+ }
+ ciph = (struct iphdr *) (icmph + 1);
+ pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);
+
+ /* Now we do real damage to this packet...! */
+ /* First change the dest IP address, and recalc checksum */
+ iph->daddr = ms->saddr;
+ ip_send_check(iph);
+
+ /* Now change the *source* address in the contained IP */
+ ciph->saddr = ms->saddr;
+ ip_send_check(ciph);
+
+ /* the TCP/UDP source port - cannot redo check */
+ pptr[0] = ms->sport;
+ __ip_masq_put(ms);
+
+ /* And finally the ICMP checksum */
+ icmph->checksum = 0;
+ icmph->checksum = ip_compute_csum((unsigned char *) icmph, len);
+
+
+ IP_MASQ_DEBUG(2, "Rewrote reverse ICMP to %08lX:%04X -> %08lX:%04X\n",
+ ntohl(ciph->saddr), ntohs(pptr[0]),
+ ntohl(ciph->daddr), ntohs(pptr[1]));
+
+
+ return 1;
+}
+
+ /*
+ * Check if it's an masqueraded port, look it up,
+ * and send it on its way...
+ *
+ * Better not have many hosts using the designated portrange
+ * as 'normal' ports, or you'll be spending many time in
+ * this function.
+ */
+
+int ip_fw_demasquerade(struct sk_buff **skb_p)
+{
+ struct sk_buff *skb = *skb_p;
+ struct iphdr *iph = skb->nh.iph;
+ union ip_masq_tphdr h;
+ struct ip_masq *ms;
+ unsigned short size;
+ int doff = 0;
+ int csum = 0;
+ int csum_ok = 0;
+ __u32 maddr;
+
+ /*
+ * Big tappo: only PACKET_HOST (nor loopback neither mcasts)
+ * ... don't know why 1st test DOES NOT include 2nd (?)
+ */
+
+ if (skb->pkt_type != PACKET_HOST || skb->dev == &loopback_dev) {
+ IP_MASQ_DEBUG(2, "ip_fw_demasquerade(): packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",
+ skb->pkt_type,
+ iph->protocol,
+ NIPQUAD(iph->daddr));
+ return 0;
+ }
+
+ h.raw = (char*) iph + iph->ihl * 4;
+
+ /*
+ * IP payload size
+ */
+ size = ntohs(iph->tot_len) - (iph->ihl * 4);
+
+ doff = proto_doff(iph->protocol, h.raw, size);
+
+ switch (doff) {
+ case 0:
+ /*
+ * Input path: other IP protos Ok, will
+ * reach local sockets path.
+ */
+ return 0;
+ case -1:
+ IP_MASQ_DEBUG(0, "I-pkt invalid packet data size\n");
+ return -1;
+ }
+
+ maddr = iph->daddr;
+ switch (iph->protocol) {
+ case IPPROTO_ICMP:
+ return(ip_fw_demasq_icmp(skb_p));
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ /*
+ * Make sure packet is in the masq range
+ * ... or some mod-ule relaxes input range
+ * ... or there is still some `special' mport opened
+ */
+ if ((ntohs(h.portp[1]) < PORT_MASQ_BEGIN
+ || ntohs(h.portp[1]) > PORT_MASQ_END)
+#ifdef CONFIG_IP_MASQUERADE_MOD
+ && (ip_masq_mod_in_rule(skb, iph) != 1)
+#endif
+ && atomic_read(&mport_count) == 0 )
+ return 0;
+
+ /* Check that the checksum is OK */
+ if ((iph->protocol == IPPROTO_UDP) && (h.uh->check == 0))
+ /* No UDP checksum */
+ break;
+#ifdef CONFIG_IP_MASQ_DEBUG
+ if (ip_masq_get_debug_level() > 3) {
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+#endif
+
+ switch (skb->ip_summed)
+ {
+ case CHECKSUM_NONE:
+ csum = csum_partial(h.raw + doff, size - doff, 0);
+ csum_ok++;
+ skb->csum = csum_partial(h.raw , doff, csum);
+
+ case CHECKSUM_HW:
+ if (csum_tcpudp_magic(iph->saddr, iph->daddr,
+ size, iph->protocol, skb->csum))
+ {
+ IP_MASQ_DEBUG(0, "Incoming failed %s checksum from %d.%d.%d.%d (size=%d)!\n",
+ masq_proto_name(iph->protocol),
+ NIPQUAD(iph->saddr),
+ size);
+ return -1;
+ }
+ default:
+ /* CHECKSUM_UNNECESSARY */
+ }
+ break;
+ default:
+ return 0;
+ }
+
+
+
+ IP_MASQ_DEBUG(2, "Incoming %s %08lX:%04X -> %08lX:%04X\n",
+ masq_proto_name(iph->protocol),
+ ntohl(iph->saddr), ntohs(h.portp[0]),
+ ntohl(iph->daddr), ntohs(h.portp[1]));
+
+ /*
+ * reroute to original host:port if found...
+ */
+
+ ms = ip_masq_in_get_iph(iph);
+
+ /*
+ * Give additional modules a chance to create an entry
+ */
+#ifdef CONFIG_IP_MASQUERADE_MOD
+ if (!ms)
+ ms = ip_masq_mod_in_create(skb, iph, maddr);
+
+ /*
+ * Call module's input update hook
+ */
+ ip_masq_mod_in_update(skb, iph, ms);
+#endif
+
+
+ if (ms != NULL)
+ {
+
+ /*
+ * got reply, so clear flag
+ */
+ ms->flags &= ~IP_MASQ_F_NO_REPLY;
+
+ /*
+ * Set daddr,dport if not defined yet
+ * and tunnel is not setup as "dest loose"
+ */
+
+ if (ms->flags & IP_MASQ_F_DLOOSE) {
+ /*
+ * update dest loose values
+ */
+ ms->dport = h.portp[0];
+ ms->daddr = iph->saddr;
+ } else {
+ if ( ms->flags & IP_MASQ_F_NO_DPORT ) { /* && ms->protocol == IPPROTO_TCP ) { */
+
+ write_lock(&__ip_masq_lock);
+
+ ip_masq_unhash(ms);
+ ms->flags &= ~IP_MASQ_F_NO_DPORT;
+ ms->dport = h.portp[0];
+ ip_masq_hash(ms); /* hash on new dport */
+
+ write_unlock(&__ip_masq_lock);
+
+ IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled dport=%d\n",
+ ntohs(ms->dport));
+
+ }
+ if (ms->flags & IP_MASQ_F_NO_DADDR ) { /* && ms->protocol == IPPROTO_TCP) { */
+
+ write_lock(&__ip_masq_lock);
+
+ ip_masq_unhash(ms);
+ ms->flags &= ~IP_MASQ_F_NO_DADDR;
+ ms->daddr = iph->saddr;
+ ip_masq_hash(ms); /* hash on new daddr */
+
+ write_unlock(&__ip_masq_lock);
+
+ IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled daddr=%lX\n",
+ ntohl(ms->daddr));
+
+ }
+ }
+ if ((skb=masq_skb_cow(skb_p, &iph, &h.raw)) == NULL) {
+ ip_masq_put(ms);
+ return -1;
+ }
+ iph->daddr = ms->saddr;
+ h.portp[1] = ms->sport;
+
+ /*
+ * Invalidate csum saving if tunnel has masq helper
+ */
+
+ if (ms->app)
+ csum_ok = 0;
+
+ /*
+ * Attempt ip_masq_app call.
+ * will fix ip_masq and iph ack_seq stuff
+ */
+
+ if (ip_masq_app_pkt_in(ms, skb_p, maddr) != 0)
+ {
+ /*
+ * skb has changed, update pointers.
+ */
+
+ skb = *skb_p;
+ iph = skb->nh.iph;
+ h.raw = (char*) iph + iph->ihl*4;
+ size = ntohs(iph->tot_len) - (iph->ihl * 4);
+ }
+
+ /*
+ * Yug! adjust UDP/TCP checksums
+ */
+
+ /*
+ * Transport's payload partial csum
+ */
+
+ if (!csum_ok) {
+ csum = csum_partial(h.raw + doff, size - doff, 0);
+ }
+ skb->csum = csum;
+
+ /*
+ * Protocol csum
+ */
+ switch (iph->protocol) {
+ case IPPROTO_TCP:
+ h.th->check = 0;
+ h.th->check=csum_tcpudp_magic(iph->saddr, iph->daddr,
+ size, iph->protocol,
+ csum_partial(h.raw , doff, csum));
+ break;
+ case IPPROTO_UDP:
+ h.uh->check = 0;
+ h.uh->check=csum_tcpudp_magic(iph->saddr, iph->daddr,
+ size, iph->protocol,
+ csum_partial(h.raw , doff, csum));
+ if (h.uh->check == 0)
+ h.uh->check = 0xFFFF;
+ break;
+ }
+ ip_send_check(iph);
+
+ IP_MASQ_DEBUG(2, "I-routed to %08lX:%04X\n",ntohl(iph->daddr),ntohs(h.portp[1]));
+
+ masq_set_state (ms, 0, iph, h.portp);
+ ip_masq_put(ms);
+
+ return 1;
+ }
+
+ /* sorry, all this trouble for a no-hit :) */
+ return 0;
+}
+
+
+void ip_masq_control_add(struct ip_masq *ms, struct ip_masq* ctl_ms)
+{
+ if (ms->control) {
+ IP_MASQ_ERR( "request control ADD for already controlled: %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->saddr),ntohs(ms->sport),
+ NIPQUAD(ms->daddr),ntohs(ms->dport));
+ ip_masq_control_del(ms);
+ }
+ IP_MASQ_DEBUG(1, "ADDing control for: ms.dst=%d.%d.%d.%d:%d ctl_ms.dst=%d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->daddr),ntohs(ms->dport),
+ NIPQUAD(ctl_ms->daddr),ntohs(ctl_ms->dport));
+ ms->control = ctl_ms;
+ atomic_inc(&ctl_ms->n_control);
+}
+
+void ip_masq_control_del(struct ip_masq *ms)
+{
+ struct ip_masq *ctl_ms = ms->control;
+ if (!ctl_ms) {
+ IP_MASQ_ERR( "request control DEL for uncontrolled: %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->saddr),ntohs(ms->sport),
+ NIPQUAD(ms->daddr),ntohs(ms->dport));
+ return;
+ }
+ IP_MASQ_DEBUG(1, "DELeting control for: ms.dst=%d.%d.%d.%d:%d ctl_ms.dst=%d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->daddr),ntohs(ms->dport),
+ NIPQUAD(ctl_ms->daddr),ntohs(ctl_ms->dport));
+ ms->control = NULL;
+ if (atomic_read(&ctl_ms->n_control) == 0) {
+ IP_MASQ_ERR( "BUG control DEL with n=0 : %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n",
+ NIPQUAD(ms->saddr),ntohs(ms->sport),
+ NIPQUAD(ms->daddr),ntohs(ms->dport));
+ return;
+
+ }
+ atomic_dec(&ctl_ms->n_control);
+}
+
+struct ip_masq * ip_masq_control_get(struct ip_masq *ms)
+{
+ return ms->control;
+}
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * /proc/net entries
+ * From userspace
+ */
+static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset,
+ int length, int unused)
+{
+ off_t pos=0, begin;
+ struct ip_masq *ms;
+ char temp[129];
+ int idx = 0;
+ int len=0;
+ struct list_head *l,*e;
+
+ if (offset < 128)
+ {
+ sprintf(temp,
+ "Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta PDelta Expires (free=%d,%d,%d)",
+ atomic_read(ip_masq_free_ports),
+ atomic_read(ip_masq_free_ports+1),
+ atomic_read(ip_masq_free_ports+2));
+ len = sprintf(buffer, "%-127s\n", temp);
+ }
+ pos = 128;
+
+ for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
+ {
+ /*
+ * Lock is actually only need in next loop
+ * we are called from uspace: must stop bh.
+ */
+ read_lock_bh(&__ip_masq_lock);
+
+ l = &ip_masq_m_table[idx];
+ for (e=l->next; e!=l; e=e->next) {
+ ms = list_entry(e, struct ip_masq, m_list);
+ pos += 128;
+ if (pos <= offset) {
+ len = 0;
+ continue;
+ }
+
+ /*
+ * We have locked the tables, no need to del/add timers
+ * nor cli() 8)
+ */
+
+ sprintf(temp,"%s %08lX:%04X %08lX:%04X %04X %08X %6d %6d %7lu",
+ masq_proto_name(ms->protocol),
+ ntohl(ms->saddr), ntohs(ms->sport),
+ ntohl(ms->daddr), ntohs(ms->dport),
+ ntohs(ms->mport),
+ ms->out_seq.init_seq,
+ ms->out_seq.delta,
+ ms->out_seq.previous_delta,
+ ms->timer.expires-jiffies);
+ len += sprintf(buffer+len, "%-127s\n", temp);
+
+ if(len >= length) {
+
+ read_unlock_bh(&__ip_masq_lock);
+ goto done;
+ }
+ }
+ read_unlock_bh(&__ip_masq_lock);
+
+ }
+done:
+
+
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len>length)
+ len = length;
+ return len;
+}
+
+#endif
+
+/*
+ * Timeouts handling by ipfwadm/ipchains
+ * From ip_fw.c
+ */
+
+int ip_fw_masq_timeouts(void *m, int len)
+{
+ struct ip_fw_masq *masq;
+ int ret = EINVAL;
+
+ if (len != sizeof(struct ip_fw_masq)) {
+ IP_MASQ_DEBUG(1, "ip_fw_masq_timeouts: length %d, expected %d\n",
+ len, sizeof(struct ip_fw_masq));
+ } else {
+ masq = (struct ip_fw_masq *)m;
+ if (masq->tcp_timeout)
+ masq_timeout_table.timeout[IP_MASQ_S_ESTABLISHED]
+ = masq->tcp_timeout;
+
+ if (masq->tcp_fin_timeout)
+ masq_timeout_table.timeout[IP_MASQ_S_FIN_WAIT]
+ = masq->tcp_fin_timeout;
+
+ if (masq->udp_timeout)
+ masq_timeout_table.timeout[IP_MASQ_S_UDP]
+ = masq->udp_timeout;
+ ret = 0;
+ }
+ return ret;
+}
+/*
+ * Module autoloading stuff
+ */
+
+static int ip_masq_user_check_hook(void) {
+#ifdef CONFIG_KMOD
+ if (ip_masq_user_hook == NULL) {
+ IP_MASQ_DEBUG(1, "About to request \"ip_masq_user\" module\n");
+ request_module("ip_masq_user");
+ }
+#endif /* CONFIG_KMOD */
+ return (ip_masq_user_hook != NULL);
+}
+
+/*
+ * user module hook- info
+ */
+static int ip_masq_user_info(char *buffer, char **start, off_t offset,
+ int len, int *eof, void *data)
+{
+ int ret = -ENOPKG;
+ if (ip_masq_user_check_hook()) {
+ ret = ip_masq_user_hook->info(buffer, start, offset, len, (int) data);
+ }
+ return ret;
+}
+
+/*
+ * user module hook- entry mgmt
+ */
+static int ip_masq_user_ctl(int optname, void *arg, int arglen)
+{
+ int ret = -ENOPKG;
+ if (ip_masq_user_check_hook()) {
+ ret = ip_masq_user_hook->ctl(optname, arg, arglen);
+ }
+ return ret;
+}
+
+/*
+ * Control from ip_sockglue
+ * MAIN ENTRY point from userspace (apart from /proc *info entries)
+ * Returns errno
+ */
+int ip_masq_uctl(int optname, char * optval , int optlen)
+{
+ struct ip_masq_ctl masq_ctl;
+ int ret = -EINVAL;
+
+ if(optlen>sizeof(masq_ctl))
+ return -EINVAL;
+
+ if(copy_from_user(&masq_ctl,optval,optlen))
+ return -EFAULT;
+
+ IP_MASQ_DEBUG(1,"ip_masq_ctl(optname=%d, optlen=%d, target=%d, cmd=%d)\n",
+ optname, optlen, masq_ctl.m_target, masq_ctl.m_cmd);
+
+ switch (masq_ctl.m_target) {
+ case IP_MASQ_TARGET_USER:
+ ret = ip_masq_user_ctl(optname, &masq_ctl, optlen);
+ break;
+#ifdef CONFIG_IP_MASQUERADE_MOD
+ case IP_MASQ_TARGET_MOD:
+ ret = ip_masq_mod_ctl(optname, &masq_ctl, optlen);
+ break;
+#endif
+ }
+
+ /*
+ * If ret>0, copy to user space
+ */
+
+ if (ret > 0 && ret <= sizeof (masq_ctl)) {
+ if (copy_to_user(optval, &masq_ctl, ret) )
+ return -EFAULT;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_net_ip_masq = NULL;
+
+#ifdef MODULE
+static void ip_masq_proc_count(struct inode *inode, int fill)
+{
+ if (fill)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+}
+#endif
+
+int ip_masq_proc_register(struct proc_dir_entry *ent)
+{
+ if (!proc_net_ip_masq) return -1;
+ IP_MASQ_DEBUG(1, "registering \"/proc/net/ip_masq/%s\" entry\n",
+ ent->name);
+ return proc_register(proc_net_ip_masq, ent);
+}
+void ip_masq_proc_unregister(struct proc_dir_entry *ent)
+{
+ if (!proc_net_ip_masq) return;
+ IP_MASQ_DEBUG(1, "unregistering \"/proc/net/ip_masq/%s\" entry\n",
+ ent->name);
+ proc_unregister(proc_net_ip_masq, ent->low_ino);
+}
+
+
+__initfunc(static void masq_proc_init(void))
+{
+ IP_MASQ_DEBUG(1,"registering /proc/net/ip_masq\n");
+ if (!proc_net_ip_masq) {
+ struct proc_dir_entry *ent;
+ ent = create_proc_entry("net/ip_masq", S_IFDIR, 0);
+ if (ent) {
+#ifdef MODULE
+ ent->fill_inode = ip_masq_proc_count;
+#endif
+ proc_net_ip_masq = ent;
+ } else {
+ IP_MASQ_ERR("Could not create \"/proc/net/ip_masq\" entry\n");
+ }
+ }
+}
+#endif /* CONFIG_PROC_FS */
+/*
+ * Wrapper over inet_select_addr()
+ */
+u32 ip_masq_select_addr(struct device *dev, u32 dst, int scope)
+{
+ return inet_select_addr(dev, dst, scope);
+}
+
+/*
+ * Initialize ip masquerading
+ */
+__initfunc(int ip_masq_init(void))
+{
+ int idx;
+ for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++) {
+ INIT_LIST_HEAD(&ip_masq_s_table[idx]);
+ INIT_LIST_HEAD(&ip_masq_m_table[idx]);
+ INIT_LIST_HEAD(&ip_masq_d_table[idx]);
+ }
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&(struct proc_dir_entry) {
+ PROC_NET_IPMSQHST, 13, "ip_masquerade",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_msqhst_procinfo
+ });
+ masq_proc_init();
+
+ ip_masq_proc_register(&(struct proc_dir_entry) {
+ 0, 3, "tcp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ NULL, /* get_info */
+ NULL, /* fill_inode */
+ NULL, NULL, NULL,
+ (char *) IPPROTO_TCP,
+ ip_masq_user_info
+ });
+ ip_masq_proc_register(&(struct proc_dir_entry) {
+ 0, 3, "udp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ NULL, /* get_info */
+ NULL, /* fill_inode */
+ NULL, NULL, NULL,
+ (char *) IPPROTO_UDP,
+ ip_masq_user_info
+ });
+ ip_masq_proc_register(&(struct proc_dir_entry) {
+ 0, 4, "icmp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ NULL, /* get_info */
+ NULL, /* fill_inode */
+ NULL, NULL, NULL,
+ (char *) IPPROTO_ICMP,
+ ip_masq_user_info
+ });
+#endif
+#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
+ ip_autofw_init();
+#endif
+#ifdef CONFIG_IP_MASQUERADE_IPPORTFW
+ ip_portfw_init();
+#endif
+#ifdef CONFIG_IP_MASQUERADE_MFW
+ ip_mfw_init();
+#endif
+ ip_masq_app_init();
+
+ return 0;
+}
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_app.c b/pfinet/linux-src/net/ipv4/ip_masq_app.c
new file mode 100644
index 00000000..84e059fa
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_app.c
@@ -0,0 +1,603 @@
+/*
+ * IP_MASQ_APP application masquerading module
+ *
+ *
+ * $Id: ip_masq_app.c,v 1.16 1998/08/29 23:51:14 davem Exp $
+ *
+ * Author: Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ * JJC : Implemented also input pkt hook
+ * Miquel van Smoorenburg : Copy more stuff when resizing skb
+ *
+ *
+ * FIXME:
+ * - ip_masq_skb_replace(): use same skb if space available.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <asm/system.h>
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#include <net/ip_masq.h>
+
+#define IP_MASQ_APP_TAB_SIZE 16 /* must be power of 2 */
+
+#define IP_MASQ_APP_HASH(proto, port) ((port^proto) & (IP_MASQ_APP_TAB_SIZE-1))
+#define IP_MASQ_APP_TYPE(proto, port) ( proto<<16 | port )
+#define IP_MASQ_APP_PORT(type) ( type & 0xffff )
+#define IP_MASQ_APP_PROTO(type) ( (type>>16) & 0x00ff )
+
+
+EXPORT_SYMBOL(register_ip_masq_app);
+EXPORT_SYMBOL(unregister_ip_masq_app);
+EXPORT_SYMBOL(ip_masq_skb_replace);
+
+/*
+ * will hold masq app. hashed list heads
+ */
+
+struct ip_masq_app *ip_masq_app_base[IP_MASQ_APP_TAB_SIZE];
+
+/*
+ * ip_masq_app registration routine
+ * port: host byte order.
+ */
+
+int register_ip_masq_app(struct ip_masq_app *mapp, unsigned short proto, __u16 port)
+{
+ unsigned long flags;
+ unsigned hash;
+ if (!mapp) {
+ IP_MASQ_ERR("register_ip_masq_app(): NULL arg\n");
+ return -EINVAL;
+ }
+ mapp->type = IP_MASQ_APP_TYPE(proto, port);
+ mapp->n_attach = 0;
+ hash = IP_MASQ_APP_HASH(proto, port);
+
+ save_flags(flags);
+ cli();
+ mapp->next = ip_masq_app_base[hash];
+ ip_masq_app_base[hash] = mapp;
+ restore_flags(flags);
+
+ return 0;
+}
+
+/*
+ * ip_masq_app unreg. routine.
+ */
+
+int unregister_ip_masq_app(struct ip_masq_app *mapp)
+{
+ struct ip_masq_app **mapp_p;
+ unsigned hash;
+ unsigned long flags;
+ if (!mapp) {
+ IP_MASQ_ERR("unregister_ip_masq_app(): NULL arg\n");
+ return -EINVAL;
+ }
+ /*
+ * only allow unregistration if it has no attachments
+ */
+ if (mapp->n_attach) {
+ IP_MASQ_ERR("unregister_ip_masq_app(): has %d attachments. failed\n",
+ mapp->n_attach);
+ return -EINVAL;
+ }
+ hash = IP_MASQ_APP_HASH(IP_MASQ_APP_PROTO(mapp->type), IP_MASQ_APP_PORT(mapp->type));
+
+ save_flags(flags);
+ cli();
+ for (mapp_p = &ip_masq_app_base[hash]; *mapp_p ; mapp_p = &(*mapp_p)->next)
+ if (mapp == (*mapp_p)) {
+ *mapp_p = mapp->next;
+ restore_flags(flags);
+ return 0;
+ }
+
+ restore_flags(flags);
+ IP_MASQ_ERR("unregister_ip_masq_app(proto=%s,port=%u): not hashed!\n",
+ masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)), IP_MASQ_APP_PORT(mapp->type));
+ return -EINVAL;
+}
+
+/*
+ * get ip_masq_app object by its proto and port (net byte order).
+ */
+
+struct ip_masq_app * ip_masq_app_get(unsigned short proto, __u16 port)
+{
+ struct ip_masq_app *mapp;
+ unsigned hash;
+ unsigned type;
+
+ port = ntohs(port);
+ type = IP_MASQ_APP_TYPE(proto,port);
+ hash = IP_MASQ_APP_HASH(proto,port);
+ for(mapp = ip_masq_app_base[hash]; mapp ; mapp = mapp->next) {
+ if (type == mapp->type) return mapp;
+ }
+ return NULL;
+}
+
+/*
+ * ip_masq_app object binding related funcs.
+ */
+
+/*
+ * change ip_masq_app object's number of bindings
+ */
+
+static __inline__ int ip_masq_app_bind_chg(struct ip_masq_app *mapp, int delta)
+{
+ unsigned long flags;
+ int n_at;
+ if (!mapp) return -1;
+ save_flags(flags);
+ cli();
+ n_at = mapp->n_attach + delta;
+ if (n_at < 0) {
+ restore_flags(flags);
+ IP_MASQ_ERR("ip_masq_app: tried to set n_attach < 0 for (proto=%s,port==%d) ip_masq_app object.\n",
+ masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)),
+ IP_MASQ_APP_PORT(mapp->type));
+ return -1;
+ }
+ mapp->n_attach = n_at;
+ restore_flags(flags);
+ return 0;
+}
+
+/*
+ * Bind ip_masq to its ip_masq_app based on proto and dport ALREADY
+ * set in ip_masq struct. Also calls constructor.
+ */
+
+struct ip_masq_app * ip_masq_bind_app(struct ip_masq *ms)
+{
+ struct ip_masq_app * mapp;
+
+ if (ms->protocol != IPPROTO_TCP && ms->protocol != IPPROTO_UDP)
+ return NULL;
+
+ mapp = ip_masq_app_get(ms->protocol, ms->dport);
+
+#if 0000
+/* #ifdef CONFIG_IP_MASQUERADE_IPAUTOFW */
+ if (mapp == NULL)
+ mapp = ip_masq_app_get(ms->protocol, ms->sport);
+/* #endif */
+#endif
+
+ if (mapp != NULL) {
+ /*
+ * don't allow binding if already bound
+ */
+
+ if (ms->app != NULL) {
+ IP_MASQ_ERR("ip_masq_bind_app() called for already bound object.\n");
+ return ms->app;
+ }
+
+ ms->app = mapp;
+ if (mapp->masq_init_1) mapp->masq_init_1(mapp, ms);
+ ip_masq_app_bind_chg(mapp, +1);
+ }
+ return mapp;
+}
+
+/*
+ * Unbind ms from type object and call ms destructor (does not kfree()).
+ */
+
+int ip_masq_unbind_app(struct ip_masq *ms)
+{
+ struct ip_masq_app * mapp;
+ mapp = ms->app;
+
+ if (ms->protocol != IPPROTO_TCP && ms->protocol != IPPROTO_UDP)
+ return 0;
+
+ if (mapp != NULL) {
+ if (mapp->masq_done_1) mapp->masq_done_1(mapp, ms);
+ ms->app = NULL;
+ ip_masq_app_bind_chg(mapp, -1);
+ }
+ return (mapp != NULL);
+}
+
+/*
+ * Fixes th->seq based on ip_masq_seq info.
+ */
+
+static __inline__ void masq_fix_seq(const struct ip_masq_seq *ms_seq, struct tcphdr *th)
+{
+ __u32 seq;
+
+ seq = ntohl(th->seq);
+
+ /*
+ * Adjust seq with delta-offset for all packets after
+ * the most recent resized pkt seq and with previous_delta offset
+ * for all packets before most recent resized pkt seq.
+ */
+
+ if (ms_seq->delta || ms_seq->previous_delta) {
+ if(after(seq,ms_seq->init_seq) ) {
+ th->seq = htonl(seq + ms_seq->delta);
+ IP_MASQ_DEBUG(1, "masq_fix_seq() : added delta (%d) to seq\n",ms_seq->delta);
+ } else {
+ th->seq = htonl(seq + ms_seq->previous_delta);
+ IP_MASQ_DEBUG(1, "masq_fix_seq() : added previous_delta (%d) to seq\n",ms_seq->previous_delta);
+ }
+ }
+
+
+}
+
+/*
+ * Fixes th->ack_seq based on ip_masq_seq info.
+ */
+
+static __inline__ void masq_fix_ack_seq(const struct ip_masq_seq *ms_seq, struct tcphdr *th)
+{
+ __u32 ack_seq;
+
+ ack_seq=ntohl(th->ack_seq);
+
+ /*
+ * Adjust ack_seq with delta-offset for
+ * the packets AFTER most recent resized pkt has caused a shift
+ * for packets before most recent resized pkt, use previous_delta
+ */
+
+ if (ms_seq->delta || ms_seq->previous_delta) {
+ if(after(ack_seq,ms_seq->init_seq)) {
+ th->ack_seq = htonl(ack_seq-ms_seq->delta);
+ IP_MASQ_DEBUG(1, "masq_fix_ack_seq() : subtracted delta (%d) from ack_seq\n",ms_seq->delta);
+
+ } else {
+ th->ack_seq = htonl(ack_seq-ms_seq->previous_delta);
+ IP_MASQ_DEBUG(1, "masq_fix_ack_seq() : subtracted previous_delta (%d) from ack_seq\n",ms_seq->previous_delta);
+ }
+ }
+
+}
+
+/*
+ * Updates ip_masq_seq if pkt has been resized
+ * Assumes already checked proto==IPPROTO_TCP and diff!=0.
+ */
+
+static __inline__ void masq_seq_update(struct ip_masq *ms, struct ip_masq_seq *ms_seq, unsigned mflag, __u32 seq, int diff)
+{
+ /* if (diff == 0) return; */
+
+ if ( !(ms->flags & mflag) || after(seq, ms_seq->init_seq))
+ {
+ ms_seq->previous_delta=ms_seq->delta;
+ ms_seq->delta+=diff;
+ ms_seq->init_seq=seq;
+ ms->flags |= mflag;
+ }
+}
+
+/*
+ * Output pkt hook. Will call bound ip_masq_app specific function
+ * called by ip_fw_masquerade(), assumes previously checked ms!=NULL
+ * returns (new - old) skb->len diff.
+ */
+
+int ip_masq_app_pkt_out(struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct ip_masq_app * mapp;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ int diff;
+ __u32 seq;
+
+ /*
+ * check if application masquerading is bound to
+ * this ip_masq.
+ * assumes that once an ip_masq is bound,
+ * it will not be unbound during its life.
+ */
+
+ if ( (mapp = ms->app) == NULL)
+ return 0;
+
+ iph = (*skb_p)->nh.iph;
+ th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+
+ /*
+ * Remember seq number in case this pkt gets resized
+ */
+
+ seq = ntohl(th->seq);
+
+ /*
+ * Fix seq stuff if flagged as so.
+ */
+
+ if (ms->protocol == IPPROTO_TCP) {
+ if (ms->flags & IP_MASQ_F_OUT_SEQ)
+ masq_fix_seq(&ms->out_seq, th);
+ if (ms->flags & IP_MASQ_F_IN_SEQ)
+ masq_fix_ack_seq(&ms->in_seq, th);
+ }
+
+ /*
+ * Call private output hook function
+ */
+
+ if ( mapp->pkt_out == NULL )
+ return 0;
+
+ diff = mapp->pkt_out(mapp, ms, skb_p, maddr);
+
+ /*
+ * Update ip_masq seq stuff if len has changed.
+ */
+
+ if (diff != 0 && ms->protocol == IPPROTO_TCP)
+ masq_seq_update(ms, &ms->out_seq, IP_MASQ_F_OUT_SEQ, seq, diff);
+
+ return diff;
+}
+
+/*
+ * Input pkt hook. Will call bound ip_masq_app specific function
+ * called by ip_fw_demasquerade(), assumes previously checked ms!=NULL.
+ * returns (new - old) skb->len diff.
+ */
+
+int ip_masq_app_pkt_in(struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct ip_masq_app * mapp;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ int diff;
+ __u32 seq;
+
+ /*
+ * check if application masquerading is bound to
+ * this ip_masq.
+ * assumes that once an ip_masq is bound,
+ * it will not be unbound during its life.
+ */
+
+ if ( (mapp = ms->app) == NULL)
+ return 0;
+
+ iph = (*skb_p)->nh.iph;
+ th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+
+ /*
+ * Remember seq number in case this pkt gets resized
+ */
+
+ seq = ntohl(th->seq);
+
+ /*
+ * Fix seq stuff if flagged as so.
+ */
+
+ if (ms->protocol == IPPROTO_TCP) {
+ if (ms->flags & IP_MASQ_F_IN_SEQ)
+ masq_fix_seq(&ms->in_seq, th);
+ if (ms->flags & IP_MASQ_F_OUT_SEQ)
+ masq_fix_ack_seq(&ms->out_seq, th);
+ }
+
+ /*
+ * Call private input hook function
+ */
+
+ if ( mapp->pkt_in == NULL )
+ return 0;
+
+ diff = mapp->pkt_in(mapp, ms, skb_p, maddr);
+
+ /*
+ * Update ip_masq seq stuff if len has changed.
+ */
+
+ if (diff != 0 && ms->protocol == IPPROTO_TCP)
+ masq_seq_update(ms, &ms->in_seq, IP_MASQ_F_IN_SEQ, seq, diff);
+
+ return diff;
+}
+
+/*
+ * /proc/ip_masq_app entry function
+ */
+
+int ip_masq_app_getinfo(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ off_t pos=0, begin=0;
+ int len=0;
+ struct ip_masq_app * mapp;
+ unsigned idx;
+
+ if (offset < 40)
+ len=sprintf(buffer,"%-39s\n", "prot port n_attach name");
+ pos = 40;
+
+ for (idx=0 ; idx < IP_MASQ_APP_TAB_SIZE; idx++)
+ for (mapp = ip_masq_app_base[idx]; mapp ; mapp = mapp->next) {
+ /*
+ * If you change the length of this sprintf, then all
+ * the length calculations need fixing too!
+ * Line length = 40 (3 + 2 + 7 + 1 + 7 + 1 + 2 + 17)
+ */
+ pos += 40;
+ if (pos < offset)
+ continue;
+
+ len += sprintf(buffer+len, "%-3s %-7u %-7d %-17s\n",
+ masq_proto_name(IP_MASQ_APP_PROTO(mapp->type)),
+ IP_MASQ_APP_PORT(mapp->type), mapp->n_attach,
+ mapp->name);
+
+ if(len >= length)
+ goto done;
+ }
+done:
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if (len > length)
+ len = length;
+ return len;
+}
+
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_ip_masq_app = {
+ PROC_NET_IP_MASQ_APP, 3, "app",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_masq_app_getinfo
+};
+#endif
+
+/*
+ * Initialization routine
+ */
+
+__initfunc(int ip_masq_app_init(void))
+{
+#ifdef CONFIG_PROC_FS
+ ip_masq_proc_register(&proc_net_ip_masq_app);
+#endif
+ return 0;
+}
+
+/*
+ * Replace a segment (of skb->data) with a new one.
+ * FIXME: Should re-use same skb if space available, this could
+ * be done if n_len < o_len, unless some extra space
+ * were already allocated at driver level :P .
+ */
+
+static struct sk_buff * skb_replace(struct sk_buff *skb, int pri, char *o_buf, int o_len, char *n_buf, int n_len)
+{
+ int maxsize, diff, o_offset;
+ struct sk_buff *n_skb;
+ int offset;
+
+ maxsize = skb->truesize;
+
+ diff = n_len - o_len;
+ o_offset = o_buf - (char*) skb->data;
+
+ if (maxsize <= n_len) {
+ if (diff != 0) {
+ memcpy(skb->data + o_offset + n_len,o_buf + o_len,
+ skb->len - (o_offset + o_len));
+ }
+
+ memcpy(skb->data + o_offset, n_buf, n_len);
+
+ n_skb = skb;
+ skb->len = n_len;
+ skb->end = skb->head+n_len;
+ } else {
+ /*
+ * Sizes differ, make a copy.
+ *
+ * FIXME: move this to core/sbuff.c:skb_grow()
+ */
+
+ n_skb = alloc_skb(MAX_HEADER + skb->len + diff, pri);
+ if (n_skb == NULL) {
+ IP_MASQ_ERR("skb_replace(): no room left (from %p)\n",
+ __builtin_return_address(0));
+ return skb;
+
+ }
+ skb_reserve(n_skb, MAX_HEADER);
+ skb_put(n_skb, skb->len + diff);
+
+ /*
+ * Copy as much data from the old skb as possible. Even
+ * though we're only forwarding packets, we need stuff
+ * like skb->protocol (PPP driver wants it).
+ */
+ offset = n_skb->data - skb->data;
+ n_skb->nh.raw = skb->nh.raw + offset;
+ n_skb->h.raw = skb->h.raw + offset;
+ n_skb->dev = skb->dev;
+ n_skb->mac.raw = skb->mac.raw + offset;
+ n_skb->pkt_type = skb->pkt_type;
+ n_skb->protocol = skb->protocol;
+ n_skb->ip_summed = skb->ip_summed;
+ n_skb->dst = dst_clone(skb->dst);
+
+ /*
+ * Copy pkt in new buffer
+ */
+
+ memcpy(n_skb->data, skb->data, o_offset);
+ memcpy(n_skb->data + o_offset, n_buf, n_len);
+ memcpy(n_skb->data + o_offset + n_len, o_buf + o_len,
+ skb->len - (o_offset + o_len) );
+
+ /*
+ * Problem, how to replace the new skb with old one,
+ * preferably inplace
+ */
+
+ kfree_skb(skb);
+ }
+ return n_skb;
+}
+
+/*
+ * calls skb_replace() and update ip header if new skb was allocated
+ */
+
+struct sk_buff * ip_masq_skb_replace(struct sk_buff *skb, int pri, char *o_buf, int o_len, char *n_buf, int n_len)
+{
+ int diff;
+ struct sk_buff *n_skb;
+ unsigned skb_len;
+
+ diff = n_len - o_len;
+ n_skb = skb_replace(skb, pri, o_buf, o_len, n_buf, n_len);
+ skb_len = skb->len;
+
+ if (diff)
+ {
+ struct iphdr *iph;
+ IP_MASQ_DEBUG(1, "masq_skb_replace(): pkt resized for %d bytes (len=%d)\n", diff, skb->len);
+ /*
+ * update ip header
+ */
+ iph = n_skb->nh.iph;
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ iph->tot_len = htons(skb_len + diff);
+ }
+ return n_skb;
+}
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_autofw.c b/pfinet/linux-src/net/ipv4/ip_masq_autofw.c
new file mode 100644
index 00000000..d2a1729c
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_autofw.c
@@ -0,0 +1,448 @@
+/*
+ * IP_MASQ_AUTOFW auto forwarding module
+ *
+ *
+ * $Id: ip_masq_autofw.c,v 1.3 1998/08/29 23:51:10 davem Exp $
+ *
+ * Author: Richard Lynch
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ *
+ * Fixes:
+ * Juan Jose Ciarlante : created this new file from ip_masq.c and ip_fw.c
+ * Juan Jose Ciarlante : modularized
+ * Juan Jose Ciarlante : use GFP_KERNEL when creating entries
+ * Juan Jose Ciarlante : call del_timer() when freeing entries (!)
+ * FIXME:
+ * - implement refcnt
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <asm/system.h>
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#include <linux/if.h>
+#include <linux/init.h>
+#include <linux/ip_fw.h>
+#include <net/ip_masq.h>
+#include <net/ip_masq_mod.h>
+#include <linux/ip_masq.h>
+
+#define IP_AUTOFW_EXPIRE 15*HZ
+
+/* WARNING: bitwise equal to ip_autofw_user in linux/ip_masq.h */
+struct ip_autofw {
+ struct ip_autofw * next;
+ __u16 type;
+ __u16 low;
+ __u16 hidden;
+ __u16 high;
+ __u16 visible;
+ __u16 protocol;
+ __u32 lastcontact;
+ __u32 where;
+ __u16 ctlproto;
+ __u16 ctlport;
+ __u16 flags;
+ struct timer_list timer;
+};
+
+/*
+ * Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
+
+/*
+ * Auto-forwarding table
+ */
+
+static struct ip_autofw * ip_autofw_hosts = NULL;
+static struct ip_masq_mod * mmod_self = NULL;
+
+/*
+ * Check if a masq entry should be created for a packet
+ */
+
+static __inline__ struct ip_autofw * ip_autofw_check_range (__u32 where, __u16 port, __u16 protocol, int reqact)
+{
+ struct ip_autofw *af;
+ af=ip_autofw_hosts;
+ port=ntohs(port);
+ while (af) {
+ if (af->type==IP_FWD_RANGE &&
+ port>=af->low &&
+ port<=af->high &&
+ protocol==af->protocol &&
+
+ /*
+ * It's ok to create masq entries after
+ * the timeout if we're in insecure mode
+ */
+ (af->flags & IP_AUTOFW_ACTIVE || !reqact || !(af->flags & IP_AUTOFW_SECURE)) &&
+ (!(af->flags & IP_AUTOFW_SECURE) || af->lastcontact==where || !reqact))
+ return(af);
+ af=af->next;
+ }
+ return(NULL);
+}
+
+static __inline__ struct ip_autofw * ip_autofw_check_port (__u16 port, __u16 protocol)
+{
+ struct ip_autofw *af;
+ af=ip_autofw_hosts;
+ port=ntohs(port);
+ while (af)
+ {
+ if (af->type==IP_FWD_PORT && port==af->visible && protocol==af->protocol)
+ return(af);
+ af=af->next;
+ }
+ return(NULL);
+}
+
+static __inline__ struct ip_autofw * ip_autofw_check_direct (__u16 port, __u16 protocol)
+{
+ struct ip_autofw *af;
+ af=ip_autofw_hosts;
+ port=ntohs(port);
+ while (af)
+ {
+ if (af->type==IP_FWD_DIRECT && af->low<=port && af->high>=port)
+ return(af);
+ af=af->next;
+ }
+ return(NULL);
+}
+
+static __inline__ void ip_autofw_update_out (__u32 who, __u32 where, __u16 port, __u16 protocol)
+{
+ struct ip_autofw *af;
+ af=ip_autofw_hosts;
+ port=ntohs(port);
+ while (af)
+ {
+ if (af->type==IP_FWD_RANGE && af->ctlport==port && af->ctlproto==protocol)
+ {
+ if (af->flags & IP_AUTOFW_USETIME)
+ {
+ mod_timer(&af->timer,
+ jiffies+IP_AUTOFW_EXPIRE);
+ }
+ af->flags|=IP_AUTOFW_ACTIVE;
+ af->lastcontact=where;
+ af->where=who;
+ }
+ af=af->next;
+ }
+}
+
+#if 0
+static __inline__ void ip_autofw_update_in (__u32 where, __u16 port, __u16 protocol)
+{
+ struct ip_autofw *af;
+ af=ip_autofw_check_range(where, port,protocol);
+ if (af)
+ {
+ mod_timer(&af->timer, jiffies+IP_AUTOFW_EXPIRE);
+ }
+}
+#endif
+
+
+static __inline__ void ip_autofw_expire(unsigned long data)
+{
+ struct ip_autofw * af;
+ af=(struct ip_autofw *) data;
+ af->flags &= ~IP_AUTOFW_ACTIVE;
+ af->timer.expires=0;
+ af->lastcontact=0;
+ if (af->flags & IP_AUTOFW_SECURE)
+ af->where=0;
+}
+
+
+
+static __inline__ int ip_autofw_add(struct ip_autofw_user * af)
+{
+ struct ip_autofw * newaf;
+ newaf = kmalloc( sizeof(struct ip_autofw), GFP_KERNEL );
+ init_timer(&newaf->timer);
+ if ( newaf == NULL )
+ {
+ printk("ip_autofw_add: malloc said no\n");
+ return( ENOMEM );
+ }
+
+ MOD_INC_USE_COUNT;
+
+ memcpy(newaf, af, sizeof(struct ip_autofw_user));
+ newaf->timer.data = (unsigned long) newaf;
+ newaf->timer.function = ip_autofw_expire;
+ newaf->timer.expires = 0;
+ newaf->lastcontact=0;
+ newaf->next=ip_autofw_hosts;
+ ip_autofw_hosts=newaf;
+ ip_masq_mod_inc_nent(mmod_self);
+ return(0);
+}
+
+static __inline__ int ip_autofw_del(struct ip_autofw_user * af)
+{
+ struct ip_autofw ** af_p, *curr;
+
+ for (af_p=&ip_autofw_hosts, curr=*af_p; (curr=*af_p); af_p = &(*af_p)->next) {
+ if (af->type == curr->type &&
+ af->low == curr->low &&
+ af->high == curr->high &&
+ af->hidden == curr->hidden &&
+ af->visible == curr->visible &&
+ af->protocol == curr->protocol &&
+ af->where == curr->where &&
+ af->ctlproto == curr->ctlproto &&
+ af->ctlport == curr->ctlport)
+ {
+ ip_masq_mod_dec_nent(mmod_self);
+ *af_p = curr->next;
+ if (af->flags&IP_AUTOFW_ACTIVE)
+ del_timer(&curr->timer);
+ kfree_s(curr,sizeof(struct ip_autofw));
+ MOD_DEC_USE_COUNT;
+ return 0;
+ }
+ curr=curr->next;
+ }
+ return EINVAL;
+}
+
+static __inline__ int ip_autofw_flush(void)
+{
+ struct ip_autofw * af;
+
+ while (ip_autofw_hosts)
+ {
+ af=ip_autofw_hosts;
+ ip_masq_mod_dec_nent(mmod_self);
+ ip_autofw_hosts=ip_autofw_hosts->next;
+ if (af->flags&IP_AUTOFW_ACTIVE)
+ del_timer(&af->timer);
+ kfree_s(af,sizeof(struct ip_autofw));
+ MOD_DEC_USE_COUNT;
+ }
+ return(0);
+}
+
+/*
+ * Methods for registered object
+ */
+
+static int autofw_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
+{
+ struct ip_autofw_user *af = &mctl->u.autofw_user;
+
+ switch (mctl->m_cmd) {
+ case IP_MASQ_CMD_ADD:
+ case IP_MASQ_CMD_INSERT:
+ if (optlen<sizeof(*af))
+ return EINVAL;
+ return ip_autofw_add(af);
+ case IP_MASQ_CMD_DEL:
+ if (optlen<sizeof(*af))
+ return EINVAL;
+ return ip_autofw_del(af);
+ case IP_MASQ_CMD_FLUSH:
+ return ip_autofw_flush();
+
+ }
+ return EINVAL;
+}
+
+
+static int autofw_out_update(const struct sk_buff *skb, const struct iphdr *iph, struct ip_masq *ms)
+{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+ /*
+ * Update any ipautofw entries ...
+ */
+
+ ip_autofw_update_out(iph->saddr, iph->daddr, portp[1], iph->protocol);
+ return IP_MASQ_MOD_NOP;
+}
+
+static struct ip_masq * autofw_out_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
+{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+ /*
+ * If the source port is supposed to match the masq port, then
+ * make it so
+ */
+
+ if (ip_autofw_check_direct(portp[1],iph->protocol)) {
+ return ip_masq_new(iph->protocol,
+ maddr, portp[0],
+ iph->saddr, portp[0],
+ iph->daddr, portp[1],
+ 0);
+ }
+ return NULL;
+}
+
+#if 0
+static int autofw_in_update(const struct sk_buff *skb, const struct iphdr *iph, __u16 *portp, struct ip_masq *ms)
+{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+ ip_autofw_update_in(iph->saddr, portp[1], iph->protocol);
+ return IP_MASQ_MOD_NOP;
+}
+#endif
+
+static int autofw_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
+{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+ return (ip_autofw_check_range(iph->saddr, portp[1], iph->protocol, 0)
+ || ip_autofw_check_direct(portp[1], iph->protocol)
+ || ip_autofw_check_port(portp[1], iph->protocol));
+}
+
+static struct ip_masq * autofw_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
+{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+ struct ip_autofw *af;
+
+ if ((af=ip_autofw_check_range(iph->saddr, portp[1], iph->protocol, 0))) {
+ IP_MASQ_DEBUG(1-debug, "autofw_check_range HIT\n");
+ return ip_masq_new(iph->protocol,
+ maddr, portp[1],
+ af->where, portp[1],
+ iph->saddr, portp[0],
+ 0);
+ }
+ if ((af=ip_autofw_check_port(portp[1], iph->protocol)) ) {
+ IP_MASQ_DEBUG(1-debug, "autofw_check_port HIT\n");
+ return ip_masq_new(iph->protocol,
+ maddr, htons(af->visible),
+ af->where, htons(af->hidden),
+ iph->saddr, portp[0],
+ 0);
+ }
+ return NULL;
+}
+
+#ifdef CONFIG_PROC_FS
+static int autofw_procinfo(char *buffer, char **start, off_t offset,
+ int length, int unused)
+{
+ off_t pos=0, begin=0;
+ struct ip_autofw * af;
+ int len=0;
+
+ len=sprintf(buffer,"Type Prot Low High Vis Hid Where Last CPto CPrt Timer Flags\n");
+
+ for(af = ip_autofw_hosts; af ; af = af->next)
+ {
+ len+=sprintf(buffer+len,"%4X %4X %04X-%04X/%04X %04X %08lX %08lX %04X %04X %6lu %4X\n",
+ af->type,
+ af->protocol,
+ af->low,
+ af->high,
+ af->visible,
+ af->hidden,
+ ntohl(af->where),
+ ntohl(af->lastcontact),
+ af->ctlproto,
+ af->ctlport,
+ (af->timer.expires<jiffies ? 0 : af->timer.expires-jiffies),
+ af->flags);
+
+ pos=begin+len;
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ break;
+ }
+ *start=buffer+(offset-begin);
+ len-=(offset-begin);
+ if(len>length)
+ len=length;
+ return len;
+}
+
+static struct proc_dir_entry autofw_proc_entry = {
+ 0, 0, NULL,
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ autofw_procinfo
+};
+
+#define proc_ent &autofw_proc_entry
+#else /* !CONFIG_PROC_FS */
+
+#define proc_ent NULL
+#endif
+
+
+#define autofw_in_update NULL
+#define autofw_out_rule NULL
+#define autofw_mod_init NULL
+#define autofw_mod_done NULL
+
+static struct ip_masq_mod autofw_mod = {
+ NULL, /* next */
+ NULL, /* next_reg */
+ "autofw", /* name */
+ ATOMIC_INIT(0), /* nent */
+ ATOMIC_INIT(0), /* refcnt */
+ proc_ent,
+ autofw_ctl,
+ autofw_mod_init,
+ autofw_mod_done,
+ autofw_in_rule,
+ autofw_in_update,
+ autofw_in_create,
+ autofw_out_rule,
+ autofw_out_update,
+ autofw_out_create,
+};
+
+__initfunc(int ip_autofw_init(void))
+{
+ return register_ip_masq_mod ((mmod_self=&autofw_mod));
+}
+
+int ip_autofw_done(void)
+{
+ return unregister_ip_masq_mod(&autofw_mod);
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_autofw_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_autofw_done() != 0)
+ printk(KERN_INFO "ip_autofw_done(): can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_cuseeme.c b/pfinet/linux-src/net/ipv4/ip_masq_cuseeme.c
new file mode 100644
index 00000000..9b412baf
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_cuseeme.c
@@ -0,0 +1,264 @@
+/*
+ * IP_MASQ_FTP CUSeeMe masquerading module
+ *
+ *
+ * Version: @(#)$Id: ip_masq_cuseeme.c,v 1.4 1998/10/06 04:48:57 davem Exp $
+ *
+ * Author: Richard Lynch
+ *
+ *
+ * Fixes:
+ * Richard Lynch : Updated patch to conform to new module
+ * specifications
+ * Nigel Metheringham : Multiple port support
+ * Michael Owings : Fixed broken init code
+ * Added code to update inbound
+ * packets with correct local addresses.
+ * Fixes audio and "chat" problems
+ * Thanx to the CU-SeeMe Consortium for
+ * technical docs
+ * Steven Clarke : Small changes for 2.1
+ *
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Multiple Port Support
+ * The helper can be made to handle up to MAX_MASQ_APP_PORTS (normally 12)
+ * with the port numbers being defined at module load time. The module
+ * uses the symbol "ports" to define a list of monitored ports, which can
+ * be specified on the insmod command line as
+ * ports=x1,x2,x3...
+ * where x[n] are integer port numbers. This option can be put into
+ * /etc/conf.modules (or /etc/modules.conf depending on your config)
+ * where modload will pick it up should you use modload to load your
+ * modules.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/udp.h>
+
+/* #define IP_MASQ_NDEBUG */
+#include <net/ip_masq.h>
+
+#pragma pack(1)
+/* CU-SeeMe Data Header */
+typedef struct {
+ u_short dest_family;
+ u_short dest_port;
+ u_long dest_addr;
+ short family;
+ u_short port;
+ u_long addr;
+ u_long seq;
+ u_short msg;
+ u_short data_type;
+ u_short packet_len;
+} cu_header;
+
+/* Open Continue Header */
+typedef struct {
+ cu_header cu_head;
+ u_short client_count; /* Number of client info structs */
+ u_long seq_no;
+ char user_name[20];
+ char stuff[4]; /* flags, version stuff, etc */
+}oc_header;
+
+/* client info structures */
+typedef struct {
+ u_long address; /* Client address */
+ char stuff[8]; /* Flags, pruning bitfield, packet counts etc */
+} client_info;
+#pragma pack()
+
+/*
+ * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper
+ * First port is set to the default port.
+ */
+static int ports[MAX_MASQ_APP_PORTS] = {7648}; /* I rely on the trailing items being set to zero */
+struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
+
+/*
+ * Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
+
+static int
+masq_cuseeme_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+masq_cuseeme_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+int
+masq_cuseeme_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb = *skb_p;
+ struct iphdr *iph = skb->nh.iph;
+ struct udphdr *uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
+ cu_header *cu_head;
+ char *data=(char *)&uh[1];
+
+ if (skb->len - ((unsigned char *) data - skb->h.raw) >= sizeof(cu_header))
+ {
+ cu_head = (cu_header *) data;
+ /* cu_head->port = ms->mport; */
+ if( cu_head->addr )
+ cu_head->addr = (u_long) maddr;
+ if(ntohs(cu_head->data_type) == 257)
+ IP_MASQ_DEBUG(1-debug, "Sending talk packet!\n");
+ }
+ return 0;
+}
+
+int
+masq_cuseeme_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb = *skb_p;
+ struct iphdr *iph = skb->nh.iph;
+ struct udphdr *uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
+ cu_header *cu_head;
+ oc_header *oc;
+ client_info *ci;
+ char *data=(char *)&uh[1];
+ u_short len = skb->len - ((unsigned char *) data - skb->h.raw);
+ int i, off;
+
+ if (len >= sizeof(cu_header))
+ {
+ cu_head = (cu_header *) data;
+ if(cu_head->dest_addr) /* Correct destination address */
+ cu_head->dest_addr = (u_long) ms->saddr;
+ if(ntohs(cu_head->data_type)==101 && len > sizeof(oc_header))
+ {
+ oc = (oc_header * ) data;
+ /* Spin (grovel) thru client_info structs till we find our own */
+ off=sizeof(oc_header);
+ for(i=0;
+ (i < oc->client_count && off+sizeof(client_info) <= len);
+ i++)
+ {
+ ci=(client_info *)(data+off);
+ if(ci->address==(u_long) maddr)
+ {
+ /* Update w/ our real ip address and exit */
+ ci->address = (u_long) ms->saddr;
+ break;
+ }
+ else
+ off+=sizeof(client_info);
+ }
+ }
+ }
+ return 0;
+}
+
+struct ip_masq_app ip_masq_cuseeme = {
+ NULL, /* next */
+ "cuseeme",
+ 0, /* type */
+ 0, /* n_attach */
+ masq_cuseeme_init_1, /* ip_masq_init_1 */
+ masq_cuseeme_done_1, /* ip_masq_done_1 */
+ masq_cuseeme_out, /* pkt_out */
+ masq_cuseeme_in /* pkt_in */
+};
+
+
+/*
+ * ip_masq_cuseeme initialization
+ */
+
+__initfunc(int ip_masq_cuseeme_init(void))
+{
+ int i, j;
+
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (ports[i]) {
+ if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
+ GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ memcpy(masq_incarnations[i], &ip_masq_cuseeme, sizeof(struct ip_masq_app));
+ if ((j = register_ip_masq_app(masq_incarnations[i],
+ IPPROTO_UDP,
+ ports[i]))) {
+ return j;
+ }
+#if DEBUG_CONFIG_IP_MASQ_CUSEEME
+ IP_MASQ_DEBUG(1-debug, "CuSeeMe: loaded support on port[%d] = %d\n",
+ i, ports[i]);
+#endif
+ } else {
+ /* To be safe, force the incarnation table entry to NULL */
+ masq_incarnations[i] = NULL;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ip_masq_cuseeme fin.
+ */
+
+int ip_masq_cuseeme_done(void)
+{
+ int i, j, k;
+
+ k=0;
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (masq_incarnations[i]) {
+ if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
+ k = j;
+ } else {
+ kfree(masq_incarnations[i]);
+ masq_incarnations[i] = NULL;
+ IP_MASQ_DEBUG(1-debug, "CuSeeMe: unloaded support on port[%d] = %d\n", i, ports[i]);
+ }
+ }
+ }
+ return k;
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_masq_cuseeme_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_masq_cuseeme_done() != 0)
+ IP_MASQ_DEBUG(1-debug, "ip_masq_cuseeme: can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_ftp.c b/pfinet/linux-src/net/ipv4/ip_masq_ftp.c
new file mode 100644
index 00000000..35d1f544
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_ftp.c
@@ -0,0 +1,393 @@
+/*
+ * IP_MASQ_FTP ftp masquerading module
+ *
+ *
+ * Version: @(#)ip_masq_ftp.c 0.04 02/05/96
+ *
+ * Author: Wouter Gadeyne
+ *
+ *
+ * Fixes:
+ * Wouter Gadeyne : Fixed masquerading support of ftp PORT commands
+ * Juan Jose Ciarlante : Code moved and adapted from ip_fw.c
+ * Keith Owens : Add keep alive for ftp control channel
+ * Nigel Metheringham : Added multiple port support
+ * Juan Jose Ciarlante : Use control_add() for ftp control chan
+ * Juan Jose Ciarlante : Litl bits for 2.1
+ * Juan Jose Ciarlante : use ip_masq_listen()
+ * Juan Jose Ciarlante : use private app_data for own flag(s)
+ *
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Multiple Port Support
+ * The helper can be made to handle up to MAX_MASQ_APP_PORTS (normally 12)
+ * with the port numbers being defined at module load time. The module
+ * uses the symbol "ports" to define a list of monitored ports, which can
+ * be specified on the insmod command line as
+ * ports=x1,x2,x3...
+ * where x[n] are integer port numbers. This option can be put into
+ * /etc/conf.modules (or /etc/modules.conf depending on your config)
+ * where modload will pick it up should you use modload to load your
+ * modules.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+
+/* #define IP_MASQ_NDEBUG */
+#include <net/ip_masq.h>
+
+
+/*
+ * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper
+ * First port is set to the default port.
+ */
+static int ports[MAX_MASQ_APP_PORTS] = {21}; /* I rely on the trailing items being set to zero */
+struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
+
+/*
+ * Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
+
+/* Dummy variable */
+static int masq_ftp_pasv;
+
+static int
+masq_ftp_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+masq_ftp_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+int
+masq_ftp_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ char *p, *data, *data_limit;
+ unsigned char p1,p2,p3,p4,p5,p6;
+ __u32 from;
+ __u16 port;
+ struct ip_masq *n_ms;
+ char buf[24]; /* xxx.xxx.xxx.xxx,ppp,ppp\000 */
+ unsigned buf_len;
+ int diff;
+
+ skb = *skb_p;
+ iph = skb->nh.iph;
+ th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+ data = (char *)&th[1];
+
+ data_limit = skb->h.raw + skb->len - 18;
+ if (skb->len >= 6 && (memcmp(data, "PASV\r\n", 6) == 0 || memcmp(data, "pasv\r\n", 6) == 0))
+ ms->app_data = &masq_ftp_pasv;
+
+ while (data < data_limit)
+ {
+ if (memcmp(data,"PORT ",5) && memcmp(data,"port ",5))
+ {
+ data ++;
+ continue;
+ }
+ p = data+5;
+ p1 = simple_strtoul(data+5,&data,10);
+ if (*data!=',')
+ continue;
+ p2 = simple_strtoul(data+1,&data,10);
+ if (*data!=',')
+ continue;
+ p3 = simple_strtoul(data+1,&data,10);
+ if (*data!=',')
+ continue;
+ p4 = simple_strtoul(data+1,&data,10);
+ if (*data!=',')
+ continue;
+ p5 = simple_strtoul(data+1,&data,10);
+ if (*data!=',')
+ continue;
+ p6 = simple_strtoul(data+1,&data,10);
+ if (*data!='\r' && *data!='\n')
+ continue;
+
+ from = (p1<<24) | (p2<<16) | (p3<<8) | p4;
+ port = (p5<<8) | p6;
+
+ IP_MASQ_DEBUG(1-debug, "PORT %X:%X detected\n",from,port);
+
+ /*
+ * Now update or create an masquerade entry for it
+ */
+
+ IP_MASQ_DEBUG(1-debug, "protocol %d %lX:%X %X:%X\n", iph->protocol, htonl(from), htons(port), iph->daddr, 0);
+
+ n_ms = ip_masq_out_get(iph->protocol,
+ htonl(from), htons(port),
+ iph->daddr, 0);
+ if (!n_ms) {
+ n_ms = ip_masq_new(IPPROTO_TCP,
+ maddr, 0,
+ htonl(from), htons(port),
+ iph->daddr, 0,
+ IP_MASQ_F_NO_DPORT);
+
+ if (n_ms==NULL)
+ return 0;
+ ip_masq_control_add(n_ms, ms);
+ }
+
+ /*
+ * Replace the old PORT with the new one
+ */
+ from = ntohl(n_ms->maddr);
+ port = ntohs(n_ms->mport);
+ sprintf(buf,"%d,%d,%d,%d,%d,%d",
+ from>>24&255,from>>16&255,from>>8&255,from&255,
+ port>>8&255,port&255);
+ buf_len = strlen(buf);
+
+ IP_MASQ_DEBUG(1-debug, "new PORT %X:%X\n",from,port);
+
+ /*
+ * Calculate required delta-offset to keep TCP happy
+ */
+
+ diff = buf_len - (data-p);
+
+ /*
+ * No shift.
+ */
+
+ if (diff==0) {
+ /*
+ * simple case, just replace the old PORT cmd
+ */
+ memcpy(p,buf,buf_len);
+ } else {
+
+ *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC, p, data-p, buf, buf_len);
+ }
+ /*
+ * Move tunnel to listen state
+ */
+ ip_masq_listen(n_ms);
+ ip_masq_put(n_ms);
+
+ return diff;
+
+ }
+ return 0;
+
+}
+
+/*
+ * Look at incoming ftp packets to catch the response to a PASV command. When
+ * we see one we build a masquerading entry for the client address, client port
+ * 0 (unknown at the moment), the server address and the server port. Mark the
+ * current masquerade entry as a control channel and point the new entry at the
+ * control entry. All this work just for ftp keepalive across masquerading.
+ *
+ * The incoming packet should be something like
+ * "227 Entering Passive Mode (xxx,xxx,xxx,xxx,ppp,ppp)".
+ * xxx,xxx,xxx,xxx is the server address, ppp,ppp is the server port number.
+ * ncftp 2.3.0 cheats by skipping the leading number then going 22 bytes into
+ * the data so we do the same. If it's good enough for ncftp then it's good
+ * enough for me.
+ *
+ * In this case, the client is the source machine being masqueraded, the server
+ * is the destination for ftp requests. It all depends on your point of view ...
+ */
+
+int
+masq_ftp_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ char *data, *data_limit;
+ unsigned char p1,p2,p3,p4,p5,p6;
+ __u32 to;
+ __u16 port;
+ struct ip_masq *n_ms;
+
+ if (ms->app_data != &masq_ftp_pasv)
+ return 0; /* quick exit if no outstanding PASV */
+
+ skb = *skb_p;
+ iph = skb->nh.iph;
+ th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+ data = (char *)&th[1];
+ data_limit = skb->h.raw + skb->len;
+
+ while (data < data_limit && *data != ' ')
+ ++data;
+ while (data < data_limit && *data == ' ')
+ ++data;
+ data += 22;
+ if (data >= data_limit || *data != '(')
+ return 0;
+ p1 = simple_strtoul(data+1, &data, 10);
+ if (data >= data_limit || *data != ',')
+ return 0;
+ p2 = simple_strtoul(data+1, &data, 10);
+ if (data >= data_limit || *data != ',')
+ return 0;
+ p3 = simple_strtoul(data+1, &data, 10);
+ if (data >= data_limit || *data != ',')
+ return 0;
+ p4 = simple_strtoul(data+1, &data, 10);
+ if (data >= data_limit || *data != ',')
+ return 0;
+ p5 = simple_strtoul(data+1, &data, 10);
+ if (data >= data_limit || *data != ',')
+ return 0;
+ p6 = simple_strtoul(data+1, &data, 10);
+ if (data >= data_limit || *data != ')')
+ return 0;
+
+ to = (p1<<24) | (p2<<16) | (p3<<8) | p4;
+ port = (p5<<8) | p6;
+
+ /*
+ * Now update or create an masquerade entry for it
+ */
+ IP_MASQ_DEBUG(1-debug, "PASV response %lX:%X %X:%X detected\n", ntohl(ms->saddr), 0, to, port);
+
+ n_ms = ip_masq_out_get(iph->protocol,
+ ms->saddr, 0,
+ htonl(to), htons(port));
+ if (!n_ms) {
+ n_ms = ip_masq_new(IPPROTO_TCP,
+ maddr, 0,
+ ms->saddr, 0,
+ htonl(to), htons(port),
+ IP_MASQ_F_NO_SPORT);
+
+ if (n_ms==NULL)
+ return 0;
+ ip_masq_control_add(n_ms, ms);
+ }
+
+#if 0 /* v0.12 state processing */
+
+ /*
+ * keep for a bit longer than tcp_fin, client may not issue open
+ * to server port before tcp_fin_timeout.
+ */
+ n_ms->timeout = ip_masq_expire->tcp_fin_timeout*3;
+#endif
+ ms->app_data = NULL;
+ ip_masq_put(n_ms);
+
+ return 0; /* no diff required for incoming packets, thank goodness */
+}
+
+struct ip_masq_app ip_masq_ftp = {
+ NULL, /* next */
+ "ftp", /* name */
+ 0, /* type */
+ 0, /* n_attach */
+ masq_ftp_init_1, /* ip_masq_init_1 */
+ masq_ftp_done_1, /* ip_masq_done_1 */
+ masq_ftp_out, /* pkt_out */
+ masq_ftp_in, /* pkt_in */
+};
+
+/*
+ * ip_masq_ftp initialization
+ */
+
+__initfunc(int ip_masq_ftp_init(void))
+{
+ int i, j;
+
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (ports[i]) {
+ if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
+ GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ memcpy(masq_incarnations[i], &ip_masq_ftp, sizeof(struct ip_masq_app));
+ if ((j = register_ip_masq_app(masq_incarnations[i],
+ IPPROTO_TCP,
+ ports[i]))) {
+ return j;
+ }
+ IP_MASQ_DEBUG(1-debug, "Ftp: loaded support on port[%d] = %d\n",
+ i, ports[i]);
+ } else {
+ /* To be safe, force the incarnation table entry to NULL */
+ masq_incarnations[i] = NULL;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ip_masq_ftp fin.
+ */
+
+int ip_masq_ftp_done(void)
+{
+ int i, j, k;
+
+ k=0;
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (masq_incarnations[i]) {
+ if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
+ k = j;
+ } else {
+ kfree(masq_incarnations[i]);
+ masq_incarnations[i] = NULL;
+ IP_MASQ_DEBUG(1-debug, "Ftp: unloaded support on port[%d] = %d\n",
+ i, ports[i]);
+ }
+ }
+ }
+ return k;
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_masq_ftp_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_masq_ftp_done() != 0)
+ printk(KERN_INFO "ip_masq_ftp: can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_irc.c b/pfinet/linux-src/net/ipv4/ip_masq_irc.c
new file mode 100644
index 00000000..e52a5720
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_irc.c
@@ -0,0 +1,345 @@
+/*
+ * IP_MASQ_IRC irc masquerading module
+ *
+ *
+ * Version: @(#)ip_masq_irc.c 0.04 99/06/19
+ *
+ * Author: Juan Jose Ciarlante
+ *
+ * Additions:
+ * - recognize a few non-irc-II DCC requests (Oliver Wagner)
+ * DCC MOVE (AmIRC/DCC.MOVE; SEND with resuming)
+ * DCC SCHAT (AmIRC IDEA encrypted CHAT)
+ * DCC TSEND (AmIRC/PIRCH SEND without ACKs)
+ * Fixes:
+ * Juan Jose Ciarlante : set NO_DADDR flag in ip_masq_new()
+ * Nigel Metheringham : Added multiple port support
+ * Juan Jose Ciarlante : litl bits for 2.1
+ * Oliver Wagner : more IRC cmds processing
+ * <winmute@lucifer.gv.kotnet.org>
+ * Juan Jose Ciarlante : put new ms entry to listen()
+ * Scottie Shore : added support for clients that add extra args
+ * <sshore@escape.ca>
+ *
+ * FIXME:
+ * - detect also previous "PRIVMSG" string ?.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Multiple Port Support
+ * The helper can be made to handle up to MAX_MASQ_APP_PORTS (normally 12)
+ * with the port numbers being defined at module load time. The module
+ * uses the symbol "ports" to define a list of monitored ports, which can
+ * be specified on the insmod command line as
+ * ports=x1,x2,x3...
+ * where x[n] are integer port numbers. This option can be put into
+ * /etc/conf.modules (or /etc/modules.conf depending on your config)
+ * where modload will pick it up should you use modload to load your
+ * modules.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/ip_masq.h>
+
+
+/*
+ * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper
+ * First port is set to the default port.
+ */
+int ports[MAX_MASQ_APP_PORTS] = {6667}; /* I rely on the trailing items being set to zero */
+struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
+/*
+ * Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
+
+
+/*
+ * List of supported DCC protocols
+ */
+
+#define NUM_DCCPROTO 5
+
+struct dccproto
+{
+ char *match;
+ int matchlen;
+};
+
+struct dccproto dccprotos[NUM_DCCPROTO] = {
+ { "SEND ", 5 },
+ { "CHAT ", 5 },
+ { "MOVE ", 5 },
+ { "TSEND ", 6 },
+ { "SCHAT ", 6 }
+};
+#define MAXMATCHLEN 6
+
+static int
+masq_irc_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+masq_irc_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+int
+masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ char *data, *data_limit;
+ __u32 s_addr;
+ __u16 s_port;
+ struct ip_masq *n_ms;
+ char buf[20]; /* "m_addr m_port" (dec base)*/
+ unsigned buf_len;
+ int diff;
+ char *dcc_p, *addr_beg_p, *addr_end_p;
+
+ skb = *skb_p;
+ iph = skb->nh.iph;
+ th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+ data = (char *)&th[1];
+
+ /*
+ * Hunt irc DCC string, the _shortest_:
+ *
+ * strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
+ * strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
+ * strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
+ * strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
+ * strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
+ * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits)
+ * P: bound port (min 1 d )
+ * F: filename (min 1 d )
+ * S: size (min 1 d )
+ * 0x01, \n: terminators
+ */
+
+ data_limit = skb->h.raw + skb->len;
+
+ while (data < (data_limit - ( 22 + MAXMATCHLEN ) ) )
+ {
+ int i;
+ if (memcmp(data,"\1DCC ",5)) {
+ data ++;
+ continue;
+ }
+
+ dcc_p = data;
+ data += 5; /* point to DCC cmd */
+
+ for(i=0; i<NUM_DCCPROTO; i++)
+ {
+ /*
+ * go through the table and hunt a match string
+ */
+
+ if( memcmp(data, dccprotos[i].match, dccprotos[i].matchlen ) == 0 )
+ {
+ data += dccprotos[i].matchlen;
+
+ /*
+ * skip next string.
+ */
+
+ while( *data++ != ' ')
+
+ /*
+ * must still parse, at least, "AAAAAAAA P\1\n",
+ * 12 bytes left.
+ */
+ if (data > (data_limit-12)) return 0;
+
+
+ addr_beg_p = data;
+
+ /*
+ * client bound address in dec base
+ */
+
+ s_addr = simple_strtoul(data,&data,10);
+ if (*data++ !=' ')
+ continue;
+
+ /*
+ * client bound port in dec base
+ */
+
+ s_port = simple_strtoul(data,&data,10);
+ addr_end_p = data;
+
+ /*
+ * Now create an masquerade entry for it
+ * must set NO_DPORT and NO_DADDR because
+ * connection is requested by another client.
+ */
+
+ n_ms = ip_masq_new(IPPROTO_TCP,
+ maddr, 0,
+ htonl(s_addr),htons(s_port),
+ 0, 0,
+ IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR);
+ if (n_ms==NULL)
+ return 0;
+
+ /*
+ * Replace the old "address port" with the new one
+ */
+
+ buf_len = sprintf(buf,"%lu %u",
+ ntohl(n_ms->maddr),ntohs(n_ms->mport));
+
+ /*
+ * Calculate required delta-offset to keep TCP happy
+ */
+
+ diff = buf_len - (addr_end_p-addr_beg_p);
+
+ *addr_beg_p = '\0';
+ IP_MASQ_DEBUG(1-debug, "masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff);
+
+ /*
+ * No shift.
+ */
+
+ if (diff==0) {
+ /*
+ * simple case, just copy.
+ */
+ memcpy(addr_beg_p,buf,buf_len);
+ } else {
+
+ *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC,
+ addr_beg_p, addr_end_p-addr_beg_p,
+ buf, buf_len);
+ }
+ ip_masq_listen(n_ms);
+ ip_masq_put(n_ms);
+ return diff;
+ }
+ }
+ }
+ return 0;
+
+}
+
+/*
+ * Main irc object
+ * You need 1 object per port in case you need
+ * to offer also other used irc ports (6665,6666,etc),
+ * they will share methods but they need own space for
+ * data.
+ */
+
+struct ip_masq_app ip_masq_irc = {
+ NULL, /* next */
+ "irc", /* name */
+ 0, /* type */
+ 0, /* n_attach */
+ masq_irc_init_1, /* init_1 */
+ masq_irc_done_1, /* done_1 */
+ masq_irc_out, /* pkt_out */
+ NULL /* pkt_in */
+};
+
+/*
+ * ip_masq_irc initialization
+ */
+
+__initfunc(int ip_masq_irc_init(void))
+{
+ int i, j;
+
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (ports[i]) {
+ if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
+ GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ memcpy(masq_incarnations[i], &ip_masq_irc, sizeof(struct ip_masq_app));
+ if ((j = register_ip_masq_app(masq_incarnations[i],
+ IPPROTO_TCP,
+ ports[i]))) {
+ return j;
+ }
+ IP_MASQ_DEBUG(1-debug,
+ "Irc: loaded support on port[%d] = %d\n",
+ i, ports[i]);
+ } else {
+ /* To be safe, force the incarnation table entry to NULL */
+ masq_incarnations[i] = NULL;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ip_masq_irc fin.
+ */
+
+int ip_masq_irc_done(void)
+{
+ int i, j, k;
+
+ k=0;
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (masq_incarnations[i]) {
+ if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
+ k = j;
+ } else {
+ kfree(masq_incarnations[i]);
+ masq_incarnations[i] = NULL;
+ IP_MASQ_DEBUG(1-debug, "Irc: unloaded support on port[%d] = %d\n",
+ i, ports[i]);
+ }
+ }
+ }
+ return k;
+}
+
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_masq_irc_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_masq_irc_done() != 0)
+ printk(KERN_INFO "ip_masq_irc: can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_mfw.c b/pfinet/linux-src/net/ipv4/ip_masq_mfw.c
new file mode 100644
index 00000000..60c77970
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_mfw.c
@@ -0,0 +1,769 @@
+/*
+ * IP_MASQ_MARKFW masquerading module
+ *
+ * Does (reverse-masq) forwarding based on skb->fwmark value
+ *
+ * $Id: ip_masq_mfw.c,v 1.3.2.1 1999/07/02 10:10:03 davem Exp $
+ *
+ * Author: Juan Jose Ciarlante <jjciarla@raiz.uncu.edu.ar>
+ * based on Steven Clarke's portfw
+ *
+ * Fixes:
+ * JuanJo Ciarlante: added u-space sched support
+ * JuanJo Ciarlante: if rport==0, use packet dest port *grin*
+ * JuanJo Ciarlante: fixed tcp syn&&!ack creation
+ *
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <net/ip.h>
+#include <linux/ip_fw.h>
+#include <linux/ip_masq.h>
+#include <net/ip_masq.h>
+#include <net/ip_masq_mod.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <asm/softirq.h>
+#include <asm/spinlock.h>
+#include <asm/atomic.h>
+
+static struct ip_masq_mod *mmod_self = NULL;
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
+
+/*
+ * Lists structure:
+ * There is a "main" linked list with entries hashed
+ * by fwmark value (struct ip_masq_mfw, the "m-entries").
+ *
+ * Each of this m-entry holds a double linked list
+ * of "forward-to" hosts (struct ip_masq_mfw_host, the "m.host"),
+ * the round-robin scheduling takes place by rotating m.host entries
+ * "inside" its m-entry.
+ */
+
+/*
+ * Each forwarded host (addr:port) is stored here
+ */
+struct ip_masq_mfw_host {
+ struct list_head list;
+ __u32 addr;
+ __u16 port;
+ __u16 pad0;
+ __u32 fwmark;
+ int pref;
+ atomic_t pref_cnt;
+};
+
+#define IP_MASQ_MFW_HSIZE 16
+/*
+ * This entries are indexed by fwmark,
+ * they hold a list of forwarded addr:port
+ */
+
+struct ip_masq_mfw {
+ struct ip_masq_mfw *next; /* linked list */
+ __u32 fwmark; /* key: firewall mark */
+ struct list_head hosts; /* list of forward-to hosts */
+ atomic_t nhosts; /* number of "" */
+ rwlock_t lock;
+};
+
+
+static struct semaphore mfw_sema = MUTEX;
+static rwlock_t mfw_lock = RW_LOCK_UNLOCKED;
+
+static struct ip_masq_mfw *ip_masq_mfw_table[IP_MASQ_MFW_HSIZE];
+
+static __inline__ int mfw_hash_val(int fwmark)
+{
+ return fwmark & 0x0f;
+}
+
+/*
+ * Get m-entry by "fwmark"
+ * Caller must lock tables.
+ */
+
+static struct ip_masq_mfw *__mfw_get(int fwmark)
+{
+ struct ip_masq_mfw* mfw;
+ int hash = mfw_hash_val(fwmark);
+
+ for (mfw=ip_masq_mfw_table[hash];mfw;mfw=mfw->next) {
+ if (mfw->fwmark==fwmark) {
+ goto out;
+ }
+ }
+out:
+ return mfw;
+}
+
+/*
+ * Links m-entry.
+ * Caller should have checked if already present for same fwmark
+ *
+ * Caller must lock tables.
+ */
+static int __mfw_add(struct ip_masq_mfw *mfw)
+{
+ int fwmark = mfw->fwmark;
+ int hash = mfw_hash_val(fwmark);
+
+ mfw->next = ip_masq_mfw_table[hash];
+ ip_masq_mfw_table[hash] = mfw;
+ ip_masq_mod_inc_nent(mmod_self);
+
+ return 0;
+}
+
+/*
+ * Creates a m-entry (doesn't link it)
+ */
+
+static struct ip_masq_mfw * mfw_new(int fwmark)
+{
+ struct ip_masq_mfw *mfw;
+
+ mfw = kmalloc(sizeof(*mfw), GFP_KERNEL);
+ if (mfw == NULL)
+ goto out;
+
+ MOD_INC_USE_COUNT;
+ memset(mfw, 0, sizeof(*mfw));
+ mfw->fwmark = fwmark;
+ mfw->lock = RW_LOCK_UNLOCKED;
+
+ INIT_LIST_HEAD(&mfw->hosts);
+out:
+ return mfw;
+}
+
+static void mfw_host_to_user(struct ip_masq_mfw_host *h, struct ip_mfw_user *mu)
+{
+ mu->raddr = h->addr;
+ mu->rport = h->port;
+ mu->fwmark = h->fwmark;
+ mu->pref = h->pref;
+}
+
+/*
+ * Creates a m.host (doesn't link it in a m-entry)
+ */
+static struct ip_masq_mfw_host * mfw_host_new(struct ip_mfw_user *mu)
+{
+ struct ip_masq_mfw_host * mfw_host;
+ mfw_host = kmalloc(sizeof (*mfw_host), GFP_KERNEL);
+ if (!mfw_host)
+ return NULL;
+
+ MOD_INC_USE_COUNT;
+ memset(mfw_host, 0, sizeof(*mfw_host));
+ mfw_host->addr = mu->raddr;
+ mfw_host->port = mu->rport;
+ mfw_host->fwmark = mu->fwmark;
+ mfw_host->pref = mu->pref;
+ atomic_set(&mfw_host->pref_cnt, mu->pref);
+
+ return mfw_host;
+}
+
+/*
+ * Create AND link m.host to m-entry.
+ * It locks m.lock.
+ */
+static int mfw_addhost(struct ip_masq_mfw *mfw, struct ip_mfw_user *mu, int attail)
+{
+ struct ip_masq_mfw_host *mfw_host;
+
+ mfw_host = mfw_host_new(mu);
+ if (!mfw_host)
+ return -ENOMEM;
+
+ write_lock_bh(&mfw->lock);
+ list_add(&mfw_host->list, attail? mfw->hosts.prev : &mfw->hosts);
+ atomic_inc(&mfw->nhosts);
+ write_unlock_bh(&mfw->lock);
+
+ return 0;
+}
+
+/*
+ * Unlink AND destroy m.host(s) from m-entry.
+ * Wildcard (nul host or addr) ok.
+ * It uses m.lock.
+ */
+static int mfw_delhost(struct ip_masq_mfw *mfw, struct ip_mfw_user *mu)
+{
+
+ struct list_head *l,*e;
+ struct ip_masq_mfw_host *h;
+ int n_del = 0;
+ l = &mfw->hosts;
+
+ write_lock_bh(&mfw->lock);
+ for (e=l->next; e!=l; e=e->next)
+ {
+ h = list_entry(e, struct ip_masq_mfw_host, list);
+ if ((!mu->raddr || h->addr == mu->raddr) &&
+ (!mu->rport || h->port == mu->rport)) {
+ /* HIT */
+ atomic_dec(&mfw->nhosts);
+ list_del(&h->list);
+ kfree_s(h, sizeof(*h));
+ MOD_DEC_USE_COUNT;
+ n_del++;
+ }
+
+ }
+ write_unlock_bh(&mfw->lock);
+ return n_del? 0 : -ESRCH;
+}
+
+/*
+ * Changes m.host parameters
+ * Wildcards ok
+ *
+ * Caller must lock tables.
+ */
+static int __mfw_edithost(struct ip_masq_mfw *mfw, struct ip_mfw_user *mu)
+{
+
+ struct list_head *l,*e;
+ struct ip_masq_mfw_host *h;
+ int n_edit = 0;
+ l = &mfw->hosts;
+
+ for (e=l->next; e!=l; e=e->next)
+ {
+ h = list_entry(e, struct ip_masq_mfw_host, list);
+ if ((!mu->raddr || h->addr == mu->raddr) &&
+ (!mu->rport || h->port == mu->rport)) {
+ /* HIT */
+ h->pref = mu->pref;
+ atomic_set(&h->pref_cnt, mu->pref);
+ n_edit++;
+ }
+
+ }
+ return n_edit? 0 : -ESRCH;
+}
+
+/*
+ * Destroys m-entry.
+ * Caller must have checked that it doesn't hold any m.host(s)
+ */
+static void mfw_destroy(struct ip_masq_mfw *mfw)
+{
+ kfree_s(mfw, sizeof(*mfw));
+ MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Unlink m-entry.
+ *
+ * Caller must lock tables.
+ */
+static int __mfw_del(struct ip_masq_mfw *mfw)
+{
+ struct ip_masq_mfw **mfw_p;
+ int ret = -EINVAL;
+
+
+ for(mfw_p=&ip_masq_mfw_table[mfw_hash_val(mfw->fwmark)];
+ *mfw_p;
+ mfw_p = &((*mfw_p)->next))
+ {
+ if (mfw==(*mfw_p)) {
+ *mfw_p = mfw->next;
+ ip_masq_mod_dec_nent(mmod_self);
+ ret = 0;
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
+
+/*
+ * Crude m.host scheduler
+ * This interface could be exported to allow playing with
+ * other sched policies.
+ *
+ * Caller must lock m-entry.
+ */
+static struct ip_masq_mfw_host * __mfw_sched(struct ip_masq_mfw *mfw, int force)
+{
+ struct ip_masq_mfw_host *h = NULL;
+
+ if (atomic_read(&mfw->nhosts) == 0)
+ goto out;
+
+ /*
+ * Here resides actual sched policy:
+ * When pref_cnt touches 0, entry gets shifted to tail and
+ * its pref_cnt reloaded from h->pref (actual value
+ * passed from u-space).
+ *
+ * Exception is pref==0: avoid scheduling.
+ */
+
+ h = list_entry(mfw->hosts.next, struct ip_masq_mfw_host, list);
+
+ if (atomic_read(&mfw->nhosts) <= 1)
+ goto out;
+
+ if ((h->pref && atomic_dec_and_test(&h->pref_cnt)) || force) {
+ atomic_set(&h->pref_cnt, h->pref);
+ list_del(&h->list);
+ list_add(&h->list, mfw->hosts.prev);
+ }
+out:
+ return h;
+}
+
+/*
+ * Main lookup routine.
+ * HITs fwmark and schedules m.host entries if required
+ */
+static struct ip_masq_mfw_host * mfw_lookup(int fwmark)
+{
+ struct ip_masq_mfw *mfw;
+ struct ip_masq_mfw_host *h = NULL;
+
+ read_lock(&mfw_lock);
+ mfw = __mfw_get(fwmark);
+
+ if (mfw) {
+ write_lock(&mfw->lock);
+ h = __mfw_sched(mfw, 0);
+ write_unlock(&mfw->lock);
+ }
+
+ read_unlock(&mfw_lock);
+ return h;
+}
+
+#ifdef CONFIG_PROC_FS
+static int mfw_procinfo(char *buffer, char **start, off_t offset,
+ int length, int dummy)
+{
+ struct ip_masq_mfw *mfw;
+ struct ip_masq_mfw_host *h;
+ struct list_head *l,*e;
+ off_t pos=0, begin;
+ char temp[129];
+ int idx = 0;
+ int len=0;
+
+ MOD_INC_USE_COUNT;
+
+ IP_MASQ_DEBUG(1-debug, "Entered mfw_info\n");
+
+ if (offset < 64)
+ {
+ sprintf(temp, "FwMark > RAddr RPort PrCnt Pref");
+ len = sprintf(buffer, "%-63s\n", temp);
+ }
+ pos = 64;
+
+ for(idx = 0; idx < IP_MASQ_MFW_HSIZE; idx++)
+ {
+ read_lock(&mfw_lock);
+ for(mfw = ip_masq_mfw_table[idx]; mfw ; mfw = mfw->next)
+ {
+ read_lock_bh(&mfw->lock);
+ l=&mfw->hosts;
+
+ for(e=l->next;l!=e;e=e->next) {
+ h = list_entry(e, struct ip_masq_mfw_host, list);
+ pos += 64;
+ if (pos <= offset) {
+ len = 0;
+ continue;
+ }
+
+ sprintf(temp,"0x%x > %08lX %5u %5d %5d",
+ h->fwmark,
+ ntohl(h->addr), ntohs(h->port),
+ atomic_read(&h->pref_cnt), h->pref);
+ len += sprintf(buffer+len, "%-63s\n", temp);
+
+ if(len >= length) {
+ read_unlock_bh(&mfw->lock);
+ read_unlock(&mfw_lock);
+ goto done;
+ }
+ }
+ read_unlock_bh(&mfw->lock);
+ }
+ read_unlock(&mfw_lock);
+ }
+
+done:
+
+ if (len) {
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ }
+ if(len>length)
+ len = length;
+ MOD_DEC_USE_COUNT;
+ return len;
+}
+static struct proc_dir_entry mfw_proc_entry = {
+/* 0, 0, NULL", */
+ 0, 3, "mfw",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ mfw_procinfo
+};
+
+#define proc_ent &mfw_proc_entry
+#else /* !CONFIG_PROC_FS */
+
+#define proc_ent NULL
+#endif
+
+
+static void mfw_flush(void)
+{
+ struct ip_masq_mfw *mfw, *local_table[IP_MASQ_MFW_HSIZE];
+ struct ip_masq_mfw_host *h;
+ struct ip_masq_mfw *mfw_next;
+ int idx;
+ struct list_head *l,*e;
+
+ write_lock_bh(&mfw_lock);
+ memcpy(local_table, ip_masq_mfw_table, sizeof ip_masq_mfw_table);
+ memset(ip_masq_mfw_table, 0, sizeof ip_masq_mfw_table);
+ write_unlock_bh(&mfw_lock);
+
+ /*
+ * For every hash table row ...
+ */
+ for(idx=0;idx<IP_MASQ_MFW_HSIZE;idx++) {
+
+ /*
+ * For every m-entry in row ...
+ */
+ for(mfw=local_table[idx];mfw;mfw=mfw_next) {
+ /*
+ * For every m.host in m-entry ...
+ */
+ l=&mfw->hosts;
+ while((e=l->next) != l) {
+ h = list_entry(e, struct ip_masq_mfw_host, list);
+ atomic_dec(&mfw->nhosts);
+ list_del(&h->list);
+ kfree_s(h, sizeof(*h));
+ MOD_DEC_USE_COUNT;
+ }
+
+ if (atomic_read(&mfw->nhosts)) {
+ IP_MASQ_ERR("mfw_flush(): after flushing row nhosts=%d\n",
+ atomic_read(&mfw->nhosts));
+ }
+ mfw_next = mfw->next;
+ kfree_s(mfw, sizeof(*mfw));
+ MOD_DEC_USE_COUNT;
+ ip_masq_mod_dec_nent(mmod_self);
+ }
+ }
+}
+
+/*
+ * User space control entry point
+ */
+static int mfw_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
+{
+ struct ip_mfw_user *mu = &mctl->u.mfw_user;
+ struct ip_masq_mfw *mfw;
+ int ret = EINVAL;
+ int arglen = optlen - IP_MASQ_CTL_BSIZE;
+ int cmd;
+
+
+ IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
+ arglen,
+ sizeof (*mu),
+ optlen,
+ sizeof (*mctl));
+
+ /*
+ * checks ...
+ */
+ if (arglen != sizeof(*mu) && optlen != sizeof(*mctl))
+ return -EINVAL;
+
+ /*
+ * Don't trust the lusers - plenty of error checking!
+ */
+ cmd = mctl->m_cmd;
+ IP_MASQ_DEBUG(1-debug, "ip_masq_mfw_ctl(cmd=%d, fwmark=%d)\n",
+ cmd, mu->fwmark);
+
+
+ switch(cmd) {
+ case IP_MASQ_CMD_NONE:
+ return 0;
+ case IP_MASQ_CMD_FLUSH:
+ break;
+ case IP_MASQ_CMD_ADD:
+ case IP_MASQ_CMD_INSERT:
+ case IP_MASQ_CMD_SET:
+ if (mu->fwmark == 0) {
+ IP_MASQ_DEBUG(1-debug, "invalid fwmark==0\n");
+ return -EINVAL;
+ }
+ if (mu->pref < 0) {
+ IP_MASQ_DEBUG(1-debug, "invalid pref==%d\n",
+ mu->pref);
+ return -EINVAL;
+ }
+ break;
+ }
+
+
+ ret = -EINVAL;
+
+ switch(cmd) {
+ case IP_MASQ_CMD_ADD:
+ case IP_MASQ_CMD_INSERT:
+ if (!mu->raddr) {
+ IP_MASQ_DEBUG(0-debug, "ip_masq_mfw_ctl(ADD): invalid redirect 0x%x:%d\n",
+ mu->raddr, mu->rport);
+ goto out;
+ }
+
+ /*
+ * Cannot just use mfw_lock because below
+ * are allocations that can sleep; so
+ * to assure "new entry" atomic creation
+ * I use a semaphore.
+ *
+ */
+ down(&mfw_sema);
+
+ read_lock(&mfw_lock);
+ mfw = __mfw_get(mu->fwmark);
+ read_unlock(&mfw_lock);
+
+ /*
+ * If first host, create m-entry
+ */
+ if (mfw == NULL) {
+ mfw = mfw_new(mu->fwmark);
+ if (mfw == NULL)
+ ret = -ENOMEM;
+ }
+
+ if (mfw) {
+ /*
+ * Put m.host in m-entry.
+ */
+ ret = mfw_addhost(mfw, mu, cmd == IP_MASQ_CMD_ADD);
+
+ /*
+ * If first host, link m-entry to hash table.
+ * Already protected by global lock.
+ */
+ if (ret == 0 && atomic_read(&mfw->nhosts) == 1) {
+ write_lock_bh(&mfw_lock);
+ __mfw_add(mfw);
+ write_unlock_bh(&mfw_lock);
+ }
+ if (atomic_read(&mfw->nhosts) == 0) {
+ mfw_destroy(mfw);
+ }
+ }
+
+ up(&mfw_sema);
+
+ break;
+
+ case IP_MASQ_CMD_DEL:
+ down(&mfw_sema);
+
+ read_lock(&mfw_lock);
+ mfw = __mfw_get(mu->fwmark);
+ read_unlock(&mfw_lock);
+
+ if (mfw) {
+ ret = mfw_delhost(mfw, mu);
+
+ /*
+ * Last lease will free
+ * XXX check logic XXX
+ */
+ if (atomic_read(&mfw->nhosts) == 0) {
+ write_lock_bh(&mfw_lock);
+ __mfw_del(mfw);
+ write_unlock_bh(&mfw_lock);
+ mfw_destroy(mfw);
+ }
+ } else
+ ret = -ESRCH;
+
+ up(&mfw_sema);
+ break;
+ case IP_MASQ_CMD_FLUSH:
+
+ down(&mfw_sema);
+ mfw_flush();
+ up(&mfw_sema);
+ ret = 0;
+ break;
+ case IP_MASQ_CMD_SET:
+ /*
+ * No need to semaphorize here, main list is not
+ * modified.
+ */
+ read_lock(&mfw_lock);
+
+ mfw = __mfw_get(mu->fwmark);
+ if (mfw) {
+ write_lock_bh(&mfw->lock);
+
+ if (mu->flags & IP_MASQ_MFW_SCHED) {
+ struct ip_masq_mfw_host *h;
+ if ((h=__mfw_sched(mfw, 1))) {
+ mfw_host_to_user(h, mu);
+ ret = 0;
+ }
+ } else {
+ ret = __mfw_edithost(mfw, mu);
+ }
+
+ write_unlock_bh(&mfw->lock);
+ }
+
+ read_unlock(&mfw_lock);
+ break;
+ }
+out:
+
+ return ret;
+}
+
+/*
+ * Module stubs called from ip_masq core module
+ */
+
+/*
+ * Input rule stub, called very early for each incoming packet,
+ * to see if this module has "interest" in packet.
+ */
+static int mfw_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
+{
+ int val;
+ read_lock(&mfw_lock);
+ val = ( __mfw_get(skb->fwmark) != 0);
+ read_unlock(&mfw_lock);
+ return val;
+}
+
+/*
+ * Input-create stub, called to allow "custom" masq creation
+ */
+static struct ip_masq * mfw_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
+{
+ union ip_masq_tphdr tph;
+ struct ip_masq *ms = NULL;
+ struct ip_masq_mfw_host *h = NULL;
+
+ tph.raw = (char*) iph + iph->ihl * 4;
+
+ switch (iph->protocol) {
+ case IPPROTO_TCP:
+ /*
+ * Only open TCP tunnel if SYN+!ACK packet
+ */
+ if (!tph.th->syn && tph.th->ack)
+ return NULL;
+ case IPPROTO_UDP:
+ break;
+ default:
+ return NULL;
+ }
+
+ /*
+ * If no entry exists in the masquerading table
+ * and the port is involved
+ * in port forwarding, create a new masq entry
+ */
+
+ if ((h=mfw_lookup(skb->fwmark))) {
+ ms = ip_masq_new(iph->protocol,
+ iph->daddr, tph.portp[1],
+ /* if no redir-port, use packet dest port */
+ h->addr, h->port? h->port : tph.portp[1],
+ iph->saddr, tph.portp[0],
+ 0);
+
+ if (ms != NULL)
+ ip_masq_listen(ms);
+ }
+ return ms;
+}
+
+
+#define mfw_in_update NULL
+#define mfw_out_rule NULL
+#define mfw_out_create NULL
+#define mfw_out_update NULL
+
+static struct ip_masq_mod mfw_mod = {
+ NULL, /* next */
+ NULL, /* next_reg */
+ "mfw", /* name */
+ ATOMIC_INIT(0), /* nent */
+ ATOMIC_INIT(0), /* refcnt */
+ proc_ent,
+ mfw_ctl,
+ NULL, /* masq_mod_init */
+ NULL, /* masq_mod_done */
+ mfw_in_rule,
+ mfw_in_update,
+ mfw_in_create,
+ mfw_out_rule,
+ mfw_out_update,
+ mfw_out_create,
+};
+
+
+__initfunc(int ip_mfw_init(void))
+{
+ return register_ip_masq_mod ((mmod_self=&mfw_mod));
+}
+
+int ip_mfw_done(void)
+{
+ return unregister_ip_masq_mod(&mfw_mod);
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_mfw_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_mfw_done() != 0)
+ printk(KERN_INFO "can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_mod.c b/pfinet/linux-src/net/ipv4/ip_masq_mod.c
new file mode 100644
index 00000000..b99502f3
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_mod.c
@@ -0,0 +1,322 @@
+/*
+ * IP_MASQ_MOD masq modules support
+ *
+ *
+ * Author: Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
+ *
+ * $Id: ip_masq_mod.c,v 1.5.2.1 1999/07/02 10:10:03 davem Exp $
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Changes:
+ * Cyrus Durgin: fixed kerneld stuff for kmod.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <net/ip_masq.h>
+#include <net/ip_masq_mod.h>
+
+#include <linux/ip_masq.h>
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+EXPORT_SYMBOL(register_ip_masq_mod);
+EXPORT_SYMBOL(unregister_ip_masq_mod);
+EXPORT_SYMBOL(ip_masq_mod_lkp_link);
+EXPORT_SYMBOL(ip_masq_mod_lkp_unlink);
+
+static spinlock_t masq_mod_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Base pointer for registered modules
+ */
+struct ip_masq_mod * ip_masq_mod_reg_base = NULL;
+
+/*
+ * Base pointer for lookup (subset of above, a module could be
+ * registered, but it could have no active rule); will avoid
+ * unnecessary lookups.
+ */
+struct ip_masq_mod * ip_masq_mod_lkp_base = NULL;
+
+int ip_masq_mod_register_proc(struct ip_masq_mod *mmod)
+{
+#ifdef CONFIG_PROC_FS
+ int ret;
+
+ struct proc_dir_entry *ent = mmod->mmod_proc_ent;
+
+ if (!ent)
+ return 0;
+ if (!ent->name) {
+ ent->name = mmod->mmod_name;
+ ent->namelen = strlen (mmod->mmod_name);
+ }
+ ret = ip_masq_proc_register(ent);
+ if (ret) mmod->mmod_proc_ent = NULL;
+
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+void ip_masq_mod_unregister_proc(struct ip_masq_mod *mmod)
+{
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *ent = mmod->mmod_proc_ent;
+ if (!ent)
+ return;
+ ip_masq_proc_unregister(ent);
+#endif
+}
+
+/*
+ * Link/unlink object for lookups
+ */
+
+int ip_masq_mod_lkp_unlink(struct ip_masq_mod *mmod)
+{
+ struct ip_masq_mod **mmod_p;
+
+ write_lock_bh(&masq_mod_lock);
+
+ for (mmod_p = &ip_masq_mod_lkp_base; *mmod_p ; mmod_p = &(*mmod_p)->next)
+ if (mmod == (*mmod_p)) {
+ *mmod_p = mmod->next;
+ mmod->next = NULL;
+ write_unlock_bh(&masq_mod_lock);
+ return 0;
+ }
+
+ write_unlock_bh(&masq_mod_lock);
+ return -EINVAL;
+}
+
+int ip_masq_mod_lkp_link(struct ip_masq_mod *mmod)
+{
+ write_lock_bh(&masq_mod_lock);
+
+ mmod->next = ip_masq_mod_lkp_base;
+ ip_masq_mod_lkp_base=mmod;
+
+ write_unlock_bh(&masq_mod_lock);
+ return 0;
+}
+
+int register_ip_masq_mod(struct ip_masq_mod *mmod)
+{
+ if (!mmod) {
+ IP_MASQ_ERR("register_ip_masq_mod(): NULL arg\n");
+ return -EINVAL;
+ }
+ if (!mmod->mmod_name) {
+ IP_MASQ_ERR("register_ip_masq_mod(): NULL mmod_name\n");
+ return -EINVAL;
+ }
+ ip_masq_mod_register_proc(mmod);
+
+ mmod->next_reg = ip_masq_mod_reg_base;
+ ip_masq_mod_reg_base=mmod;
+
+ return 0;
+}
+
+int unregister_ip_masq_mod(struct ip_masq_mod *mmod)
+{
+ struct ip_masq_mod **mmod_p;
+
+ if (!mmod) {
+ IP_MASQ_ERR( "unregister_ip_masq_mod(): NULL arg\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Only allow unregistration if it is not referenced
+ */
+ if (atomic_read(&mmod->refcnt)) {
+ IP_MASQ_ERR( "unregister_ip_masq_mod(): is in use by %d guys. failed\n",
+ atomic_read(&mmod->refcnt));
+ return -EINVAL;
+ }
+
+ /*
+ * Must be already unlinked from lookup list
+ */
+ if (mmod->next) {
+ IP_MASQ_WARNING("MASQ: unregistering \"%s\" while in lookup list.fixed.",
+ mmod->mmod_name);
+ ip_masq_mod_lkp_unlink(mmod);
+ }
+
+ for (mmod_p = &ip_masq_mod_reg_base; *mmod_p ; mmod_p = &(*mmod_p)->next_reg)
+ if (mmod == (*mmod_p)) {
+ ip_masq_mod_unregister_proc(mmod);
+ *mmod_p = mmod->next_reg;
+ return 0;
+ }
+
+ IP_MASQ_ERR("unregister_ip_masq_mod(%s): not linked \n", mmod->mmod_name);
+ return -EINVAL;
+}
+
+int ip_masq_mod_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
+{
+ struct ip_masq_mod *mmod;
+ int ret = IP_MASQ_MOD_NOP;
+
+ for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
+ if (!mmod->mmod_in_rule) continue;
+ switch (ret=mmod->mmod_in_rule(skb, iph)) {
+ case IP_MASQ_MOD_NOP:
+ continue;
+ case IP_MASQ_MOD_ACCEPT:
+ case IP_MASQ_MOD_REJECT:
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
+
+int ip_masq_mod_out_rule(const struct sk_buff *skb, const struct iphdr *iph)
+{
+ struct ip_masq_mod *mmod;
+ int ret = IP_MASQ_MOD_NOP;
+
+ for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
+ if (!mmod->mmod_out_rule) continue;
+ switch (ret=mmod->mmod_out_rule(skb, iph)) {
+ case IP_MASQ_MOD_NOP:
+ continue;
+ case IP_MASQ_MOD_ACCEPT:
+ case IP_MASQ_MOD_REJECT:
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
+
+struct ip_masq * ip_masq_mod_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
+{
+ struct ip_masq_mod *mmod;
+ struct ip_masq *ms = NULL;
+
+ for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
+ if (!mmod->mmod_in_create) continue;
+ if ((ms=mmod->mmod_in_create(skb, iph, maddr))) {
+ goto out;
+ }
+ }
+out:
+ return ms;
+}
+
+struct ip_masq * ip_masq_mod_out_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
+{
+ struct ip_masq_mod *mmod;
+ struct ip_masq *ms = NULL;
+
+ for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
+ if (!mmod->mmod_out_create) continue;
+ if ((ms=mmod->mmod_out_create(skb, iph, maddr))) {
+ goto out;
+ }
+ }
+out:
+ return ms;
+}
+
+int ip_masq_mod_in_update(const struct sk_buff *skb, const struct iphdr *iph, struct ip_masq *ms)
+{
+ struct ip_masq_mod *mmod;
+ int ret = IP_MASQ_MOD_NOP;
+
+ for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
+ if (!mmod->mmod_in_update) continue;
+ switch (ret=mmod->mmod_in_update(skb, iph, ms)) {
+ case IP_MASQ_MOD_NOP:
+ continue;
+ case IP_MASQ_MOD_ACCEPT:
+ case IP_MASQ_MOD_REJECT:
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
+
+int ip_masq_mod_out_update(const struct sk_buff *skb, const struct iphdr *iph, struct ip_masq *ms)
+{
+ struct ip_masq_mod *mmod;
+ int ret = IP_MASQ_MOD_NOP;
+
+ for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
+ if (!mmod->mmod_out_update) continue;
+ switch (ret=mmod->mmod_out_update(skb, iph, ms)) {
+ case IP_MASQ_MOD_NOP:
+ continue;
+ case IP_MASQ_MOD_ACCEPT:
+ case IP_MASQ_MOD_REJECT:
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
+
+struct ip_masq_mod * ip_masq_mod_getbyname(const char *mmod_name)
+{
+ struct ip_masq_mod * mmod;
+
+ IP_MASQ_DEBUG(1, "searching mmod_name \"%s\"\n", mmod_name);
+
+ for (mmod=ip_masq_mod_reg_base; mmod ; mmod=mmod->next_reg) {
+ if (mmod->mmod_ctl && *(mmod_name)
+ && (strcmp(mmod_name, mmod->mmod_name)==0)) {
+ /* HIT */
+ return mmod;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Module control entry
+ */
+int ip_masq_mod_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
+{
+ struct ip_masq_mod * mmod;
+#ifdef CONFIG_KMOD
+ char kmod_name[IP_MASQ_TNAME_MAX+8];
+#endif
+ /* tappo */
+ mctl->m_tname[IP_MASQ_TNAME_MAX-1] = 0;
+
+ mmod = ip_masq_mod_getbyname(mctl->m_tname);
+ if (mmod)
+ return mmod->mmod_ctl(optname, mctl, optlen);
+#ifdef CONFIG_KMOD
+ sprintf(kmod_name,"ip_masq_%s", mctl->m_tname);
+
+ IP_MASQ_DEBUG(1, "About to request \"%s\" module\n", kmod_name);
+
+ /*
+ * Let sleep for a while ...
+ */
+ request_module(kmod_name);
+ mmod = ip_masq_mod_getbyname(mctl->m_tname);
+ if (mmod)
+ return mmod->mmod_ctl(optname, mctl, optlen);
+#endif
+ return ESRCH;
+}
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_portfw.c b/pfinet/linux-src/net/ipv4/ip_masq_portfw.c
new file mode 100644
index 00000000..6c697a10
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_portfw.c
@@ -0,0 +1,508 @@
+/*
+ * IP_MASQ_PORTFW masquerading module
+ *
+ *
+ * $Id: ip_masq_portfw.c,v 1.3.2.1 1999/07/02 10:10:02 davem Exp $
+ *
+ * Author: Steven Clarke <steven.clarke@monmouth.demon.co.uk>
+ *
+ * Fixes:
+ * Juan Jose Ciarlante : created this new file from ip_masq.c and ip_fw.c
+ * Juan Jose Ciarlante : modularized
+ * Juan Jose Ciarlante : use GFP_KERNEL
+ * Juan Jose Ciarlante : locking
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <net/ip.h>
+#include <linux/ip_fw.h>
+#include <linux/ip_masq.h>
+#include <net/ip_masq.h>
+#include <net/ip_masq_mod.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#define IP_PORTFW_PORT_MIN 1
+#define IP_PORTFW_PORT_MAX 60999
+
+struct ip_portfw {
+ struct list_head list;
+ __u32 laddr, raddr;
+ __u16 lport, rport;
+ atomic_t pref_cnt; /* pref "counter" down to 0 */
+ int pref; /* user set pref */
+};
+
+static struct ip_masq_mod *mmod_self = NULL;
+/*
+ * Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
+
+/*
+ * Lock
+ */
+static rwlock_t portfw_lock = RW_LOCK_UNLOCKED;
+
+static struct list_head portfw_list[2];
+static __inline__ int portfw_idx(int protocol)
+{
+ return (protocol==IPPROTO_TCP);
+}
+
+/*
+ *
+ * Delete forwarding entry(s):
+ * called from _DEL, u-space.
+ * . "relaxed" match, except for lport
+ *
+ */
+
+static __inline__ int ip_portfw_del(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr)
+{
+ int prot = portfw_idx(protocol);
+ struct ip_portfw *n;
+ struct list_head *entry;
+ struct list_head *list = &portfw_list[prot];
+ int nent;
+
+ nent = atomic_read(&mmod_self->mmod_nent);
+
+ write_lock_bh(&portfw_lock);
+
+ for (entry=list->next;entry != list;entry = entry->next) {
+ n = list_entry(entry, struct ip_portfw, list);
+ if (n->lport == lport &&
+ (!laddr || n->laddr == laddr) &&
+ (!raddr || n->raddr == raddr) &&
+ (!rport || n->rport == rport)) {
+ list_del(entry);
+ ip_masq_mod_dec_nent(mmod_self);
+ kfree_s(n, sizeof(struct ip_portfw));
+ MOD_DEC_USE_COUNT;
+ }
+ }
+ write_unlock_bh(&portfw_lock);
+
+ return nent==atomic_read(&mmod_self->mmod_nent)? ESRCH : 0;
+}
+
+/*
+ * Flush tables
+ * called from _FLUSH, u-space.
+ */
+static __inline__ void ip_portfw_flush(void)
+{
+ int prot;
+ struct list_head *l;
+ struct list_head *e;
+ struct ip_portfw *n;
+
+ write_lock_bh(&portfw_lock);
+
+ for (prot = 0; prot < 2;prot++) {
+ l = &portfw_list[prot];
+ while((e=l->next) != l) {
+ ip_masq_mod_dec_nent(mmod_self);
+ n = list_entry (e, struct ip_portfw, list);
+ list_del(e);
+ kfree_s(n, sizeof (*n));
+ MOD_DEC_USE_COUNT;
+ }
+ }
+
+ write_unlock_bh(&portfw_lock);
+}
+
+/*
+ * Lookup routine for lport,laddr match
+ * must be called with locked tables
+ */
+static __inline__ struct ip_portfw *ip_portfw_lookup(__u16 protocol, __u16 lport, __u32 laddr, __u32 *daddr_p, __u16 *dport_p)
+{
+ int prot = portfw_idx(protocol);
+
+ struct ip_portfw *n = NULL;
+ struct list_head *l, *e;
+
+ l = &portfw_list[prot];
+
+ for (e=l->next;e!=l;e=e->next) {
+ n = list_entry(e, struct ip_portfw, list);
+ if (lport == n->lport && laddr == n->laddr) {
+ /* Please be nice, don't pass only a NULL dport */
+ if (daddr_p) {
+ *daddr_p = n->raddr;
+ *dport_p = n->rport;
+ }
+
+ goto out;
+ }
+ }
+ n = NULL;
+out:
+ return n;
+}
+
+/*
+ * Edit routine for lport,[laddr], [raddr], [rport] match
+ * By now, only called from u-space
+ */
+static __inline__ int ip_portfw_edit(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr, int pref)
+{
+ int prot = portfw_idx(protocol);
+
+ struct ip_portfw *n = NULL;
+ struct list_head *l, *e;
+ int count = 0;
+
+
+ read_lock_bh(&portfw_lock);
+
+ l = &portfw_list[prot];
+
+ for (e=l->next;e!=l;e=e->next) {
+ n = list_entry(e, struct ip_portfw, list);
+ if (lport == n->lport &&
+ (!laddr || laddr == n->laddr) &&
+ (!rport || rport == n->rport) &&
+ (!raddr || raddr == n->raddr)) {
+ n->pref = pref;
+ atomic_set(&n->pref_cnt, pref);
+ count++;
+ }
+ }
+
+ read_unlock_bh(&portfw_lock);
+
+ return count;
+}
+
+/*
+ * Add/edit en entry
+ * called from _ADD, u-space.
+ * must return 0 or +errno
+ */
+static __inline__ int ip_portfw_add(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr, int pref)
+{
+ struct ip_portfw *npf;
+ int prot = portfw_idx(protocol);
+
+ if (pref <= 0)
+ return EINVAL;
+
+ if (ip_portfw_edit(protocol, lport, laddr, rport, raddr, pref)) {
+ /*
+ * Edit ok ...
+ */
+ return 0;
+ }
+
+ /* may block ... */
+ npf = (struct ip_portfw*) kmalloc(sizeof(struct ip_portfw), GFP_KERNEL);
+
+ if (!npf)
+ return ENOMEM;
+
+ MOD_INC_USE_COUNT;
+ memset(npf, 0, sizeof(*npf));
+
+ npf->laddr = laddr;
+ npf->lport = lport;
+ npf->rport = rport;
+ npf->raddr = raddr;
+ npf->pref = pref;
+
+ atomic_set(&npf->pref_cnt, npf->pref);
+ INIT_LIST_HEAD(&npf->list);
+
+ write_lock_bh(&portfw_lock);
+
+ /*
+ * Add at head
+ */
+ list_add(&npf->list, &portfw_list[prot]);
+
+ write_unlock_bh(&portfw_lock);
+
+ ip_masq_mod_inc_nent(mmod_self);
+ return 0;
+}
+
+
+
+static __inline__ int portfw_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
+{
+ struct ip_portfw_user *mm = &mctl->u.portfw_user;
+ int ret = EINVAL;
+ int arglen = optlen - IP_MASQ_CTL_BSIZE;
+ int cmd;
+
+
+ IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
+ arglen,
+ sizeof (*mm),
+ optlen,
+ sizeof (*mctl));
+
+ /*
+ * Yes, I'm a bad guy ...
+ */
+ if (arglen != sizeof(*mm) && optlen != sizeof(*mctl))
+ return EINVAL;
+
+ /*
+ * Don't trust the lusers - plenty of error checking!
+ */
+ cmd = mctl->m_cmd;
+ IP_MASQ_DEBUG(1-debug, "ip_masq_portfw_ctl(cmd=%d)\n", cmd);
+
+
+ switch (cmd) {
+ case IP_MASQ_CMD_NONE:
+ return 0;
+ case IP_MASQ_CMD_FLUSH:
+ break;
+ default:
+ if (htons(mm->lport) < IP_PORTFW_PORT_MIN || htons(mm->lport) > IP_PORTFW_PORT_MAX)
+ return EINVAL;
+
+ if (mm->protocol!=IPPROTO_TCP && mm->protocol!=IPPROTO_UDP)
+ return EINVAL;
+ }
+
+ switch(cmd) {
+ case IP_MASQ_CMD_ADD:
+ ret = ip_portfw_add(mm->protocol,
+ mm->lport, mm->laddr,
+ mm->rport, mm->raddr,
+ mm->pref);
+ break;
+
+ case IP_MASQ_CMD_DEL:
+ ret = ip_portfw_del(mm->protocol,
+ mm->lport, mm->laddr,
+ mm->rport, mm->raddr);
+ break;
+ case IP_MASQ_CMD_FLUSH:
+ ip_portfw_flush();
+ ret = 0;
+ break;
+ }
+
+
+ return ret;
+}
+
+
+
+
+#ifdef CONFIG_PROC_FS
+
+static int portfw_procinfo(char *buffer, char **start, off_t offset,
+ int length, int unused)
+{
+ off_t pos=0, begin;
+ struct ip_portfw *pf;
+ struct list_head *l, *e;
+ char temp[65];
+ int ind;
+ int len=0;
+
+
+ if (offset < 64)
+ {
+ sprintf(temp, "Prot LAddr LPort > RAddr RPort PrCnt Pref");
+ len = sprintf(buffer, "%-63s\n", temp);
+ }
+ pos = 64;
+
+ read_lock_bh(&portfw_lock);
+
+ for(ind = 0; ind < 2; ind++)
+ {
+ l = &portfw_list[ind];
+ for (e=l->next; e!=l; e=e->next)
+ {
+ pf = list_entry(e, struct ip_portfw, list);
+ pos += 64;
+ if (pos <= offset) {
+ len = 0;
+ continue;
+ }
+
+ sprintf(temp,"%s %08lX %5u > %08lX %5u %5d %5d",
+ ind ? "TCP" : "UDP",
+ ntohl(pf->laddr), ntohs(pf->lport),
+ ntohl(pf->raddr), ntohs(pf->rport),
+ atomic_read(&pf->pref_cnt), pf->pref);
+ len += sprintf(buffer+len, "%-63s\n", temp);
+
+ if (len >= length)
+ goto done;
+ }
+ }
+done:
+ read_unlock_bh(&portfw_lock);
+
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len>length)
+ len = length;
+ return len;
+}
+
+static struct proc_dir_entry portfw_proc_entry = {
+/* 0, 0, NULL", */
+ 0, 6, "portfw", /* Just for compatibility, for now ... */
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ portfw_procinfo
+};
+
+#define proc_ent &portfw_proc_entry
+#else /* !CONFIG_PROC_FS */
+
+#define proc_ent NULL
+#endif
+
+static int portfw_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
+{
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+#ifdef CONFIG_IP_MASQ_DEBUG
+ struct rtable *rt = (struct rtable *)skb->dst;
+#endif
+ struct ip_portfw *pfw;
+
+ IP_MASQ_DEBUG(2, "portfw_in_rule(): skb:= dev=%s (index=%d), rt_iif=%d, rt_flags=0x%x rt_dev___=%s daddr=%d.%d.%d.%d dport=%d\n",
+ skb->dev->name, skb->dev->ifindex, rt->rt_iif, rt->rt_flags,
+ rt->u.dst.dev->name,
+ NIPQUAD(iph->daddr), ntohs(portp[1]));
+
+ read_lock(&portfw_lock);
+ pfw = ip_portfw_lookup(iph->protocol, portp[1], iph->daddr, NULL, NULL);
+ read_unlock(&portfw_lock);
+ return (pfw!=0);
+}
+
+static struct ip_masq * portfw_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
+{
+ /*
+ * If no entry exists in the masquerading table
+ * and the port is involved
+ * in port forwarding, create a new masq entry
+ */
+
+ __u32 raddr;
+ __u16 rport;
+ const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+ struct ip_masq *ms = NULL;
+ struct ip_portfw *pf;
+
+ /*
+ * Lock for writing.
+ */
+ write_lock(&portfw_lock);
+
+ if ((pf=ip_portfw_lookup(iph->protocol,
+ portp[1], iph->daddr,
+ &raddr, &rport))) {
+ ms = ip_masq_new(iph->protocol,
+ iph->daddr, portp[1],
+ raddr, rport,
+ iph->saddr, portp[0],
+ 0);
+ ip_masq_listen(ms);
+
+ if (!ms || atomic_read(&mmod_self->mmod_nent) <= 1
+ /* || ip_masq_nlocks(&portfw_lock) != 1 */ )
+ /*
+ * Maybe later...
+ */
+ goto out;
+
+ /*
+ * Entry created, lock==1.
+ * if pref_cnt == 0, move
+ * entry at _tail_.
+ * This is a simple load balance scheduling
+ */
+
+ if (atomic_dec_and_test(&pf->pref_cnt)) {
+
+ atomic_set(&pf->pref_cnt, pf->pref);
+ list_del(&pf->list);
+ list_add(&pf->list,
+ portfw_list[portfw_idx(iph->protocol)].prev);
+
+ }
+ }
+out:
+ write_unlock(&portfw_lock);
+ return ms;
+}
+
+#define portfw_in_update NULL
+#define portfw_out_rule NULL
+#define portfw_out_create NULL
+#define portfw_out_update NULL
+
+static struct ip_masq_mod portfw_mod = {
+ NULL, /* next */
+ NULL, /* next_reg */
+ "portfw", /* name */
+ ATOMIC_INIT(0), /* nent */
+ ATOMIC_INIT(0), /* refcnt */
+ proc_ent,
+ portfw_ctl,
+ NULL, /* masq_mod_init */
+ NULL, /* masq_mod_done */
+ portfw_in_rule,
+ portfw_in_update,
+ portfw_in_create,
+ portfw_out_rule,
+ portfw_out_update,
+ portfw_out_create,
+};
+
+
+
+__initfunc(int ip_portfw_init(void))
+{
+ INIT_LIST_HEAD(&portfw_list[0]);
+ INIT_LIST_HEAD(&portfw_list[1]);
+ return register_ip_masq_mod ((mmod_self=&portfw_mod));
+}
+
+int ip_portfw_done(void)
+{
+ return unregister_ip_masq_mod(&portfw_mod);
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_portfw_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_portfw_done() != 0)
+ printk(KERN_INFO "ip_portfw_done(): can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_quake.c b/pfinet/linux-src/net/ipv4/ip_masq_quake.c
new file mode 100644
index 00000000..995c3a0a
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_quake.c
@@ -0,0 +1,322 @@
+/*
+ * IP_MASQ_QUAKE quake masquerading module
+ *
+ *
+ * Version: @(#)ip_masq_quake.c 0.02 22/02/97
+ *
+ * Author: Harald Hoyer mailto:HarryH@Royal.Net
+ *
+ *
+ * Fixes:
+ * Harald Hoyer : Unofficial Quake Specs found at
+ * http://www.gamers.org/dEngine/quake/spec/
+ * Harald Hoyer : Check for QUAKE-STRING
+ * Juan Jose Ciarlante : litl bits for 2.1
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/udp.h>
+#include <net/ip_masq.h>
+
+#define DEBUG_CONFIG_IP_MASQ_QUAKE 0
+
+typedef struct
+{
+ __u16 type; // (Little Endian) Type of message.
+ __u16 length; // (Little Endian) Length of message, header included.
+ char message[0]; // The contents of the message.
+} QUAKEHEADER;
+
+struct quake_priv_data {
+ /* Have we seen a client connect message */
+ signed char cl_connect;
+};
+
+static int
+masq_quake_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_INC_USE_COUNT;
+ if ((ms->app_data = kmalloc(sizeof(struct quake_priv_data),
+ GFP_ATOMIC)) == NULL)
+ printk(KERN_INFO "Quake: No memory for application data\n");
+ else
+ {
+ struct quake_priv_data *priv =
+ (struct quake_priv_data *)ms->app_data;
+ priv->cl_connect = 0;
+ }
+ return 0;
+}
+
+static int
+masq_quake_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_DEC_USE_COUNT;
+ if (ms->app_data)
+ kfree_s(ms->app_data, sizeof(struct quake_priv_data));
+ return 0;
+}
+
+int
+masq_quake_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct udphdr *uh;
+ QUAKEHEADER *qh;
+ __u16 udp_port;
+ char *data;
+ unsigned char code;
+ struct quake_priv_data *priv = (struct quake_priv_data *)ms->app_data;
+
+ if(priv->cl_connect == -1)
+ return 0;
+
+ skb = *skb_p;
+
+ iph = skb->nh.iph;
+ uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
+
+ /* Check for lenght */
+ if(ntohs(uh->len) < 5)
+ return 0;
+
+ qh = (QUAKEHEADER *)&uh[1];
+
+ if(qh->type != 0x0080)
+ return 0;
+
+
+ code = qh->message[0];
+
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_in: code = %d \n", (int)code);
+#endif
+
+ switch(code) {
+ case 0x01:
+ /* Connection Request */
+
+ if(ntohs(qh->length) < 0x0c) {
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_in: length < 0xc \n");
+#endif
+ return 0;
+ }
+
+ data = &qh->message[1];
+
+ /* Check for stomping string */
+ if(memcmp(data,"QUAKE\0\3",7)) {
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_out: memcmp failed \n");
+#endif
+ return 0;
+ }
+ else {
+ priv->cl_connect = 1;
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_out: memcmp ok \n");
+#endif
+ }
+ break;
+
+ case 0x81:
+ /* Accept Connection */
+ if((ntohs(qh->length) < 0x09) || (priv->cl_connect == 0))
+ return 0;
+ data = &qh->message[1];
+
+ memcpy(&udp_port, data, 2);
+
+ ms->dport = htons(udp_port);
+
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_in: in_rewrote UDP port %d \n", udp_port);
+#endif
+ priv->cl_connect = -1;
+
+ break;
+ }
+
+ return 0;
+}
+
+int
+masq_quake_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct udphdr *uh;
+ QUAKEHEADER *qh;
+ __u16 udp_port;
+ char *data;
+ unsigned char code;
+ struct ip_masq *n_ms;
+ struct quake_priv_data *priv = (struct quake_priv_data *)ms->app_data;
+
+ if(priv->cl_connect == -1)
+ return 0;
+
+ skb = *skb_p;
+
+ iph = skb->nh.iph;
+ uh = (struct udphdr *)&(((char *)iph)[iph->ihl*4]);
+
+ /* Check for lenght */
+ if(ntohs(uh->len) < 5)
+ return 0;
+
+ qh = (QUAKEHEADER *)&uh[1];
+
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_out: qh->type = %d \n", (int)qh->type);
+#endif
+
+ if(qh->type != 0x0080)
+ return 0;
+
+ code = qh->message[0];
+
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_out: code = %d \n", (int)code);
+#endif
+
+ switch(code) {
+ case 0x01:
+ /* Connection Request */
+
+ if(ntohs(qh->length) < 0x0c) {
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_out: length < 0xc \n");
+#endif
+ return 0;
+ }
+
+ data = &qh->message[1];
+
+ /* Check for stomping string */
+ if(memcmp(data,"QUAKE\0\3",7)) {
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_out: memcmp failed \n");
+#endif
+ return 0;
+ }
+ else {
+ priv->cl_connect = 1;
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_out: memcmp ok \n");
+#endif
+ }
+ break;
+
+ case 0x81:
+ /* Accept Connection */
+ if((ntohs(qh->length) < 0x09) || (priv->cl_connect == 0))
+ return 0;
+
+ data = &qh->message[1];
+
+ memcpy(&udp_port, data, 2);
+
+ n_ms = ip_masq_new(IPPROTO_UDP,
+ maddr, 0,
+ ms->saddr, htons(udp_port),
+ ms->daddr, ms->dport,
+ 0);
+
+ if (n_ms==NULL)
+ return 0;
+
+#if DEBUG_CONFIG_IP_MASQ_QUAKE
+ printk("Quake_out: out_rewrote UDP port %d -> %d\n",
+ udp_port, ntohs(n_ms->mport));
+#endif
+ udp_port = ntohs(n_ms->mport);
+ memcpy(data, &udp_port, 2);
+
+ ip_masq_listen(n_ms);
+ ip_masq_control_add(n_ms, ms);
+ ip_masq_put(n_ms);
+
+ break;
+ }
+
+ return 0;
+}
+
+struct ip_masq_app ip_masq_quake = {
+ NULL, /* next */
+ "Quake_26", /* name */
+ 0, /* type */
+ 0, /* n_attach */
+ masq_quake_init_1, /* ip_masq_init_1 */
+ masq_quake_done_1, /* ip_masq_done_1 */
+ masq_quake_out, /* pkt_out */
+ masq_quake_in /* pkt_in */
+};
+struct ip_masq_app ip_masq_quakenew = {
+ NULL, /* next */
+ "Quake_27", /* name */
+ 0, /* type */
+ 0, /* n_attach */
+ masq_quake_init_1, /* ip_masq_init_1 */
+ masq_quake_done_1, /* ip_masq_done_1 */
+ masq_quake_out, /* pkt_out */
+ masq_quake_in /* pkt_in */
+};
+
+/*
+ * ip_masq_quake initialization
+ */
+
+__initfunc(int ip_masq_quake_init(void))
+{
+ return (register_ip_masq_app(&ip_masq_quake, IPPROTO_UDP, 26000) +
+ register_ip_masq_app(&ip_masq_quakenew, IPPROTO_UDP, 27000));
+}
+
+/*
+ * ip_masq_quake fin.
+ */
+
+int ip_masq_quake_done(void)
+{
+ return (unregister_ip_masq_app(&ip_masq_quake) +
+ unregister_ip_masq_app(&ip_masq_quakenew));
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_masq_quake_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_masq_quake_done() != 0)
+ printk("ip_masq_quake: can't remove module");
+}
+
+#endif /* MODULE */
+
+
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_raudio.c b/pfinet/linux-src/net/ipv4/ip_masq_raudio.c
new file mode 100644
index 00000000..ee3e276b
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_raudio.c
@@ -0,0 +1,578 @@
+/*
+ * IP_MASQ_RAUDIO - Real Audio masquerading module
+ *
+ *
+ * Version: @(#)$Id: ip_masq_raudio.c,v 1.11 1998/10/06 04:49:04 davem Exp $
+ *
+ * Author: Nigel Metheringham
+ * Real Time Streaming code by Progressive Networks
+ * [strongly based on ftp module by Juan Jose Ciarlante & Wouter Gadeyne]
+ * [Real Audio information taken from Progressive Networks firewall docs]
+ * [Kudos to Progressive Networks for making the protocol specs available]
+ *
+ *
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ *
+ * Limitations
+ * The IP Masquerading proxies at present do not have access to a processed
+ * data stream. Hence for a protocol like the Real Audio control protocol,
+ * which depends on knowing where you are in the data stream, you either
+ * to keep a *lot* of state in your proxy, or you cheat and simplify the
+ * problem [needless to say I did the latter].
+ *
+ * This proxy only handles data in the first packet. Everything else is
+ * passed transparently. This means it should work under all normal
+ * circumstances, but it could be fooled by new data formats or a
+ * malicious application!
+ *
+ * At present the "first packet" is defined as a packet starting with
+ * the protocol ID string - "PNA".
+ * When the link is up there appears to be enough control data
+ * crossing the control link to keep it open even if a long audio
+ * piece is playing.
+ *
+ * The Robust UDP support added in RealAudio 3.0 is supported, but due
+ * to servers/clients not making great use of this has not been greatly
+ * tested. RealVideo (as used in the Real client version 4.0beta1) is
+ * supported but again is not greatly tested (bandwidth requirements
+ * appear to exceed that available at the sites supporting the protocol).
+ *
+ * Multiple Port Support
+ * The helper can be made to handle up to MAX_MASQ_APP_PORTS (normally 12)
+ * with the port numbers being defined at module load time. The module
+ * uses the symbol "ports" to define a list of monitored ports, which can
+ * be specified on the insmod command line as
+ * ports=x1,x2,x3...
+ * where x[n] are integer port numbers. This option can be put into
+ * /etc/conf.modules (or /etc/modules.conf depending on your config)
+ * where modload will pick it up should you use modload to load your
+ * modules.
+ *
+ * Fixes:
+ * Juan Jose Ciarlante : Use control_add() for control chan
+ * 10/15/97 - Modifications to allow masquerading of RTSP connections as
+ * well as PNA, which can potentially exist on the same port.
+ * Joe Rumsey <ogre@real.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/ip_masq.h>
+
+/*
+#ifndef DEBUG_CONFIG_IP_MASQ_RAUDIO
+#define DEBUG_CONFIG_IP_MASQ_RAUDIO 0
+#endif
+*/
+
+#define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c))
+#define ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
+
+struct raudio_priv_data {
+ /* Associated data connection - setup but not used at present */
+ struct ip_masq *data_conn;
+ /* UDP Error correction connection - setup but not used at present */
+ struct ip_masq *error_conn;
+ /* Have we seen and performed setup */
+ short seen_start;
+ short is_rtsp;
+};
+
+int
+masq_rtsp_out (struct ip_masq_app *mapp,
+ struct ip_masq *ms,
+ struct sk_buff **skb_p,
+ __u32 maddr);
+
+/*
+ * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper
+ * First port is set to the default port.
+ */
+int ports[MAX_MASQ_APP_PORTS] = {554, 7070, 0}; /* I rely on the trailing items being set to zero */
+struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
+
+/*
+ * Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
+
+
+static int
+masq_raudio_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_INC_USE_COUNT;
+ if ((ms->app_data = kmalloc(sizeof(struct raudio_priv_data),
+ GFP_ATOMIC)) == NULL)
+ printk(KERN_INFO "RealAudio: No memory for application data\n");
+ else
+ {
+ struct raudio_priv_data *priv =
+ (struct raudio_priv_data *)ms->app_data;
+ priv->seen_start = 0;
+ priv->data_conn = NULL;
+ priv->error_conn = NULL;
+ priv->is_rtsp = 0;
+ }
+ return 0;
+}
+
+static int
+masq_raudio_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_DEC_USE_COUNT;
+ if (ms->app_data)
+ kfree_s(ms->app_data, sizeof(struct raudio_priv_data));
+ return 0;
+}
+
+int
+masq_raudio_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ char *p, *data, *data_limit;
+ struct ip_masq *n_ms;
+ unsigned short version, msg_id, msg_len, udp_port;
+ struct raudio_priv_data *priv =
+ (struct raudio_priv_data *)ms->app_data;
+
+ /* Everything running correctly already */
+ if (priv && priv->seen_start)
+ return 0;
+
+ if(priv && priv->is_rtsp)
+ return masq_rtsp_out(mapp, ms, skb_p, maddr);
+
+ skb = *skb_p;
+ iph = skb->nh.iph;
+ th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+ data = (char *)&th[1];
+
+ data_limit = skb->h.raw + skb->len;
+
+ if(memcmp(data, "OPTIONS", 7) == 0 ||
+ memcmp(data, "DESCRIBE", 8) == 0)
+ {
+ IP_MASQ_DEBUG(1-debug, "RealAudio: Detected RTSP connection\n");
+ /* This is an RTSP client */
+ if(priv)
+ priv->is_rtsp = 1;
+ return masq_rtsp_out(mapp, ms, skb_p, maddr);
+ }
+
+ /* Check to see if this is the first packet with protocol ID */
+ if (memcmp(data, "PNA", 3)) {
+ IP_MASQ_DEBUG(1-debug, "RealAudio: not initial protocol packet - ignored\n");
+ return(0);
+ }
+ data += 3;
+ memcpy(&version, data, 2);
+
+ IP_MASQ_DEBUG(1-debug, "RealAudio: initial seen - protocol version %d\n",
+ ntohs(version));
+ if (priv)
+ priv->seen_start = 1;
+
+ if (ntohs(version) >= 256)
+ {
+ printk(KERN_INFO "RealAudio: version (%d) not supported\n",
+ ntohs(version));
+ return 0;
+ }
+
+ data += 2;
+ while (data+4 < data_limit) {
+ memcpy(&msg_id, data, 2);
+ data += 2;
+ memcpy(&msg_len, data, 2);
+ data += 2;
+ if (ntohs(msg_id) == 0) {
+ /* The zero tag indicates the end of options */
+ IP_MASQ_DEBUG(1-debug, "RealAudio: packet end tag seen\n");
+ return 0;
+ }
+ IP_MASQ_DEBUG(1-debug, "RealAudio: msg %d - %d byte\n",
+ ntohs(msg_id), ntohs(msg_len));
+ if (ntohs(msg_id) == 0) {
+ /* The zero tag indicates the end of options */
+ return 0;
+ }
+ p = data;
+ data += ntohs(msg_len);
+ if (data > data_limit)
+ {
+ printk(KERN_INFO "RealAudio: Packet too short for data\n");
+ return 0;
+ }
+ if ((ntohs(msg_id) == 1) || (ntohs(msg_id) == 7)) {
+ /*
+ * MsgId == 1
+ * Audio UDP data port on client
+ *
+ * MsgId == 7
+ * Robust UDP error correction port number on client
+ *
+ * Since these messages are treated just the same, they
+ * are bundled together here....
+ */
+ memcpy(&udp_port, p, 2);
+
+ /*
+ * Sometimes a server sends a message 7 with a zero UDP port
+ * Rather than do anything with this, just ignore it!
+ */
+ if (udp_port == 0)
+ continue;
+
+
+ n_ms = ip_masq_new(IPPROTO_UDP,
+ maddr, 0,
+ ms->saddr, udp_port,
+ ms->daddr, 0,
+ IP_MASQ_F_NO_DPORT);
+
+ if (n_ms==NULL)
+ return 0;
+
+ ip_masq_listen(n_ms);
+ ip_masq_control_add(n_ms, ms);
+
+ memcpy(p, &(n_ms->mport), 2);
+ IP_MASQ_DEBUG(1-debug, "RealAudio: rewrote UDP port %d -> %d in msg %d\n",
+ ntohs(udp_port), ntohs(n_ms->mport), ntohs(msg_id));
+
+ /* Make ref in application data to data connection */
+ if (priv) {
+ if (ntohs(msg_id) == 1)
+ priv->data_conn = n_ms;
+ else
+ priv->error_conn = n_ms;
+ }
+
+ ip_masq_put(n_ms);
+ }
+ }
+ return 0;
+}
+
+/*
+ * masq_rtsp_out
+ *
+ *
+ */
+int
+masq_rtsp_out (struct ip_masq_app *mapp,
+ struct ip_masq *ms,
+ struct sk_buff **skb_p,
+ __u32 maddr)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ char *data, *data_limit;
+ struct ip_masq *n_ms, *n_ms2;
+ unsigned short udp_port;
+ struct raudio_priv_data *priv =
+ (struct raudio_priv_data *)ms->app_data;
+ const char* srch = "transport:";
+ const char* srchpos = srch;
+ const char* srchend = srch + strlen(srch);
+ int state = 0;
+ char firstport[6];
+ int firstportpos = 0;
+ char secondport[6];
+ int secondportpos = 0;
+ char *portstart = NULL, *portend = NULL;
+ int diff;
+
+ /* Everything running correctly already */
+ if (priv && priv->seen_start)
+ return 0;
+
+ skb = *skb_p;
+ iph = skb->nh.iph;
+ th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+ data = (char *)&th[1];
+
+ data_limit = skb->h.raw + skb->len;
+
+ firstport[0] = 0;
+ secondport[0] = 0;
+
+ while(data < data_limit && state >= 0)
+ {
+ switch(state)
+ {
+ case 0:
+ case 1:
+ if(TOLOWER(*data) == *srchpos)
+ {
+ srchpos++;
+ if(srchpos == srchend)
+ {
+ IP_MASQ_DEBUG(1-debug, "Found string %s in message\n",
+ srch);
+ state++;
+ if(state == 1)
+ {
+ srch = "client_port";
+ srchpos = srch;
+ srchend = srch + strlen(srch);
+ }
+ }
+ }
+ else
+ {
+ srchpos = srch;
+ }
+ break;
+ case 2:
+ if(*data == '=')
+ state = 3;
+ break;
+ case 3:
+ if(ISDIGIT(*data))
+ {
+ portstart = data;
+ firstportpos = 0;
+ firstport[firstportpos++] = *data;
+ state = 4;
+ }
+ break;
+ case 4:
+ if(*data == '-')
+ {
+ state = 5;
+ }
+ else if(*data == ';')
+ {
+ portend = data - 1;
+ firstport[firstportpos] = 0;
+ state = -1;
+ }
+ else if(ISDIGIT(*data))
+ {
+ firstport[firstportpos++] = *data;
+ }
+ else if(*data != ' ' && *data != '\t')
+ {
+ /* This is a badly formed RTSP message, let's bail out */
+ IP_MASQ_DEBUG(1-debug, "Badly formed RTSP Message\n");
+ return 0;
+ }
+ break;
+ case 5:
+ if(ISDIGIT(*data))
+ {
+ secondportpos = 0;
+ secondport[secondportpos++] = *data;
+ state = 6;
+ }
+ else if(*data == ';')
+ {
+ portend = data - 1;
+ secondport[secondportpos] = 0;
+ state = -1;
+ }
+ break;
+ case 6:
+ if(*data == ';')
+ {
+ portend = data - 1;
+ secondport[secondportpos] = 0;
+ state = -1;
+ }
+ else if(ISDIGIT(*data))
+ {
+ secondport[secondportpos++] = *data;
+ }
+ else if(*data != ' ' && *data != '\t')
+ {
+ /* This is a badly formed RTSP message, let's bail out */
+ IP_MASQ_DEBUG(1-debug, "Badly formed RTSP Message\n");
+ return 0;
+ }
+ break;
+ }
+ data++;
+ }
+
+ if(state >= 0)
+ return 0;
+
+ if(firstportpos > 0)
+ {
+ char newbuf[12]; /* xxxxx-xxxxx\0 */
+ char* tmpptr;
+
+ udp_port = htons(simple_strtoul(firstport, &tmpptr, 10));
+ n_ms = ip_masq_new(IPPROTO_UDP,
+ maddr, 0,
+ ms->saddr, udp_port,
+ ms->daddr, 0,
+ IP_MASQ_F_NO_DPORT);
+ if (n_ms==NULL)
+ return 0;
+
+ ip_masq_listen(n_ms);
+ ip_masq_control_add(n_ms, ms);
+
+ if(secondportpos > 0)
+ {
+ udp_port = htons(simple_strtoul(secondport, &tmpptr, 10));
+ n_ms2 = ip_masq_new(IPPROTO_UDP,
+ maddr, 0,
+ ms->saddr, udp_port,
+ ms->daddr, 0,
+ IP_MASQ_F_NO_DPORT);
+ if (n_ms2==NULL) {
+ ip_masq_put(n_ms);
+ return 0;
+ }
+
+ ip_masq_listen(n_ms2);
+ ip_masq_control_add(n_ms2, ms);
+ sprintf(newbuf, "%d-%d", ntohs(n_ms->mport),
+ ntohs(n_ms2->mport));
+ }
+ else
+ {
+ sprintf(newbuf, "%d", ntohs(n_ms->mport));
+ n_ms2 = NULL;
+ }
+ *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC,
+ portstart, portend - portstart + 1,
+ newbuf, strlen(newbuf));
+ IP_MASQ_DEBUG(1-debug, "RTSP: rewrote client_port to %s\n", newbuf);
+ diff = strlen(newbuf) - (portend - portstart);
+ }
+ else
+ {
+ return 0;
+ }
+
+ if(priv)
+ {
+ priv->seen_start = 1;
+ if(n_ms)
+ priv->data_conn = n_ms;
+ if(n_ms2)
+ priv->error_conn = n_ms2;
+ }
+ /*
+ * Release tunnels
+ */
+
+ if (n_ms)
+ ip_masq_put(n_ms);
+
+ if (n_ms2)
+ ip_masq_put(n_ms2);
+
+ return diff;
+}
+
+struct ip_masq_app ip_masq_raudio = {
+ NULL, /* next */
+ "RealAudio", /* name */
+ 0, /* type */
+ 0, /* n_attach */
+ masq_raudio_init_1, /* ip_masq_init_1 */
+ masq_raudio_done_1, /* ip_masq_done_1 */
+ masq_raudio_out, /* pkt_out */
+ NULL /* pkt_in */
+};
+
+/*
+ * ip_masq_raudio initialization
+ */
+
+__initfunc(int ip_masq_raudio_init(void))
+{
+ int i, j;
+
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (ports[i]) {
+ if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
+ GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ memcpy(masq_incarnations[i], &ip_masq_raudio, sizeof(struct ip_masq_app));
+ if ((j = register_ip_masq_app(masq_incarnations[i],
+ IPPROTO_TCP,
+ ports[i]))) {
+ return j;
+ }
+ IP_MASQ_DEBUG(1-debug, "RealAudio: loaded support on port[%d] = %d\n",
+ i, ports[i]);
+ } else {
+ /* To be safe, force the incarnation table entry to NULL */
+ masq_incarnations[i] = NULL;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ip_masq_raudio fin.
+ */
+
+int ip_masq_raudio_done(void)
+{
+ int i, j, k;
+
+ k=0;
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (masq_incarnations[i]) {
+ if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
+ k = j;
+ } else {
+ kfree(masq_incarnations[i]);
+ masq_incarnations[i] = NULL;
+ IP_MASQ_DEBUG(1-debug, "RealAudio: unloaded support on port[%d] = %d\n",
+ i, ports[i]);
+ }
+ }
+ }
+ return k;
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_masq_raudio_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_masq_raudio_done() != 0)
+ printk(KERN_INFO "ip_masq_raudio: can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_user.c b/pfinet/linux-src/net/ipv4/ip_masq_user.c
new file mode 100644
index 00000000..51297441
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_user.c
@@ -0,0 +1,473 @@
+/*
+ * IP_MASQ_USER user space control module
+ *
+ *
+ * $Id: ip_masq_user.c,v 1.1.2.1 1999/08/07 10:56:33 davem Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <asm/system.h>
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/inet.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/checksum.h>
+#include <net/ip_masq.h>
+#include <net/ip_masq_mod.h>
+#include <linux/sysctl.h>
+#include <linux/ip_fw.h>
+
+#include <linux/ip_masq.h>
+
+/*
+ * Debug level
+ */
+static int debug=0;
+
+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
+MODULE_PARM(debug, "i");
+
+/*
+static int check_5uple (struct ip_masq_user *ums) {
+ return 0;
+}
+*/
+static void masq_user_k2u(const struct ip_masq *ms, struct ip_masq_user *ums)
+{
+ ums->protocol = ms->protocol;
+ ums->daddr = ms->daddr;
+ ums->dport = ms->dport;
+ ums->maddr = ms->maddr;
+ ums->mport = ms->mport;
+ ums->saddr = ms->saddr;
+ ums->sport = ms->sport;
+ ums->timeout = ms->timeout;
+}
+
+
+static int ip_masq_user_maddr(struct ip_masq_user *ums)
+{
+ struct device *dev;
+ struct rtable *rt;
+ int ret = -EINVAL;
+ u32 rt_daddr, rt_saddr;
+ u32 tos;
+
+ /*
+ * Did specify masq address.
+ */
+ if (ums->maddr)
+ return 0;
+
+ /*
+ * Select address to use for routing query
+ */
+
+ rt_daddr = ums->rt_daddr? ums->rt_daddr : ums->daddr;
+ rt_saddr = ums->rt_saddr? ums->rt_saddr : ums->saddr;
+
+
+ /*
+ * No address for routing, cannot continue
+ */
+ if (rt_daddr == 0) {
+ IP_MASQ_DEBUG(1-debug, "cannot setup maddr with daddr=%lX, rt_addr=%lX\n",
+ ntohl(ums->daddr), ntohl(ums->rt_daddr));
+ return -EINVAL;
+ }
+
+ /*
+ * Find out rt device
+ */
+
+ rt_saddr = 0;
+ tos = RT_TOS(ums->ip_tos) | RTO_CONN;
+
+ if ((ret=ip_route_output(&rt, rt_daddr, rt_saddr, tos, 0 /* dev */))) {
+ IP_MASQ_DEBUG(0-debug, "could not setup maddr for routing daddr=%lX, saddr=%lX\n",
+ ntohl(rt_daddr), ntohl(rt_saddr));
+ return ret;
+ }
+ dev = rt->u.dst.dev;
+ ums->maddr = ip_masq_select_addr(dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+
+ IP_MASQ_DEBUG(1-debug, "did setup maddr=%lX\n", ntohl(ums->maddr));
+ ip_rt_put(rt);
+ return 0;
+}
+
+/*
+ * Create new entry (from uspace)
+ */
+static int ip_masq_user_new(struct ip_masq_user *ums)
+{
+ struct ip_masq *ms = NULL;
+ unsigned mflags = 0;
+ int ret;
+
+ if (masq_proto_num (ums->protocol) == -1) {
+ return EPROTONOSUPPORT;
+ }
+
+ if (ums->dport == 0) {
+ ums->flags |= IP_MASQ_USER_F_LISTEN;
+ }
+
+ if (ums->flags | IP_MASQ_USER_F_LISTEN) {
+ if ((ums->saddr == 0) || (ums->sport == 0)) {
+ return EINVAL;
+ }
+ mflags |= (IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR);
+
+ }
+
+ if ((ret = ip_masq_user_maddr(ums)) < 0) {
+ return -ret;
+ }
+
+ mflags |= IP_MASQ_F_USER;
+ ms = ip_masq_new(ums->protocol,
+ ums->maddr, ums->mport,
+ ums->saddr, ums->sport,
+ ums->daddr, ums->dport,
+ mflags);
+
+ if (ms == NULL) {
+ /*
+ * FIXME: ip_masq_new() should return errno
+ */
+ return EBUSY;
+ }
+
+ /*
+ * Setup timeouts for this new entry
+ */
+
+ if (ums->timeout) {
+ ms->timeout = ums->timeout;
+ } else if (ums->flags | IP_MASQ_USER_F_LISTEN) {
+ ip_masq_listen(ms);
+ }
+
+ masq_user_k2u(ms, ums);
+ ip_masq_put(ms);
+ return 0;
+}
+
+/*
+ * Delete existing entry
+ */
+static int ip_masq_user_del(struct ip_masq_user *ums)
+{
+ struct ip_masq *ms=NULL;
+
+ if (masq_proto_num (ums->protocol) == -1) {
+ return EPROTONOSUPPORT;
+ }
+ start_bh_atomic();
+ if (ums->mport && ums->maddr) {
+ ms = ip_masq_in_get(ums->protocol,
+ ums->daddr, ums->dport,
+ ums->maddr, ums->mport);
+ end_bh_atomic();
+ } else if (ums->sport && ums->saddr) {
+ ms = ip_masq_out_get(ums->protocol,
+ ums->saddr, ums->sport,
+ ums->daddr, ums->dport);
+ end_bh_atomic();
+ } else
+ return EINVAL;
+
+ if (ms == NULL) {
+ return ESRCH;
+ }
+
+ /*
+ * got (locked) entry, setup almost tiny timeout :) and
+ * give away
+ *
+ * FIXME: should use something better than S_CLOSE
+ */
+ ms->timeout = IP_MASQ_S_CLOSE;
+
+ masq_user_k2u(ms, ums);
+ ip_masq_put(ms);
+ return 0;
+}
+
+static struct ip_masq * ip_masq_user_locked_get (struct ip_masq_user *ums, int *err)
+{
+ struct ip_masq *ms=NULL;
+ if (masq_proto_num (ums->protocol) == -1) {
+ *err = EPROTONOSUPPORT;
+ }
+
+ start_bh_atomic();
+ if (ums->mport && ums->maddr) {
+ ms = ip_masq_in_get(ums->protocol,
+ ums->daddr, ums->dport,
+ ums->maddr, ums->mport);
+ end_bh_atomic();
+ } else if (ums->sport && ums->saddr) {
+ ms = ip_masq_out_get(ums->protocol,
+ ums->saddr, ums->sport,
+ ums->daddr, ums->dport);
+ end_bh_atomic();
+ } else
+ *err = EINVAL;
+
+ if (ms == NULL) *err = ESRCH;
+ return ms;
+}
+
+/*
+ * Get existing entry (complete full tunnel info)
+ */
+static int ip_masq_user_get(struct ip_masq_user *ums)
+{
+ struct ip_masq *ms=NULL;
+ int err;
+
+ ms = ip_masq_user_locked_get(ums, &err);
+ if (ms == NULL)
+ return err;
+
+ masq_user_k2u(ms, ums);
+
+ ip_masq_put(ms);
+ return 0;
+}
+
+/*
+ * Set (some, valid) entry parameters
+ */
+static int ip_masq_user_set(struct ip_masq_user *ums)
+{
+ struct ip_masq *ms = NULL;
+ int err;
+
+ ms = ip_masq_user_locked_get(ums, &err);
+ if (ms == NULL)
+ return err;
+
+ /*
+ * FIXME: must allow selecting what you want to set
+ */
+ ms->timeout = ums->timeout;
+
+ masq_user_k2u(ms, ums);
+
+ ip_masq_put(ms);
+ return 0;
+}
+
+
+/*
+ * Entry point
+ * ret value:
+ * <0 err
+ * ==0 ok
+ * >0 ok, copy to user
+ */
+static int ip_masq_user_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
+{
+ struct ip_masq_user *ums = &mctl->u.user;
+ int ret = EINVAL;
+ int arglen = optlen - IP_MASQ_CTL_BSIZE;
+ int cmd;
+
+ IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
+ arglen,
+ sizeof (*ums),
+ optlen,
+ sizeof (*mctl));
+
+ /*
+ * Yes, I'm a bad guy ...
+ */
+ if (arglen != sizeof(*ums) && optlen != sizeof(*mctl))
+ return EINVAL;
+
+ MOD_INC_USE_COUNT;
+
+ /*
+ * Don't trust the lusers - plenty of error checking!
+ */
+ cmd = mctl->m_cmd;
+ IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(cmd=%d)\n", cmd);
+
+ switch (mctl->m_cmd) {
+ case IP_MASQ_CMD_ADD:
+ case IP_MASQ_CMD_INSERT:
+ ret = ip_masq_user_new(ums);
+ break;
+ case IP_MASQ_CMD_DEL:
+ ret = ip_masq_user_del(ums);
+ break;
+ case IP_MASQ_CMD_SET:
+ ret = ip_masq_user_set(ums);
+ break;
+ case IP_MASQ_CMD_GET:
+ ret = ip_masq_user_get(ums);
+ break;
+ }
+
+ /*
+ * For all of the above, return masq tunnel info
+ */
+
+ ret = -ret;
+
+ if (ret == 0) {
+ ret = sizeof (*ums) + IP_MASQ_CTL_BSIZE;
+ IP_MASQ_DEBUG(1-debug, "will return %d bytes to user\n", ret);
+ }
+
+ MOD_DEC_USE_COUNT;
+ return ret;
+}
+
+
+#ifdef CONFIG_PROC_FS
+static int ip_masq_user_info(char *buffer, char **start, off_t offset,
+ int length, int proto)
+{
+ off_t pos=0, begin;
+ struct ip_masq *ms;
+ char temp[129];
+ int idx = 0;
+ int col;
+ int len=0;
+ int magic_control;
+ struct list_head *l,*e;
+
+ MOD_INC_USE_COUNT;
+
+ IP_MASQ_DEBUG(1-debug, "Entered user_info with proto=%d\n", proto);
+
+ if (offset < 128)
+ {
+ sprintf(temp,
+ "Prot SrcIP SPrt DstIP DPrt MAddr MPrt State Flgs Ref Ctl Expires HRow HCol (free=%d,%d,%d)",
+ atomic_read(ip_masq_free_ports),
+ atomic_read(ip_masq_free_ports+1),
+ atomic_read(ip_masq_free_ports+2));
+ len = sprintf(buffer, "%-127s\n", temp);
+ }
+ pos = 128;
+
+ for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
+ {
+ /*
+ * Lock is actually only need in next loop
+ * we are called from uspace: must stop bh.
+ */
+ col=0;
+ read_lock_bh(&__ip_masq_lock);
+ l = &ip_masq_m_table[idx];
+ for (e=l->next; e!=l; e=e->next) {
+ col++;
+ ms = list_entry(e, struct ip_masq, m_list);
+ if (ms->protocol != proto) {
+ continue;
+ }
+
+ pos += 128;
+ if (pos <= offset) {
+ len = 0;
+ continue;
+ }
+
+ /*
+ * We have locked the tables, no need to del/add timers
+ * nor cli() 8)
+ */
+
+
+ magic_control = atomic_read(&ms->n_control);
+ if (!magic_control && ms->control) magic_control = -1;
+ sprintf(temp,"%-4s %08lX:%04X %08lX:%04X %08lX:%04X %-12s %3X %4d %3d %7lu %4d %4d",
+ masq_proto_name(ms->protocol),
+ ntohl(ms->saddr), ntohs(ms->sport),
+ ntohl(ms->daddr), ntohs(ms->dport),
+ ntohl(ms->maddr), ntohs(ms->mport),
+ ip_masq_state_name(ms->state),
+ ms->flags,
+ atomic_read(&ms->refcnt),
+ magic_control,
+ (ms->timer.expires-jiffies)/HZ,
+ idx, col);
+ len += sprintf(buffer+len, "%-127s\n", temp);
+
+ if(len >= length) {
+ read_unlock_bh(&__ip_masq_lock);
+ goto done;
+ }
+ }
+ read_unlock_bh(&__ip_masq_lock);
+ }
+
+done:
+
+ if (len) {
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ }
+ if(len>length)
+ len = length;
+ MOD_DEC_USE_COUNT;
+ return len;
+}
+#else
+#define ip_masq_user_info NULL
+#endif
+
+static struct ip_masq_hook ip_masq_user = {
+ ip_masq_user_ctl,
+ ip_masq_user_info
+};
+
+int ip_masq_user_init(void)
+{
+ if (ip_masq_user_hook != NULL)
+ return -EEXIST;
+ ip_masq_user_hook = &ip_masq_user;
+ return 0;
+}
+
+int ip_masq_user_done(void)
+{
+ if (ip_masq_user_hook == NULL)
+ return ENOENT;
+ ip_masq_user_hook = NULL;
+ return 0;
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+int init_module(void)
+{
+ if (ip_masq_user_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_masq_user_done() != 0)
+ printk(KERN_INFO "ip_masq_user_done(): can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_vdolive.c b/pfinet/linux-src/net/ipv4/ip_masq_vdolive.c
new file mode 100644
index 00000000..4724e3b9
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_masq_vdolive.c
@@ -0,0 +1,294 @@
+/*
+ * IP_MASQ_VDOLIVE - VDO Live masquerading module
+ *
+ *
+ * Version: @(#)$Id: ip_masq_vdolive.c,v 1.4 1998/10/06 04:49:07 davem Exp $
+ *
+ * Author: Nigel Metheringham <Nigel.Metheringham@ThePLAnet.net>
+ * PLAnet Online Ltd
+ *
+ * Fixes: Minor changes for 2.1 by
+ * Steven Clarke <Steven.Clarke@ThePlanet.Net>, Planet Online Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Thanks:
+ * Thank you to VDOnet Corporation for allowing me access to
+ * a protocol description without an NDA. This means that
+ * this module can be distributed as source - a great help!
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/ip_masq.h>
+
+struct vdolive_priv_data {
+ /* Ports used */
+ unsigned short origport;
+ unsigned short masqport;
+ /* State of decode */
+ unsigned short state;
+};
+
+/*
+ * List of ports (up to MAX_MASQ_APP_PORTS) to be handled by helper
+ * First port is set to the default port.
+ */
+static int ports[MAX_MASQ_APP_PORTS] = {7000}; /* I rely on the trailing items being set to zero */
+struct ip_masq_app *masq_incarnations[MAX_MASQ_APP_PORTS];
+
+/*
+ * Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
+
+static int
+masq_vdolive_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_INC_USE_COUNT;
+ if ((ms->app_data = kmalloc(sizeof(struct vdolive_priv_data),
+ GFP_ATOMIC)) == NULL)
+ IP_MASQ_DEBUG(1-debug, "VDOlive: No memory for application data\n");
+ else
+ {
+ struct vdolive_priv_data *priv =
+ (struct vdolive_priv_data *)ms->app_data;
+ priv->origport = 0;
+ priv->masqport = 0;
+ priv->state = 0;
+ }
+ return 0;
+}
+
+static int
+masq_vdolive_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
+{
+ MOD_DEC_USE_COUNT;
+ if (ms->app_data)
+ kfree_s(ms->app_data, sizeof(struct vdolive_priv_data));
+ return 0;
+}
+
+int
+masq_vdolive_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
+{
+ struct sk_buff *skb;
+ struct iphdr *iph;
+ struct tcphdr *th;
+ char *data, *data_limit;
+ unsigned int tagval; /* This should be a 32 bit quantity */
+ struct ip_masq *n_ms;
+ struct vdolive_priv_data *priv =
+ (struct vdolive_priv_data *)ms->app_data;
+
+ /* This doesn't work at all if no priv data was allocated on startup */
+ if (!priv)
+ return 0;
+
+ /* Everything running correctly already */
+ if (priv->state == 3)
+ return 0;
+
+ skb = *skb_p;
+ iph = skb->nh.iph;
+ th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+ data = (char *)&th[1];
+
+ data_limit = skb->h.raw + skb->len;
+
+ if (data+8 > data_limit) {
+ IP_MASQ_DEBUG(1-debug, "VDOlive: packet too short for ID %p %p\n", data, data_limit);
+ return 0;
+ }
+ memcpy(&tagval, data+4, 4);
+ IP_MASQ_DEBUG(1-debug, "VDOlive: packet seen, tag %ld, in initial state %d\n", ntohl(tagval), priv->state);
+
+ /* Check for leading packet ID */
+ if ((ntohl(tagval) != 6) && (ntohl(tagval) != 1)) {
+ IP_MASQ_DEBUG(1-debug, "VDOlive: unrecognised tag %ld, in initial state %d\n", ntohl(tagval), priv->state);
+ return 0;
+ }
+
+
+ /* Check packet is long enough for data - ignore if not */
+ if ((ntohl(tagval) == 6) && (data+36 > data_limit)) {
+ IP_MASQ_DEBUG(1-debug, "VDOlive: initial packet too short %p %p\n", data, data_limit);
+ return 0;
+ } else if ((ntohl(tagval) == 1) && (data+20 > data_limit)) {
+ IP_MASQ_DEBUG(1-debug,"VDOlive: secondary packet too short %p %p\n", data, data_limit);
+ return 0;
+ }
+
+ /* Adjust data pointers */
+ /*
+ * I could check the complete protocol version tag
+ * in here however I am just going to look for the
+ * "VDO Live" tag in the hope that this part will
+ * remain constant even if the version changes
+ */
+ if (ntohl(tagval) == 6) {
+ data += 24;
+ IP_MASQ_DEBUG(1-debug, "VDOlive: initial packet found\n");
+ } else {
+ data += 8;
+ IP_MASQ_DEBUG(1-debug, "VDOlive: secondary packet found\n");
+ }
+
+ if (memcmp(data, "VDO Live", 8) != 0) {
+ IP_MASQ_DEBUG(1-debug,"VDOlive: did not find tag\n");
+ return 0;
+ }
+ /*
+ * The port number is the next word after the tag.
+ * VDOlive encodes all of these values
+ * in 32 bit words, so in this case I am
+ * skipping the first 2 bytes of the next
+ * word to get to the relevant 16 bits
+ */
+ data += 10;
+
+ /*
+ * If we have not seen the port already,
+ * set the masquerading tunnel up
+ */
+ if (!priv->origport) {
+ memcpy(&priv->origport, data, 2);
+ IP_MASQ_DEBUG(1-debug, "VDOlive: found port %d\n", ntohs(priv->origport));
+
+ /* Open up a tunnel */
+ n_ms = ip_masq_new(IPPROTO_UDP,
+ maddr, 0,
+ ms->saddr, priv->origport,
+ ms->daddr, 0,
+ IP_MASQ_F_NO_DPORT);
+
+ if (n_ms==NULL) {
+ ip_masq_put(n_ms);
+ IP_MASQ_DEBUG(1-debug, "VDOlive: unable to build UDP tunnel for %x:%x\n", ms->saddr, priv->origport);
+ /* Leave state as unset */
+ priv->origport = 0;
+ return 0;
+ }
+ ip_masq_listen(n_ms);
+
+ ip_masq_put(ms);
+ priv->masqport = n_ms->mport;
+ } else if (memcmp(data, &(priv->origport), 2)) {
+ IP_MASQ_DEBUG(1-debug, "VDOlive: ports do not match\n");
+ /* Write the port in anyhow!!! */
+ }
+
+ /*
+ * Write masq port into packet
+ */
+ memcpy(data, &(priv->masqport), 2);
+ IP_MASQ_DEBUG(1-debug, "VDOlive: rewrote port %d to %d, server %08X\n", ntohs(priv->origport), ntohs(priv->masqport), ms->saddr);
+
+ /*
+ * Set state bit to make which bit has been done
+ */
+
+ priv->state |= (ntohl(tagval) == 6) ? 1 : 2;
+
+ return 0;
+}
+
+
+struct ip_masq_app ip_masq_vdolive = {
+ NULL, /* next */
+ "VDOlive", /* name */
+ 0, /* type */
+ 0, /* n_attach */
+ masq_vdolive_init_1, /* ip_masq_init_1 */
+ masq_vdolive_done_1, /* ip_masq_done_1 */
+ masq_vdolive_out, /* pkt_out */
+ NULL /* pkt_in */
+};
+
+/*
+ * ip_masq_vdolive initialization
+ */
+
+__initfunc(int ip_masq_vdolive_init(void))
+{
+ int i, j;
+
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (ports[i]) {
+ if ((masq_incarnations[i] = kmalloc(sizeof(struct ip_masq_app),
+ GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+ memcpy(masq_incarnations[i], &ip_masq_vdolive, sizeof(struct ip_masq_app));
+ if ((j = register_ip_masq_app(masq_incarnations[i],
+ IPPROTO_TCP,
+ ports[i]))) {
+ return j;
+ }
+ IP_MASQ_DEBUG(1-debug, "RealAudio: loaded support on port[%d] = %d\n", i, ports[i]);
+ } else {
+ /* To be safe, force the incarnation table entry to NULL */
+ masq_incarnations[i] = NULL;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ip_masq_vdolive fin.
+ */
+
+int ip_masq_vdolive_done(void)
+{
+ int i, j, k;
+
+ k=0;
+ for (i=0; (i<MAX_MASQ_APP_PORTS); i++) {
+ if (masq_incarnations[i]) {
+ if ((j = unregister_ip_masq_app(masq_incarnations[i]))) {
+ k = j;
+ } else {
+ kfree(masq_incarnations[i]);
+ masq_incarnations[i] = NULL;
+ IP_MASQ_DEBUG(1-debug,"VDOlive: unloaded support on port[%d] = %d\n", i, ports[i]);
+ }
+ }
+ }
+ return k;
+}
+
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if (ip_masq_vdolive_init() != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (ip_masq_vdolive_done() != 0)
+ IP_MASQ_DEBUG(1-debug, "ip_masq_vdolive: can't remove module");
+}
+
+#endif /* MODULE */
diff --git a/pfinet/linux-src/net/ipv4/ip_nat_dumb.c b/pfinet/linux-src/net/ipv4/ip_nat_dumb.c
new file mode 100644
index 00000000..5a1c6d75
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_nat_dumb.c
@@ -0,0 +1,158 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Dumb Network Address Translation.
+ *
+ * Version: $Id: ip_nat_dumb.c,v 1.8 1999/03/21 05:22:40 davem Exp $
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ * Rani Assaf : A zero checksum is a special case
+ * only in UDP
+ * Rani Assaf : Added ICMP messages rewriting
+ * Rani Assaf : Repaired wrong changes, made by ANK.
+ *
+ *
+ * NOTE: It is just working model of real NAT.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/icmp.h>
+#include <linux/netdevice.h>
+#include <net/sock.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/firewall.h>
+#include <linux/ip_fw.h>
+#include <net/checksum.h>
+#include <linux/route.h>
+#include <net/route.h>
+#include <net/ip_fib.h>
+
+
+int
+ip_do_nat(struct sk_buff *skb)
+{
+ struct rtable *rt = (struct rtable*)skb->dst;
+ struct iphdr *iph = skb->nh.iph;
+ u32 odaddr = iph->daddr;
+ u32 osaddr = iph->saddr;
+ u16 check;
+
+ IPCB(skb)->flags |= IPSKB_TRANSLATED;
+
+ /* Rewrite IP header */
+ iph->daddr = rt->rt_dst_map;
+ iph->saddr = rt->rt_src_map;
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+ /* If it is the first fragment, rewrite protocol headers */
+
+ if (!(iph->frag_off & htons(IP_OFFSET))) {
+ u16 *cksum;
+
+ switch(iph->protocol) {
+ case IPPROTO_TCP:
+ cksum = (u16*)&((struct tcphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
+ if ((u8*)(cksum+1) > skb->tail)
+ goto truncated;
+ check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, ~(*cksum));
+ *cksum = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
+ break;
+ case IPPROTO_UDP:
+ cksum = (u16*)&((struct udphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
+ if ((u8*)(cksum+1) > skb->tail)
+ goto truncated;
+ if ((check = *cksum) != 0) {
+ check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, ~check);
+ check = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
+ *cksum = check ? : 0xFFFF;
+ }
+ break;
+ case IPPROTO_ICMP:
+ {
+ struct icmphdr *icmph = (struct icmphdr*)((char*)iph + (iph->ihl<<2));
+ struct iphdr *ciph;
+ u32 idaddr, isaddr;
+ int updated;
+
+ if ((icmph->type != ICMP_DEST_UNREACH) &&
+ (icmph->type != ICMP_TIME_EXCEEDED) &&
+ (icmph->type != ICMP_PARAMETERPROB))
+ break;
+
+ ciph = (struct iphdr *) (icmph + 1);
+
+ if ((u8*)(ciph+1) > skb->tail)
+ goto truncated;
+
+ isaddr = ciph->saddr;
+ idaddr = ciph->daddr;
+ updated = 0;
+
+ if (rt->rt_flags&RTCF_DNAT && ciph->saddr == odaddr) {
+ ciph->saddr = iph->daddr;
+ updated = 1;
+ }
+ if (rt->rt_flags&RTCF_SNAT) {
+ if (ciph->daddr != osaddr) {
+ struct fib_result res;
+ struct rt_key key;
+ unsigned flags = 0;
+
+ key.src = ciph->daddr;
+ key.dst = ciph->saddr;
+ key.iif = skb->dev->ifindex;
+ key.oif = 0;
+#ifdef CONFIG_IP_ROUTE_TOS
+ key.tos = RT_TOS(ciph->tos);
+#endif
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ key.fwmark = 0;
+#endif
+ /* Use fib_lookup() until we get our own
+ * hash table of NATed hosts -- Rani
+ */
+ if (fib_lookup(&key, &res) == 0 && res.r) {
+ ciph->daddr = fib_rules_policy(ciph->daddr, &res, &flags);
+ if (ciph->daddr != idaddr)
+ updated = 1;
+ }
+ } else {
+ ciph->daddr = iph->saddr;
+ updated = 1;
+ }
+ }
+ if (updated) {
+ cksum = &icmph->checksum;
+ /* Using tcpudp primitive. Why not? */
+ check = csum_tcpudp_magic(ciph->saddr, ciph->daddr, 0, 0, ~(*cksum));
+ *cksum = csum_tcpudp_magic(~isaddr, ~idaddr, 0, 0, ~check);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return 0;
+
+truncated:
+ return -EINVAL;
+}
diff --git a/pfinet/linux-src/net/ipv4/ip_options.c b/pfinet/linux-src/net/ipv4/ip_options.c
new file mode 100644
index 00000000..a3d1f0aa
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_options.c
@@ -0,0 +1,617 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * The options processing module for ip.c
+ *
+ * Version: $Id: ip_options.c,v 1.16.2.1 1999/06/02 04:06:19 davem Exp $
+ *
+ * Authors: A.N.Kuznetsov
+ *
+ */
+
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/icmp.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <net/sock.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+
+/*
+ * Write options to IP header, record destination address to
+ * source route option, address of outgoing interface
+ * (we should already know it, so that this function is allowed be
+ * called only after routing decision) and timestamp,
+ * if we originate this datagram.
+ *
+ * daddr is real destination address, next hop is recorded in IP header.
+ * saddr is address of outgoing interface.
+ */
+
+void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
+ u32 daddr, struct rtable *rt, int is_frag)
+{
+ unsigned char * iph = skb->nh.raw;
+
+ memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options));
+ memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen);
+ opt = &(IPCB(skb)->opt);
+ opt->is_data = 0;
+
+ if (opt->srr)
+ memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4);
+
+ if (!is_frag) {
+ if (opt->rr_needaddr)
+ ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, rt);
+ if (opt->ts_needaddr)
+ ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt);
+ if (opt->ts_needtime) {
+ struct timeval tv;
+ __u32 midtime;
+ do_gettimeofday(&tv);
+ midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
+ memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
+ }
+ return;
+ }
+ if (opt->rr) {
+ memset(iph+opt->rr, IPOPT_NOP, iph[opt->rr+1]);
+ opt->rr = 0;
+ opt->rr_needaddr = 0;
+ }
+ if (opt->ts) {
+ memset(iph+opt->ts, IPOPT_NOP, iph[opt->ts+1]);
+ opt->ts = 0;
+ opt->ts_needaddr = opt->ts_needtime = 0;
+ }
+}
+
+/*
+ * Provided (sopt, skb) points to received options,
+ * build in dopt compiled option set appropriate for answering.
+ * i.e. invert SRR option, copy anothers,
+ * and grab room in RR/TS options.
+ *
+ * NOTE: dopt cannot point to skb.
+ */
+
+int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
+{
+ struct ip_options *sopt;
+ unsigned char *sptr, *dptr;
+ int soffset, doffset;
+ int optlen;
+ u32 daddr;
+
+ memset(dopt, 0, sizeof(struct ip_options));
+
+ dopt->is_data = 1;
+
+ sopt = &(IPCB(skb)->opt);
+
+ if (sopt->optlen == 0) {
+ dopt->optlen = 0;
+ return 0;
+ }
+
+ sptr = skb->nh.raw;
+ dptr = dopt->__data;
+
+ if (skb->dst)
+ daddr = ((struct rtable*)skb->dst)->rt_spec_dst;
+ else
+ daddr = skb->nh.iph->daddr;
+
+ if (sopt->rr) {
+ optlen = sptr[sopt->rr+1];
+ soffset = sptr[sopt->rr+2];
+ dopt->rr = dopt->optlen + sizeof(struct iphdr);
+ memcpy(dptr, sptr+sopt->rr, optlen);
+ if (sopt->rr_needaddr && soffset <= optlen) {
+ if (soffset + 3 > optlen)
+ return -EINVAL;
+ dptr[2] = soffset + 4;
+ dopt->rr_needaddr = 1;
+ }
+ dptr += optlen;
+ dopt->optlen += optlen;
+ }
+ if (sopt->ts) {
+ optlen = sptr[sopt->ts+1];
+ soffset = sptr[sopt->ts+2];
+ dopt->ts = dopt->optlen + sizeof(struct iphdr);
+ memcpy(dptr, sptr+sopt->ts, optlen);
+ if (soffset <= optlen) {
+ if (sopt->ts_needaddr) {
+ if (soffset + 3 > optlen)
+ return -EINVAL;
+ dopt->ts_needaddr = 1;
+ soffset += 4;
+ }
+ if (sopt->ts_needtime) {
+ if (soffset + 3 > optlen)
+ return -EINVAL;
+ if ((dptr[3]&0xF) != IPOPT_TS_PRESPEC) {
+ dopt->ts_needtime = 1;
+ soffset += 4;
+ } else {
+ dopt->ts_needtime = 0;
+
+ if (soffset + 8 <= optlen) {
+ __u32 addr;
+
+ memcpy(&addr, sptr+soffset-1, 4);
+ if (inet_addr_type(addr) != RTN_LOCAL) {
+ dopt->ts_needtime = 1;
+ soffset += 8;
+ }
+ }
+ }
+ }
+ dptr[2] = soffset;
+ }
+ dptr += optlen;
+ dopt->optlen += optlen;
+ }
+ if (sopt->srr) {
+ unsigned char * start = sptr+sopt->srr;
+ u32 faddr;
+
+ optlen = start[1];
+ soffset = start[2];
+ doffset = 0;
+ if (soffset > optlen)
+ soffset = optlen + 1;
+ soffset -= 4;
+ if (soffset > 3) {
+ memcpy(&faddr, &start[soffset-1], 4);
+ for (soffset-=4, doffset=4; soffset > 3; soffset-=4, doffset+=4)
+ memcpy(&dptr[doffset-1], &start[soffset-1], 4);
+ /*
+ * RFC1812 requires to fix illegal source routes.
+ */
+ if (memcmp(&skb->nh.iph->saddr, &start[soffset+3], 4) == 0)
+ doffset -= 4;
+ }
+ if (doffset > 3) {
+ memcpy(&start[doffset-1], &daddr, 4);
+ dopt->faddr = faddr;
+ dptr[0] = start[0];
+ dptr[1] = doffset+3;
+ dptr[2] = 4;
+ dptr += doffset+3;
+ dopt->srr = dopt->optlen + sizeof(struct iphdr);
+ dopt->optlen += doffset+3;
+ dopt->is_strictroute = sopt->is_strictroute;
+ }
+ }
+ while (dopt->optlen & 3) {
+ *dptr++ = IPOPT_END;
+ dopt->optlen++;
+ }
+ return 0;
+}
+
+/*
+ * Options "fragmenting", just fill options not
+ * allowed in fragments with NOOPs.
+ * Simple and stupid 8), but the most efficient way.
+ */
+
+void ip_options_fragment(struct sk_buff * skb)
+{
+ unsigned char * optptr = skb->nh.raw;
+ struct ip_options * opt = &(IPCB(skb)->opt);
+ int l = opt->optlen;
+ int optlen;
+
+ while (l > 0) {
+ switch (*optptr) {
+ case IPOPT_END:
+ return;
+ case IPOPT_NOOP:
+ l--;
+ optptr++;
+ continue;
+ }
+ optlen = optptr[1];
+ if (optlen<2 || optlen>l)
+ return;
+ if (!IPOPT_COPIED(*optptr))
+ memset(optptr, IPOPT_NOOP, optlen);
+ l -= optlen;
+ optptr += optlen;
+ }
+ opt->ts = 0;
+ opt->rr = 0;
+ opt->rr_needaddr = 0;
+ opt->ts_needaddr = 0;
+ opt->ts_needtime = 0;
+ return;
+}
+
+/*
+ * Verify options and fill pointers in struct options.
+ * Caller should clear *opt, and set opt->data.
+ * If opt == NULL, then skb->data should point to IP header.
+ */
+
+int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
+{
+ int l;
+ unsigned char * iph;
+ unsigned char * optptr;
+ int optlen;
+ unsigned char * pp_ptr = NULL;
+ struct rtable *rt = skb ? (struct rtable*)skb->dst : NULL;
+
+ if (!opt) {
+ opt = &(IPCB(skb)->opt);
+ memset(opt, 0, sizeof(struct ip_options));
+ iph = skb->nh.raw;
+ opt->optlen = ((struct iphdr *)iph)->ihl*4 - sizeof(struct iphdr);
+ optptr = iph + sizeof(struct iphdr);
+ opt->is_data = 0;
+ } else {
+ optptr = opt->is_data ? opt->__data : (unsigned char*)&(skb->nh.iph[1]);
+ iph = optptr - sizeof(struct iphdr);
+ }
+
+ for (l = opt->optlen; l > 0; ) {
+ switch (*optptr) {
+ case IPOPT_END:
+ for (optptr++, l--; l>0; l--) {
+ if (*optptr != IPOPT_END) {
+ *optptr = IPOPT_END;
+ opt->is_changed = 1;
+ }
+ }
+ goto eol;
+ case IPOPT_NOOP:
+ l--;
+ optptr++;
+ continue;
+ }
+ optlen = optptr[1];
+ if (optlen<2 || optlen>l) {
+ pp_ptr = optptr;
+ goto error;
+ }
+ switch (*optptr) {
+ case IPOPT_SSRR:
+ case IPOPT_LSRR:
+ if (optlen < 3) {
+ pp_ptr = optptr + 1;
+ goto error;
+ }
+ if (optptr[2] < 4) {
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+ /* NB: cf RFC-1812 5.2.4.1 */
+ if (opt->srr) {
+ pp_ptr = optptr;
+ goto error;
+ }
+ if (!skb) {
+ if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) {
+ pp_ptr = optptr + 1;
+ goto error;
+ }
+ memcpy(&opt->faddr, &optptr[3], 4);
+ if (optlen > 7)
+ memmove(&optptr[3], &optptr[7], optlen-7);
+ }
+ opt->is_strictroute = (optptr[0] == IPOPT_SSRR);
+ opt->srr = optptr - iph;
+ break;
+ case IPOPT_RR:
+ if (opt->rr) {
+ pp_ptr = optptr;
+ goto error;
+ }
+ if (optlen < 3) {
+ pp_ptr = optptr + 1;
+ goto error;
+ }
+ if (optptr[2] < 4) {
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+ if (optptr[2] <= optlen) {
+ if (optptr[2]+3 > optlen) {
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+ if (skb) {
+ memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
+ opt->is_changed = 1;
+ }
+ optptr[2] += 4;
+ opt->rr_needaddr = 1;
+ }
+ opt->rr = optptr - iph;
+ break;
+ case IPOPT_TIMESTAMP:
+ if (opt->ts) {
+ pp_ptr = optptr;
+ goto error;
+ }
+ if (optlen < 4) {
+ pp_ptr = optptr + 1;
+ goto error;
+ }
+ if (optptr[2] < 5) {
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+ if (optptr[2] <= optlen) {
+ __u32 * timeptr = NULL;
+ if (optptr[2]+3 > optptr[1]) {
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+ switch (optptr[3]&0xF) {
+ case IPOPT_TS_TSONLY:
+ opt->ts = optptr - iph;
+ if (skb)
+ timeptr = (__u32*)&optptr[optptr[2]-1];
+ opt->ts_needtime = 1;
+ optptr[2] += 4;
+ break;
+ case IPOPT_TS_TSANDADDR:
+ if (optptr[2]+7 > optptr[1]) {
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+ opt->ts = optptr - iph;
+ if (skb) {
+ memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
+ timeptr = (__u32*)&optptr[optptr[2]+3];
+ }
+ opt->ts_needaddr = 1;
+ opt->ts_needtime = 1;
+ optptr[2] += 8;
+ break;
+ case IPOPT_TS_PRESPEC:
+ if (optptr[2]+7 > optptr[1]) {
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+ opt->ts = optptr - iph;
+ {
+ u32 addr;
+ memcpy(&addr, &optptr[optptr[2]-1], 4);
+ if (inet_addr_type(addr) == RTN_UNICAST)
+ break;
+ if (skb)
+ timeptr = (__u32*)&optptr[optptr[2]+3];
+ }
+ opt->ts_needtime = 1;
+ optptr[2] += 8;
+ break;
+ default:
+ if (!skb && !capable(CAP_NET_RAW)) {
+ pp_ptr = optptr + 3;
+ goto error;
+ }
+ break;
+ }
+ if (timeptr) {
+ struct timeval tv;
+ __u32 midtime;
+ do_gettimeofday(&tv);
+ midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
+ memcpy(timeptr, &midtime, sizeof(__u32));
+ opt->is_changed = 1;
+ }
+ } else {
+ unsigned overflow = optptr[3]>>4;
+ if (overflow == 15) {
+ pp_ptr = optptr + 3;
+ goto error;
+ }
+ opt->ts = optptr - iph;
+ if (skb) {
+ optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
+ opt->is_changed = 1;
+ }
+ }
+ break;
+ case IPOPT_RA:
+ if (optlen < 4) {
+ pp_ptr = optptr + 1;
+ goto error;
+ }
+ if (optptr[2] == 0 && optptr[3] == 0)
+ opt->router_alert = optptr - iph;
+ break;
+ case IPOPT_SEC:
+ case IPOPT_SID:
+ default:
+ if (!skb && !capable(CAP_NET_RAW)) {
+ pp_ptr = optptr;
+ goto error;
+ }
+ break;
+ }
+ l -= optlen;
+ optptr += optlen;
+ }
+
+eol:
+ if (!pp_ptr)
+ return 0;
+
+error:
+ if (skb) {
+ icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
+ }
+ return -EINVAL;
+}
+
+
+/*
+ * Undo all the changes done by ip_options_compile().
+ */
+
+void ip_options_undo(struct ip_options * opt)
+{
+ if (opt->srr) {
+ unsigned char * optptr = opt->__data+opt->srr-sizeof(struct iphdr);
+ memmove(optptr+7, optptr+3, optptr[1]-7);
+ memcpy(optptr+3, &opt->faddr, 4);
+ }
+ if (opt->rr_needaddr) {
+ unsigned char * optptr = opt->__data+opt->rr-sizeof(struct iphdr);
+ optptr[2] -= 4;
+ memset(&optptr[optptr[2]-1], 0, 4);
+ }
+ if (opt->ts) {
+ unsigned char * optptr = opt->__data+opt->ts-sizeof(struct iphdr);
+ if (opt->ts_needtime) {
+ optptr[2] -= 4;
+ memset(&optptr[optptr[2]-1], 0, 4);
+ if ((optptr[3]&0xF) == IPOPT_TS_PRESPEC)
+ optptr[2] -= 4;
+ }
+ if (opt->ts_needaddr) {
+ optptr[2] -= 4;
+ memset(&optptr[optptr[2]-1], 0, 4);
+ }
+ }
+}
+
+int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen, int user)
+{
+ struct ip_options *opt;
+
+ opt = kmalloc(sizeof(struct ip_options)+((optlen+3)&~3), GFP_KERNEL);
+ if (!opt)
+ return -ENOMEM;
+ memset(opt, 0, sizeof(struct ip_options));
+ if (optlen) {
+ if (user) {
+ if (copy_from_user(opt->__data, data, optlen))
+ return -EFAULT;
+ } else
+ memcpy(opt->__data, data, optlen);
+ }
+ while (optlen & 3)
+ opt->__data[optlen++] = IPOPT_END;
+ opt->optlen = optlen;
+ opt->is_data = 1;
+ opt->is_setbyuser = 1;
+ if (optlen && ip_options_compile(opt, NULL)) {
+ kfree_s(opt, sizeof(struct ip_options) + optlen);
+ return -EINVAL;
+ }
+ *optp = opt;
+ return 0;
+}
+
+void ip_forward_options(struct sk_buff *skb)
+{
+ struct ip_options * opt = &(IPCB(skb)->opt);
+ unsigned char * optptr;
+ struct rtable *rt = (struct rtable*)skb->dst;
+ unsigned char *raw = skb->nh.raw;
+
+ if (opt->rr_needaddr) {
+ optptr = (unsigned char *)raw + opt->rr;
+ ip_rt_get_source(&optptr[optptr[2]-5], rt);
+ opt->is_changed = 1;
+ }
+ if (opt->srr_is_hit) {
+ int srrptr, srrspace;
+
+ optptr = raw + opt->srr;
+
+ for ( srrptr=optptr[2], srrspace = optptr[1];
+ srrptr <= srrspace;
+ srrptr += 4
+ ) {
+ if (srrptr + 3 > srrspace)
+ break;
+ if (memcmp(&rt->rt_dst, &optptr[srrptr-1], 4) == 0)
+ break;
+ }
+ if (srrptr + 3 <= srrspace) {
+ opt->is_changed = 1;
+ ip_rt_get_source(&optptr[srrptr-1], rt);
+ skb->nh.iph->daddr = rt->rt_dst;
+ optptr[2] = srrptr+4;
+ } else
+ printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");
+ if (opt->ts_needaddr) {
+ optptr = raw + opt->ts;
+ ip_rt_get_source(&optptr[optptr[2]-9], rt);
+ opt->is_changed = 1;
+ }
+ }
+ if (opt->is_changed) {
+ opt->is_changed = 0;
+ ip_send_check(skb->nh.iph);
+ }
+}
+
+int ip_options_rcv_srr(struct sk_buff *skb)
+{
+ struct ip_options *opt = &(IPCB(skb)->opt);
+ int srrspace, srrptr;
+ u32 nexthop;
+ struct iphdr *iph = skb->nh.iph;
+ unsigned char * optptr = skb->nh.raw + opt->srr;
+ struct rtable *rt = (struct rtable*)skb->dst;
+ struct rtable *rt2;
+ int err;
+
+ if (!opt->srr)
+ return 0;
+
+ if (skb->pkt_type != PACKET_HOST)
+ return -EINVAL;
+ if (rt->rt_type == RTN_UNICAST) {
+ if (!opt->is_strictroute)
+ return 0;
+ icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl(16<<24));
+ return -EINVAL;
+ }
+ if (rt->rt_type != RTN_LOCAL)
+ return -EINVAL;
+
+ for (srrptr=optptr[2], srrspace = optptr[1]; srrptr <= srrspace; srrptr += 4) {
+ if (srrptr + 3 > srrspace) {
+ icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((opt->srr+2)<<24));
+ return -EINVAL;
+ }
+ memcpy(&nexthop, &optptr[srrptr-1], 4);
+
+ rt = (struct rtable*)skb->dst;
+ skb->dst = NULL;
+ err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev);
+ rt2 = (struct rtable*)skb->dst;
+ if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {
+ ip_rt_put(rt2);
+ skb->dst = &rt->u.dst;
+ return -EINVAL;
+ }
+ ip_rt_put(rt);
+ if (rt2->rt_type != RTN_LOCAL)
+ break;
+ /* Superfast 8) loopback forward */
+ memcpy(&iph->daddr, &optptr[srrptr-1], 4);
+ opt->is_changed = 1;
+ }
+ if (srrptr <= srrspace) {
+ opt->srr_is_hit = 1;
+ opt->is_changed = 1;
+ }
+ return 0;
+}
diff --git a/pfinet/linux-src/net/ipv4/ip_output.c b/pfinet/linux-src/net/ipv4/ip_output.c
new file mode 100644
index 00000000..44d63557
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_output.c
@@ -0,0 +1,992 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * The Internet Protocol (IP) output module.
+ *
+ * Version: $Id: ip_output.c,v 1.67 1999/03/25 00:43:00 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Donald Becker, <becker@super.org>
+ * Alan Cox, <Alan.Cox@linux.org>
+ * Richard Underwood
+ * Stefan Becker, <stefanb@yello.ping.de>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *
+ * See ip_input.c for original log
+ *
+ * Fixes:
+ * Alan Cox : Missing nonblock feature in ip_build_xmit.
+ * Mike Kilburn : htons() missing in ip_build_xmit.
+ * Bradford Johnson: Fix faulty handling of some frames when
+ * no route is found.
+ * Alexander Demenshin: Missing sk/skb free in ip_queue_xmit
+ * (in case if packet not accepted by
+ * output firewall rules)
+ * Mike McLagan : Routing by source
+ * Alexey Kuznetsov: use new route cache
+ * Andi Kleen: Fix broken PMTU recovery and remove
+ * some redundant tests.
+ * Vitaly E. Lavrov : Transparent proxy revived after year coma.
+ * Andi Kleen : Replace ip_reply with ip_send_reply.
+ * Andi Kleen : Split fast and slow ip_build_xmit path
+ * for decreased register pressure on x86
+ * and more readibility.
+ * Marc Boucher : When call_out_firewall returns FW_QUEUE,
+ * silently drop skb instead of failing with -EPERM.
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/arp.h>
+#include <net/icmp.h>
+#include <net/raw.h>
+#include <net/checksum.h>
+#include <linux/igmp.h>
+#include <linux/ip_fw.h>
+#include <linux/firewall.h>
+#include <linux/mroute.h>
+#include <linux/netlink.h>
+
+/*
+ * Shall we try to damage output packets if routing dev changes?
+ */
+
+int sysctl_ip_dynaddr = 0;
+
+
+int ip_id_count = 0;
+
+/* Generate a checksum for an outgoing IP datagram. */
+__inline__ void ip_send_check(struct iphdr *iph)
+{
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+}
+
+/*
+ * Add an ip header to a skbuff and send it out.
+ */
+void ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
+ u32 saddr, u32 daddr, struct ip_options *opt)
+{
+ struct rtable *rt = (struct rtable *)skb->dst;
+ struct iphdr *iph;
+ struct device *dev;
+
+ /* Build the IP header. */
+ if (opt)
+ iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr) + opt->optlen);
+ else
+ iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr));
+
+ iph->version = 4;
+ iph->ihl = 5;
+ iph->tos = sk->ip_tos;
+ iph->frag_off = 0;
+ if (ip_dont_fragment(sk, &rt->u.dst))
+ iph->frag_off |= htons(IP_DF);
+ iph->ttl = sk->ip_ttl;
+ iph->daddr = rt->rt_dst;
+ iph->saddr = rt->rt_src;
+ iph->protocol = sk->protocol;
+ iph->tot_len = htons(skb->len);
+ iph->id = htons(ip_id_count++);
+ skb->nh.iph = iph;
+
+ if (opt && opt->optlen) {
+ iph->ihl += opt->optlen>>2;
+ ip_options_build(skb, opt, daddr, rt, 0);
+ }
+
+ dev = rt->u.dst.dev;
+
+#ifdef CONFIG_FIREWALL
+ /* Now we have no better mechanism to notify about error. */
+ switch (call_out_firewall(PF_INET, dev, iph, NULL, &skb)) {
+ case FW_REJECT:
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+ /* Fall thru... */
+ case FW_BLOCK:
+ case FW_QUEUE:
+ kfree_skb(skb);
+ return;
+ }
+#endif
+
+ ip_send_check(iph);
+
+ /* Send it out. */
+ skb->dst->output(skb);
+ return;
+}
+
+int __ip_finish_output(struct sk_buff *skb)
+{
+ return ip_finish_output(skb);
+}
+
+int ip_mc_output(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+ struct rtable *rt = (struct rtable*)skb->dst;
+ struct device *dev = rt->u.dst.dev;
+
+ /*
+ * If the indicated interface is up and running, send the packet.
+ */
+
+ ip_statistics.IpOutRequests++;
+#ifdef CONFIG_IP_ROUTE_NAT
+ if (rt->rt_flags & RTCF_NAT)
+ ip_do_nat(skb);
+#endif
+
+ skb->dev = dev;
+ skb->protocol = __constant_htons(ETH_P_IP);
+
+ /*
+ * Multicasts are looped back for other local users
+ */
+
+ if (rt->rt_flags&RTCF_MULTICAST && (!sk || sk->ip_mc_loop)) {
+#ifdef CONFIG_IP_MROUTE
+ /* Small optimization: do not loopback not local frames,
+ which returned after forwarding; they will be dropped
+ by ip_mr_input in any case.
+ Note, that local frames are looped back to be delivered
+ to local recipients.
+
+ This check is duplicated in ip_mr_input at the moment.
+ */
+ if ((rt->rt_flags&RTCF_LOCAL) || !(IPCB(skb)->flags&IPSKB_FORWARDED))
+#endif
+ dev_loopback_xmit(skb);
+
+ /* Multicasts with ttl 0 must not go beyond the host */
+
+ if (skb->nh.iph->ttl == 0) {
+ kfree_skb(skb);
+ return 0;
+ }
+ }
+
+ if (rt->rt_flags&RTCF_BROADCAST)
+ dev_loopback_xmit(skb);
+
+ return ip_finish_output(skb);
+}
+
+int ip_output(struct sk_buff *skb)
+{
+#ifdef CONFIG_IP_ROUTE_NAT
+ struct rtable *rt = (struct rtable*)skb->dst;
+#endif
+
+ ip_statistics.IpOutRequests++;
+
+#ifdef CONFIG_IP_ROUTE_NAT
+ if (rt->rt_flags&RTCF_NAT)
+ ip_do_nat(skb);
+#endif
+
+ return ip_finish_output(skb);
+}
+
+/* Queues a packet to be sent, and starts the transmitter if necessary.
+ * This routine also needs to put in the total length and compute the
+ * checksum. We use to do this in two stages, ip_build_header() then
+ * this, but that scheme created a mess when routes disappeared etc.
+ * So we do it all here, and the TCP send engine has been changed to
+ * match. (No more unroutable FIN disasters, etc. wheee...) This will
+ * most likely make other reliable transport layers above IP easier
+ * to implement under Linux.
+ */
+void ip_queue_xmit(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+ struct ip_options *opt = sk->opt;
+ struct rtable *rt;
+ struct device *dev;
+ struct iphdr *iph;
+ unsigned int tot_len;
+
+ /* Make sure we can route this packet. */
+ rt = (struct rtable *) sk->dst_cache;
+ if(rt == NULL || rt->u.dst.obsolete) {
+ u32 daddr;
+
+ sk->dst_cache = NULL;
+ ip_rt_put(rt);
+
+ /* Use correct destination address if we have options. */
+ daddr = sk->daddr;
+ if(opt && opt->srr)
+ daddr = opt->faddr;
+
+ /* If this fails, retransmit mechanism of transport layer will
+ * keep trying until route appears or the connection times itself
+ * out.
+ */
+ if(ip_route_output(&rt, daddr, sk->saddr,
+ RT_TOS(sk->ip_tos) | RTO_CONN | sk->localroute,
+ sk->bound_dev_if))
+ goto drop;
+ sk->dst_cache = &rt->u.dst;
+ }
+ if(opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
+ goto no_route;
+
+ /* We have a route, so grab a reference. */
+ skb->dst = dst_clone(sk->dst_cache);
+
+ /* OK, we know where to send it, allocate and build IP header. */
+ iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0));
+ iph->version = 4;
+ iph->ihl = 5;
+ iph->tos = sk->ip_tos;
+ iph->frag_off = 0;
+ iph->ttl = sk->ip_ttl;
+ iph->daddr = rt->rt_dst;
+ iph->saddr = rt->rt_src;
+ iph->protocol = sk->protocol;
+ skb->nh.iph = iph;
+ /* Transport layer set skb->h.foo itself. */
+
+ if(opt && opt->optlen) {
+ iph->ihl += opt->optlen >> 2;
+ ip_options_build(skb, opt, sk->daddr, rt, 0);
+ }
+
+ tot_len = skb->len;
+ iph->tot_len = htons(tot_len);
+ iph->id = htons(ip_id_count++);
+
+ dev = rt->u.dst.dev;
+
+#ifdef CONFIG_FIREWALL
+ /* Now we have no better mechanism to notify about error. */
+ switch (call_out_firewall(PF_INET, dev, iph, NULL, &skb)) {
+ case FW_REJECT:
+ start_bh_atomic();
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+ end_bh_atomic();
+ /* Fall thru... */
+ case FW_BLOCK:
+ case FW_QUEUE:
+ goto drop;
+ }
+#endif
+
+ /* This can happen when the transport layer has segments queued
+ * with a cached route, and by the time we get here things are
+ * re-routed to a device with a different MTU than the original
+ * device. Sick, but we must cover it.
+ */
+ if (skb_headroom(skb) < dev->hard_header_len && dev->hard_header) {
+ struct sk_buff *skb2;
+
+ skb2 = skb_realloc_headroom(skb, (dev->hard_header_len + 15) & ~15);
+ kfree_skb(skb);
+ if (skb2 == NULL)
+ return;
+ if (sk)
+ skb_set_owner_w(skb, sk);
+ skb = skb2;
+ iph = skb->nh.iph;
+ }
+
+ /* Do we need to fragment. Again this is inefficient. We
+ * need to somehow lock the original buffer and use bits of it.
+ */
+ if (tot_len > rt->u.dst.pmtu)
+ goto fragment;
+
+ if (ip_dont_fragment(sk, &rt->u.dst))
+ iph->frag_off |= __constant_htons(IP_DF);
+
+ /* Add an IP checksum. */
+ ip_send_check(iph);
+
+ skb->priority = sk->priority;
+ skb->dst->output(skb);
+ return;
+
+fragment:
+ if (ip_dont_fragment(sk, &rt->u.dst) &&
+ tot_len > (iph->ihl<<2) + sizeof(struct tcphdr)+16) {
+ /* Reject packet ONLY if TCP might fragment
+ it itself, if were careful enough.
+ Test is not precise (f.e. it does not take sacks
+ into account). Actually, tcp should make it. --ANK (980801)
+ */
+ iph->frag_off |= __constant_htons(IP_DF);
+ NETDEBUG(printk(KERN_DEBUG "sending pkt_too_big to self\n"));
+
+ /* icmp_send is not reenterable, so that bh_atomic... --ANK */
+ start_bh_atomic();
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+ htonl(rt->u.dst.pmtu));
+ end_bh_atomic();
+ goto drop;
+ }
+ ip_fragment(skb, skb->dst->output);
+ return;
+
+no_route:
+ sk->dst_cache = NULL;
+ ip_rt_put(rt);
+ ip_statistics.IpOutNoRoutes++;
+ /* Fall through... */
+drop:
+ kfree_skb(skb);
+}
+
+/*
+ * Build and send a packet, with as little as one copy
+ *
+ * Doesn't care much about ip options... option length can be
+ * different for fragment at 0 and other fragments.
+ *
+ * Note that the fragment at the highest offset is sent first,
+ * so the getfrag routine can fill in the TCP/UDP checksum header
+ * field in the last fragment it sends... actually it also helps
+ * the reassemblers, they can put most packets in at the head of
+ * the fragment queue, and they know the total size in advance. This
+ * last feature will measurably improve the Linux fragment handler one
+ * day.
+ *
+ * The callback has five args, an arbitrary pointer (copy of frag),
+ * the source IP address (may depend on the routing table), the
+ * destination address (char *), the offset to copy from, and the
+ * length to be copied.
+ */
+
+int ip_build_xmit_slow(struct sock *sk,
+ int getfrag (const void *,
+ char *,
+ unsigned int,
+ unsigned int),
+ const void *frag,
+ unsigned length,
+ struct ipcm_cookie *ipc,
+ struct rtable *rt,
+ int flags)
+{
+ unsigned int fraglen, maxfraglen, fragheaderlen;
+ int err;
+ int offset, mf;
+ int mtu;
+ unsigned short id;
+
+ int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
+ int nfrags=0;
+ struct ip_options *opt = ipc->opt;
+ int df = 0;
+
+ mtu = rt->u.dst.pmtu;
+ if (ip_dont_fragment(sk, &rt->u.dst))
+ df = htons(IP_DF);
+
+ length -= sizeof(struct iphdr);
+
+ if (opt) {
+ fragheaderlen = sizeof(struct iphdr) + opt->optlen;
+ maxfraglen = ((mtu-sizeof(struct iphdr)-opt->optlen) & ~7) + fragheaderlen;
+ } else {
+ fragheaderlen = sizeof(struct iphdr);
+
+ /*
+ * Fragheaderlen is the size of 'overhead' on each buffer. Now work
+ * out the size of the frames to send.
+ */
+
+ maxfraglen = ((mtu-sizeof(struct iphdr)) & ~7) + fragheaderlen;
+ }
+
+ if (length + fragheaderlen > 0xFFFF) {
+ ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, mtu);
+ return -EMSGSIZE;
+ }
+
+ /*
+ * Start at the end of the frame by handling the remainder.
+ */
+
+ offset = length - (length % (maxfraglen - fragheaderlen));
+
+ /*
+ * Amount of memory to allocate for final fragment.
+ */
+
+ fraglen = length - offset + fragheaderlen;
+
+ if (length-offset==0) {
+ fraglen = maxfraglen;
+ offset -= maxfraglen-fragheaderlen;
+ }
+
+
+ /*
+ * The last fragment will not have MF (more fragments) set.
+ */
+
+ mf = 0;
+
+ /*
+ * Don't fragment packets for path mtu discovery.
+ */
+
+ if (offset > 0 && df) {
+ ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, mtu);
+ return(-EMSGSIZE);
+ }
+
+ /*
+ * Lock the device lists.
+ */
+
+ dev_lock_list();
+
+ /*
+ * Get an identifier
+ */
+
+ id = htons(ip_id_count++);
+
+ /*
+ * Begin outputting the bytes.
+ */
+
+ do {
+ char *data;
+ struct sk_buff * skb;
+
+ /*
+ * Get the memory we require with some space left for alignment.
+ */
+
+ skb = sock_alloc_send_skb(sk, fraglen+hh_len+15, 0, flags&MSG_DONTWAIT, &err);
+ if (skb == NULL)
+ goto error;
+
+ /*
+ * Fill in the control structures
+ */
+
+ skb->priority = sk->priority;
+ skb->dst = dst_clone(&rt->u.dst);
+ skb_reserve(skb, hh_len);
+
+ /*
+ * Find where to start putting bytes.
+ */
+
+ data = skb_put(skb, fraglen);
+ skb->nh.iph = (struct iphdr *)data;
+
+ /*
+ * Only write IP header onto non-raw packets
+ */
+
+ {
+ struct iphdr *iph = (struct iphdr *)data;
+
+ iph->version = 4;
+ iph->ihl = 5;
+ if (opt) {
+ iph->ihl += opt->optlen>>2;
+ ip_options_build(skb, opt,
+ ipc->addr, rt, offset);
+ }
+ iph->tos = sk->ip_tos;
+ iph->tot_len = htons(fraglen - fragheaderlen + iph->ihl*4);
+ iph->id = id;
+ iph->frag_off = htons(offset>>3);
+ iph->frag_off |= mf|df;
+ if (rt->rt_type == RTN_MULTICAST)
+ iph->ttl = sk->ip_mc_ttl;
+ else
+ iph->ttl = sk->ip_ttl;
+ iph->protocol = sk->protocol;
+ iph->check = 0;
+ iph->saddr = rt->rt_src;
+ iph->daddr = rt->rt_dst;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ data += iph->ihl*4;
+
+ /*
+ * Any further fragments will have MF set.
+ */
+
+ mf = htons(IP_MF);
+ }
+
+ /*
+ * User data callback
+ */
+
+ if (getfrag(frag, data, offset, fraglen-fragheaderlen)) {
+ err = -EFAULT;
+ kfree_skb(skb);
+ goto error;
+ }
+
+ offset -= (maxfraglen-fragheaderlen);
+ fraglen = maxfraglen;
+
+ nfrags++;
+
+#ifdef CONFIG_FIREWALL
+ switch (call_out_firewall(PF_INET, rt->u.dst.dev, skb->nh.iph, NULL, &skb)) {
+ case FW_QUEUE:
+ kfree_skb(skb);
+ continue;
+ case FW_BLOCK:
+ case FW_REJECT:
+ kfree_skb(skb);
+ err = -EPERM;
+ goto error;
+ }
+#endif
+
+ err = -ENETDOWN;
+ if (rt->u.dst.output(skb))
+ goto error;
+ } while (offset >= 0);
+
+ if (nfrags>1)
+ ip_statistics.IpFragCreates += nfrags;
+ dev_unlock_list();
+ return 0;
+
+error:
+ ip_statistics.IpOutDiscards++;
+ if (nfrags>1)
+ ip_statistics.IpFragCreates += nfrags;
+ dev_unlock_list();
+ return err;
+}
+
+
+/*
+ * Fast path for unfragmented packets.
+ */
+int ip_build_xmit(struct sock *sk,
+ int getfrag (const void *,
+ char *,
+ unsigned int,
+ unsigned int),
+ const void *frag,
+ unsigned length,
+ struct ipcm_cookie *ipc,
+ struct rtable *rt,
+ int flags)
+{
+ int err;
+ struct sk_buff *skb;
+ int df;
+ struct iphdr *iph;
+
+ /*
+ * Try the simple case first. This leaves fragmented frames, and by
+ * choice RAW frames within 20 bytes of maximum size(rare) to the long path
+ */
+
+ if (!sk->ip_hdrincl) {
+ length += sizeof(struct iphdr);
+
+ /*
+ * Check for slow path.
+ */
+ if (length > rt->u.dst.pmtu || ipc->opt != NULL)
+ return ip_build_xmit_slow(sk,getfrag,frag,length,ipc,rt,flags);
+ } else {
+ if (length > rt->u.dst.dev->mtu) {
+ ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, rt->u.dst.dev->mtu);
+ return -EMSGSIZE;
+ }
+ }
+
+ /*
+ * Do path mtu discovery if needed.
+ */
+ df = 0;
+ if (ip_dont_fragment(sk, &rt->u.dst))
+ df = htons(IP_DF);
+
+ /*
+ * Fast path for unfragmented frames without options.
+ */
+ {
+ int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
+
+ skb = sock_alloc_send_skb(sk, length+hh_len+15,
+ 0, flags&MSG_DONTWAIT, &err);
+ if(skb==NULL)
+ goto error;
+ skb_reserve(skb, hh_len);
+ }
+
+ skb->priority = sk->priority;
+ skb->dst = dst_clone(&rt->u.dst);
+
+ skb->nh.iph = iph = (struct iphdr *)skb_put(skb, length);
+
+ dev_lock_list();
+
+ if(!sk->ip_hdrincl) {
+ iph->version=4;
+ iph->ihl=5;
+ iph->tos=sk->ip_tos;
+ iph->tot_len = htons(length);
+ iph->id=htons(ip_id_count++);
+ iph->frag_off = df;
+ iph->ttl=sk->ip_mc_ttl;
+ if (rt->rt_type != RTN_MULTICAST)
+ iph->ttl=sk->ip_ttl;
+ iph->protocol=sk->protocol;
+ iph->saddr=rt->rt_src;
+ iph->daddr=rt->rt_dst;
+ iph->check=0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ err = getfrag(frag, ((char *)iph)+iph->ihl*4,0, length-iph->ihl*4);
+ }
+ else
+ err = getfrag(frag, (void *)iph, 0, length);
+
+ dev_unlock_list();
+
+ if (err)
+ goto error_fault;
+
+#ifdef CONFIG_FIREWALL
+ switch (call_out_firewall(PF_INET, rt->u.dst.dev, iph, NULL, &skb)) {
+ case FW_QUEUE:
+ kfree_skb(skb);
+ return 0;
+ case FW_BLOCK:
+ case FW_REJECT:
+ kfree_skb(skb);
+ err = -EPERM;
+ goto error;
+ }
+#endif
+
+ return rt->u.dst.output(skb);
+
+error_fault:
+ err = -EFAULT;
+ kfree_skb(skb);
+error:
+ ip_statistics.IpOutDiscards++;
+ return err;
+}
+
+
+
+/*
+ * This IP datagram is too large to be sent in one piece. Break it up into
+ * smaller pieces (each of size equal to IP header plus
+ * a block of the data of the original IP data part) that will yet fit in a
+ * single device frame, and queue such a frame for sending.
+ *
+ * Yes this is inefficient, feel free to submit a quicker one.
+ */
+
+void ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+{
+ struct iphdr *iph;
+ unsigned char *raw;
+ unsigned char *ptr;
+ struct device *dev;
+ struct sk_buff *skb2;
+ unsigned int mtu, hlen, left, len;
+ int offset;
+ int not_last_frag;
+ struct rtable *rt = (struct rtable*)skb->dst;
+
+ dev = rt->u.dst.dev;
+
+ /*
+ * Point into the IP datagram header.
+ */
+
+ raw = skb->nh.raw;
+ iph = (struct iphdr*)raw;
+
+ /*
+ * Setup starting values.
+ */
+
+ hlen = iph->ihl * 4;
+ left = ntohs(iph->tot_len) - hlen; /* Space per frame */
+ mtu = rt->u.dst.pmtu - hlen; /* Size of data space */
+ ptr = raw + hlen; /* Where to start from */
+
+ /*
+ * The protocol doesn't seem to say what to do in the case that the
+ * frame + options doesn't fit the mtu. As it used to fall down dead
+ * in this case we were fortunate it didn't happen
+ *
+ * It is impossible, because mtu>=68. --ANK (980801)
+ */
+
+#ifdef CONFIG_NET_PARANOIA
+ if (mtu<8)
+ goto fail;
+#endif
+
+ /*
+ * Fragment the datagram.
+ */
+
+ offset = (ntohs(iph->frag_off) & IP_OFFSET) << 3;
+ not_last_frag = iph->frag_off & htons(IP_MF);
+
+ /*
+ * Keep copying data until we run out.
+ */
+
+ while(left > 0) {
+ len = left;
+ /* IF: it doesn't fit, use 'mtu' - the data space left */
+ if (len > mtu)
+ len = mtu;
+ /* IF: we are not sending upto and including the packet end
+ then align the next start on an eight byte boundary */
+ if (len < left) {
+ len &= ~7;
+ }
+ /*
+ * Allocate buffer.
+ */
+
+ if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15,GFP_ATOMIC)) == NULL) {
+ NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
+ goto fail;
+ }
+
+ /*
+ * Set up data on packet
+ */
+
+ skb2->pkt_type = skb->pkt_type;
+ skb2->priority = skb->priority;
+ skb_reserve(skb2, (dev->hard_header_len+15)&~15);
+ skb_put(skb2, len + hlen);
+ skb2->nh.raw = skb2->data;
+ skb2->h.raw = skb2->data + hlen;
+
+ /*
+ * Charge the memory for the fragment to any owner
+ * it might possess
+ */
+
+ if (skb->sk)
+ skb_set_owner_w(skb2, skb->sk);
+ skb2->dst = dst_clone(skb->dst);
+
+ /*
+ * Copy the packet header into the new buffer.
+ */
+
+ memcpy(skb2->nh.raw, raw, hlen);
+
+ /*
+ * Copy a block of the IP datagram.
+ */
+ memcpy(skb2->h.raw, ptr, len);
+ left -= len;
+
+ /*
+ * Fill in the new header fields.
+ */
+ iph = skb2->nh.iph;
+ iph->frag_off = htons((offset >> 3));
+
+ /* ANK: dirty, but effective trick. Upgrade options only if
+ * the segment to be fragmented was THE FIRST (otherwise,
+ * options are already fixed) and make it ONCE
+ * on the initial skb, so that all the following fragments
+ * will inherit fixed options.
+ */
+ if (offset == 0)
+ ip_options_fragment(skb);
+
+ /*
+ * Added AC : If we are fragmenting a fragment that's not the
+ * last fragment then keep MF on each bit
+ */
+ if (left > 0 || not_last_frag)
+ iph->frag_off |= htons(IP_MF);
+ ptr += len;
+ offset += len;
+
+ /*
+ * Put this fragment into the sending queue.
+ */
+
+ ip_statistics.IpFragCreates++;
+
+ iph->tot_len = htons(len + hlen);
+
+ ip_send_check(iph);
+
+ output(skb2);
+ }
+ kfree_skb(skb);
+ ip_statistics.IpFragOKs++;
+ return;
+
+fail:
+ kfree_skb(skb);
+ ip_statistics.IpFragFails++;
+}
+
+/*
+ * Fetch data from kernel space and fill in checksum if needed.
+ */
+static int ip_reply_glue_bits(const void *dptr, char *to, unsigned int offset,
+ unsigned int fraglen)
+{
+ struct ip_reply_arg *dp = (struct ip_reply_arg*)dptr;
+ u16 *pktp = (u16 *)to;
+ struct iovec *iov;
+ int len;
+ int hdrflag = 1;
+
+ iov = &dp->iov[0];
+ if (offset >= iov->iov_len) {
+ offset -= iov->iov_len;
+ iov++;
+ hdrflag = 0;
+ }
+ len = iov->iov_len - offset;
+ if (fraglen > len) { /* overlapping. */
+ dp->csum = csum_partial_copy_nocheck(iov->iov_base+offset, to, len,
+ dp->csum);
+ offset = 0;
+ fraglen -= len;
+ to += len;
+ iov++;
+ }
+
+ dp->csum = csum_partial_copy_nocheck(iov->iov_base+offset, to, fraglen,
+ dp->csum);
+
+ if (hdrflag && dp->csumoffset)
+ *(pktp + dp->csumoffset) = csum_fold(dp->csum); /* fill in checksum */
+ return 0;
+}
+
+/*
+ * Generic function to send a packet as reply to another packet.
+ * Used to send TCP resets so far. ICMP should use this function too.
+ *
+ * Should run single threaded per socket because it uses the sock
+ * structure to pass arguments.
+ */
+void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
+ unsigned int len)
+{
+ struct {
+ struct ip_options opt;
+ char data[40];
+ } replyopts;
+ struct ipcm_cookie ipc;
+ u32 daddr;
+ struct rtable *rt = (struct rtable*)skb->dst;
+
+ if (ip_options_echo(&replyopts.opt, skb))
+ return;
+
+ sk->ip_tos = skb->nh.iph->tos;
+ sk->priority = skb->priority;
+ sk->protocol = skb->nh.iph->protocol;
+
+ daddr = ipc.addr = rt->rt_src;
+ ipc.opt = &replyopts.opt;
+
+ if (ipc.opt->srr)
+ daddr = replyopts.opt.faddr;
+ if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0))
+ return;
+
+ /* And let IP do all the hard work. */
+ ip_build_xmit(sk, ip_reply_glue_bits, arg, len, &ipc, rt, MSG_DONTWAIT);
+ ip_rt_put(rt);
+}
+
+/*
+ * IP protocol layer initialiser
+ */
+
+static struct packet_type ip_packet_type =
+{
+ __constant_htons(ETH_P_IP),
+ NULL, /* All devices */
+ ip_rcv,
+ NULL,
+ NULL,
+};
+
+
+
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IP_MULTICAST
+static struct proc_dir_entry proc_net_igmp = {
+ PROC_NET_IGMP, 4, "igmp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_mc_procinfo
+};
+#endif
+#endif
+
+/*
+ * IP registers the packet type and then calls the subprotocol initialisers
+ */
+
+__initfunc(void ip_init(void))
+{
+ dev_add_pack(&ip_packet_type);
+
+ ip_rt_init();
+
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IP_MULTICAST
+ proc_net_register(&proc_net_igmp);
+#endif
+#endif
+}
+
diff --git a/pfinet/linux-src/net/ipv4/ip_sockglue.c b/pfinet/linux-src/net/ipv4/ip_sockglue.c
new file mode 100644
index 00000000..369a6770
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ip_sockglue.c
@@ -0,0 +1,739 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * The IP to API glue.
+ *
+ * Version: $Id: ip_sockglue.c,v 1.42 1999/04/22 10:07:34 davem Exp $
+ *
+ * Authors: see ip.c
+ *
+ * Fixes:
+ * Many : Split from ip.c , see ip.c for history.
+ * Martin Mares : TOS setting fixed.
+ * Alan Cox : Fixed a couple of oopses in Martin's
+ * TOS tweaks.
+ * Mike McLagan : Routing by source
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/icmp.h>
+#include <linux/netdevice.h>
+#include <net/sock.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/igmp.h>
+#include <linux/firewall.h>
+#include <linux/ip_fw.h>
+#include <linux/route.h>
+#include <linux/mroute.h>
+#include <net/route.h>
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#include <net/transp_v6.h>
+#endif
+
+#ifdef CONFIG_IP_MASQUERADE
+#include <linux/ip_masq.h>
+#endif
+
+#include <linux/errqueue.h>
+#include <asm/uaccess.h>
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+#define IP_CMSG_PKTINFO 1
+#define IP_CMSG_TTL 2
+#define IP_CMSG_TOS 4
+#define IP_CMSG_RECVOPTS 8
+#define IP_CMSG_RETOPTS 16
+
+/*
+ * SOL_IP control messages.
+ */
+
+static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
+{
+ struct in_pktinfo info;
+ struct rtable *rt = (struct rtable *)skb->dst;
+
+ info.ipi_addr.s_addr = skb->nh.iph->daddr;
+ if (rt) {
+ info.ipi_ifindex = rt->rt_iif;
+ info.ipi_spec_dst.s_addr = rt->rt_spec_dst;
+ } else {
+ info.ipi_ifindex = 0;
+ info.ipi_spec_dst.s_addr = 0;
+ }
+
+ put_cmsg(msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
+}
+
+static void ip_cmsg_recv_ttl(struct msghdr *msg, struct sk_buff *skb)
+{
+ int ttl = skb->nh.iph->ttl;
+ put_cmsg(msg, SOL_IP, IP_TTL, sizeof(int), &ttl);
+}
+
+static void ip_cmsg_recv_tos(struct msghdr *msg, struct sk_buff *skb)
+{
+ put_cmsg(msg, SOL_IP, IP_TOS, 1, &skb->nh.iph->tos);
+}
+
+static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb)
+{
+ if (IPCB(skb)->opt.optlen == 0)
+ return;
+
+ put_cmsg(msg, SOL_IP, IP_RECVOPTS, IPCB(skb)->opt.optlen, skb->nh.iph+1);
+}
+
+
+void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
+{
+ unsigned char optbuf[sizeof(struct ip_options) + 40];
+ struct ip_options * opt = (struct ip_options*)optbuf;
+
+ if (IPCB(skb)->opt.optlen == 0)
+ return;
+
+ if (ip_options_echo(opt, skb)) {
+ msg->msg_flags |= MSG_CTRUNC;
+ return;
+ }
+ ip_options_undo(opt);
+
+ put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
+}
+
+
+void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
+{
+ unsigned flags = skb->sk->ip_cmsg_flags;
+
+ /* Ordered by supposed usage frequency */
+ if (flags & 1)
+ ip_cmsg_recv_pktinfo(msg, skb);
+ if ((flags>>=1) == 0)
+ return;
+
+ if (flags & 1)
+ ip_cmsg_recv_ttl(msg, skb);
+ if ((flags>>=1) == 0)
+ return;
+
+ if (flags & 1)
+ ip_cmsg_recv_tos(msg, skb);
+ if ((flags>>=1) == 0)
+ return;
+
+ if (flags & 1)
+ ip_cmsg_recv_opts(msg, skb);
+ if ((flags>>=1) == 0)
+ return;
+
+ if (flags & 1)
+ ip_cmsg_recv_retopts(msg, skb);
+}
+
+int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
+{
+ int err;
+ struct cmsghdr *cmsg;
+
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
+ (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ + cmsg->cmsg_len) > msg->msg_controllen) {
+ return -EINVAL;
+ }
+ if (cmsg->cmsg_level != SOL_IP)
+ continue;
+ switch (cmsg->cmsg_type) {
+ case IP_RETOPTS:
+ err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
+ err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40, 0);
+ if (err)
+ return err;
+ break;
+ case IP_PKTINFO:
+ {
+ struct in_pktinfo *info;
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo)))
+ return -EINVAL;
+ info = (struct in_pktinfo *)CMSG_DATA(cmsg);
+ ipc->oif = info->ipi_ifindex;
+ ipc->addr = info->ipi_spec_dst.s_addr;
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+
+/* Special input handler for packets catched by router alert option.
+ They are selected only by protocol field, and then processed likely
+ local ones; but only if someone wants them! Otherwise, router
+ not running rsvpd will kill RSVP.
+
+ It is user level problem, what it will make with them.
+ I have no idea, how it will masquearde or NAT them (it is joke, joke :-)),
+ but receiver should be enough clever f.e. to forward mtrace requests,
+ sent to multicast group to reach destination designated router.
+ */
+struct ip_ra_chain *ip_ra_chain;
+
+int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *))
+{
+ struct ip_ra_chain *ra, *new_ra, **rap;
+
+ if (sk->type != SOCK_RAW || sk->num == IPPROTO_RAW)
+ return -EINVAL;
+
+ new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
+
+ for (rap = &ip_ra_chain; (ra=*rap) != NULL; rap = &ra->next) {
+ if (ra->sk == sk) {
+ if (on) {
+ if (new_ra)
+ kfree(new_ra);
+ return -EADDRINUSE;
+ }
+ *rap = ra->next;
+ synchronize_bh();
+
+ if (ra->destructor)
+ ra->destructor(sk);
+ kfree(ra);
+ return 0;
+ }
+ }
+ if (new_ra == NULL)
+ return -ENOBUFS;
+ new_ra->sk = sk;
+ new_ra->destructor = destructor;
+
+ new_ra->next = ra;
+ wmb();
+ *rap = new_ra;
+
+ return 0;
+}
+
+void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
+ u16 port, u32 info, u8 *payload)
+{
+ struct sock_exterr_skb *serr;
+
+ if (!sk->ip_recverr)
+ return;
+
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (!skb)
+ return;
+
+ serr = SKB_EXT_ERR(skb);
+ serr->ee.ee_errno = err;
+ serr->ee.ee_origin = SO_EE_ORIGIN_ICMP;
+ serr->ee.ee_type = skb->h.icmph->type;
+ serr->ee.ee_code = skb->h.icmph->code;
+ serr->ee.ee_pad = 0;
+ serr->ee.ee_info = info;
+ serr->ee.ee_data = 0;
+ serr->addr_offset = (u8*)&(((struct iphdr*)(skb->h.icmph+1))->daddr) - skb->nh.raw;
+ serr->port = port;
+
+ skb->h.raw = payload;
+ skb_pull(skb, payload - skb->data);
+
+ if (sock_queue_err_skb(sk, skb))
+ kfree_skb(skb);
+}
+
+void ip_local_error(struct sock *sk, int err, u32 daddr, u16 port, u32 info)
+{
+ struct sock_exterr_skb *serr;
+ struct iphdr *iph;
+ struct sk_buff *skb;
+
+ if (!sk->ip_recverr)
+ return;
+
+ skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC);
+ if (!skb)
+ return;
+
+ iph = (struct iphdr*)skb_put(skb, sizeof(struct iphdr));
+ skb->nh.iph = iph;
+ iph->daddr = daddr;
+
+ serr = SKB_EXT_ERR(skb);
+ serr->ee.ee_errno = err;
+ serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
+ serr->ee.ee_type = 0;
+ serr->ee.ee_code = 0;
+ serr->ee.ee_pad = 0;
+ serr->ee.ee_info = info;
+ serr->ee.ee_data = 0;
+ serr->addr_offset = (u8*)&iph->daddr - skb->nh.raw;
+ serr->port = port;
+
+ skb->h.raw = skb->tail;
+ skb_pull(skb, skb->tail - skb->data);
+
+ if (sock_queue_err_skb(sk, skb))
+ kfree_skb(skb);
+}
+
+/*
+ * Handle MSG_ERRQUEUE
+ */
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
+{
+ struct sock_exterr_skb *serr;
+ struct sk_buff *skb, *skb2;
+ struct sockaddr_in *sin;
+ struct {
+ struct sock_extended_err ee;
+ struct sockaddr_in offender;
+ } errhdr;
+ int err;
+ int copied;
+
+ err = -EAGAIN;
+ skb = skb_dequeue(&sk->error_queue);
+ if (skb == NULL)
+ goto out;
+
+ copied = skb->len;
+ if (copied > len) {
+ msg->msg_flags |= MSG_TRUNC;
+ copied = len;
+ }
+ err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
+ if (err)
+ goto out_free_skb;
+
+ serr = SKB_EXT_ERR(skb);
+
+ sin = (struct sockaddr_in *)msg->msg_name;
+ if (sin) {
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = *(u32*)(skb->nh.raw + serr->addr_offset);
+ sin->sin_port = serr->port;
+ }
+
+ memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
+ sin = &errhdr.offender;
+ sin->sin_family = AF_UNSPEC;
+ if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) {
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = skb->nh.iph->saddr;
+ if (sk->ip_cmsg_flags)
+ ip_cmsg_recv(msg, skb);
+ }
+
+ put_cmsg(msg, SOL_IP, IP_RECVERR, sizeof(errhdr), &errhdr);
+
+ /* Now we could try to dump offended packet options */
+
+ msg->msg_flags |= MSG_ERRQUEUE;
+ err = copied;
+
+ /* Reset and regenerate socket error */
+ sk->err = 0;
+ if ((skb2 = skb_peek(&sk->error_queue)) != NULL) {
+ sk->err = SKB_EXT_ERR(skb2)->ee.ee_errno;
+ sk->error_report(sk);
+ }
+
+out_free_skb:
+ kfree_skb(skb);
+out:
+ return err;
+}
+
+
+/*
+ * Socket option code for IP. This is the end of the line after any TCP,UDP etc options on
+ * an IP socket.
+ *
+ * We implement IP_TOS (type of service), IP_TTL (time to live).
+ */
+
+int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
+{
+ int val=0,err;
+#if defined(CONFIG_IP_FIREWALL)
+ char tmp_fw[MAX(sizeof(struct ip_fwtest),sizeof(struct ip_fwnew))];
+#endif
+ if(optlen>=sizeof(int)) {
+ if(get_user(val, (int *) optval))
+ return -EFAULT;
+ } else if(optlen>=sizeof(char)) {
+ unsigned char ucval;
+ if(get_user(ucval, (unsigned char *) optval))
+ return -EFAULT;
+ val = (int)ucval;
+ }
+ /* If optlen==0, it is equivalent to val == 0 */
+
+ if(level!=SOL_IP)
+ return -ENOPROTOOPT;
+#ifdef CONFIG_IP_MROUTE
+ if(optname>=MRT_BASE && optname <=MRT_BASE+10)
+ {
+ return ip_mroute_setsockopt(sk,optname,optval,optlen);
+ }
+#endif
+
+ switch(optname)
+ {
+ case IP_OPTIONS:
+ {
+ struct ip_options * opt = NULL;
+ if (optlen > 40 || optlen < 0)
+ return -EINVAL;
+ err = ip_options_get(&opt, optval, optlen, 1);
+ if (err)
+ return err;
+ lock_sock(sk);
+ if (sk->type == SOCK_STREAM) {
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ if (sk->family == PF_INET ||
+ ((tcp_connected(sk->state) || sk->state == TCP_SYN_SENT)
+ && sk->daddr != LOOPBACK4_IPV6)) {
+#endif
+ if (opt)
+ tp->ext_header_len = opt->optlen;
+ tcp_sync_mss(sk, tp->pmtu_cookie);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ }
+#endif
+ }
+ opt = xchg(&sk->opt, opt);
+ release_sock(sk);
+ if (opt)
+ kfree_s(opt, sizeof(struct ip_options) + opt->optlen);
+ return 0;
+ }
+ case IP_PKTINFO:
+ if (val)
+ sk->ip_cmsg_flags |= IP_CMSG_PKTINFO;
+ else
+ sk->ip_cmsg_flags &= ~IP_CMSG_PKTINFO;
+ return 0;
+ case IP_RECVTTL:
+ if (val)
+ sk->ip_cmsg_flags |= IP_CMSG_TTL;
+ else
+ sk->ip_cmsg_flags &= ~IP_CMSG_TTL;
+ return 0;
+ case IP_RECVTOS:
+ if (val)
+ sk->ip_cmsg_flags |= IP_CMSG_TOS;
+ else
+ sk->ip_cmsg_flags &= ~IP_CMSG_TOS;
+ return 0;
+ case IP_RECVOPTS:
+ if (val)
+ sk->ip_cmsg_flags |= IP_CMSG_RECVOPTS;
+ else
+ sk->ip_cmsg_flags &= ~IP_CMSG_RECVOPTS;
+ return 0;
+ case IP_RETOPTS:
+ if (val)
+ sk->ip_cmsg_flags |= IP_CMSG_RETOPTS;
+ else
+ sk->ip_cmsg_flags &= ~IP_CMSG_RETOPTS;
+ return 0;
+ case IP_TOS: /* This sets both TOS and Precedence */
+ /* Reject setting of unused bits */
+ if (val & ~(IPTOS_TOS_MASK|IPTOS_PREC_MASK))
+ return -EINVAL;
+ if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP &&
+ !capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (sk->ip_tos != val) {
+ lock_sock(sk);
+ sk->ip_tos=val;
+ sk->priority = rt_tos2priority(val);
+ dst_release(xchg(&sk->dst_cache, NULL));
+ release_sock(sk);
+ }
+ return 0;
+ case IP_TTL:
+ if (optlen<1)
+ return -EINVAL;
+ if(val==-1)
+ val = ip_statistics.IpDefaultTTL;
+ if(val<1||val>255)
+ return -EINVAL;
+ sk->ip_ttl=val;
+ return 0;
+ case IP_HDRINCL:
+ if(sk->type!=SOCK_RAW)
+ return -ENOPROTOOPT;
+ sk->ip_hdrincl=val?1:0;
+ return 0;
+ case IP_MTU_DISCOVER:
+ if (val<0 || val>2)
+ return -EINVAL;
+ sk->ip_pmtudisc = val;
+ return 0;
+ case IP_RECVERR:
+ sk->ip_recverr = !!val;
+ if (!val)
+ skb_queue_purge(&sk->error_queue);
+ return 0;
+ case IP_MULTICAST_TTL:
+ if (optlen<1)
+ return -EINVAL;
+ if (val==-1)
+ val = 1;
+ if (val < 0 || val > 255)
+ return -EINVAL;
+ sk->ip_mc_ttl=val;
+ return 0;
+ case IP_MULTICAST_LOOP:
+ if (optlen<1)
+ return -EINVAL;
+ sk->ip_mc_loop = val ? 1 : 0;
+ return 0;
+ case IP_MULTICAST_IF:
+ {
+ struct ip_mreqn mreq;
+ struct device *dev = NULL;
+
+ /*
+ * Check the arguments are allowable
+ */
+
+ if (optlen >= sizeof(struct ip_mreqn)) {
+ if (copy_from_user(&mreq,optval,sizeof(mreq)))
+ return -EFAULT;
+ } else {
+ memset(&mreq, 0, sizeof(mreq));
+ if (optlen >= sizeof(struct in_addr) &&
+ copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr)))
+ return -EFAULT;
+ }
+
+ if (!mreq.imr_ifindex) {
+ if (mreq.imr_address.s_addr == INADDR_ANY) {
+ sk->ip_mc_index = 0;
+ sk->ip_mc_addr = 0;
+ return 0;
+ }
+ dev = ip_dev_find(mreq.imr_address.s_addr);
+ } else
+ dev = dev_get_by_index(mreq.imr_ifindex);
+
+ if (!dev)
+ return -EADDRNOTAVAIL;
+
+ if (sk->bound_dev_if && dev->ifindex != sk->bound_dev_if)
+ return -EINVAL;
+
+ sk->ip_mc_index = mreq.imr_ifindex;
+ sk->ip_mc_addr = mreq.imr_address.s_addr;
+ return 0;
+ }
+
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ {
+ struct ip_mreqn mreq;
+
+ if (optlen < sizeof(struct ip_mreq))
+ return -EINVAL;
+ if (optlen >= sizeof(struct ip_mreqn)) {
+ if(copy_from_user(&mreq,optval,sizeof(mreq)))
+ return -EFAULT;
+ } else {
+ memset(&mreq, 0, sizeof(mreq));
+ if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq)))
+ return -EFAULT;
+ }
+
+ if (optname == IP_ADD_MEMBERSHIP)
+ return ip_mc_join_group(sk,&mreq);
+ else
+ return ip_mc_leave_group(sk,&mreq);
+ }
+ case IP_ROUTER_ALERT:
+ return ip_ra_control(sk, val ? 1 : 0, NULL);
+
+#ifdef CONFIG_IP_FIREWALL
+ case IP_FW_MASQ_TIMEOUTS:
+ case IP_FW_APPEND:
+ case IP_FW_REPLACE:
+ case IP_FW_DELETE:
+ case IP_FW_DELETE_NUM:
+ case IP_FW_INSERT:
+ case IP_FW_FLUSH:
+ case IP_FW_ZERO:
+ case IP_FW_CHECK:
+ case IP_FW_CREATECHAIN:
+ case IP_FW_DELETECHAIN:
+ case IP_FW_POLICY:
+ if(!capable(CAP_NET_ADMIN))
+ return -EACCES;
+ if(optlen>sizeof(tmp_fw) || optlen<1)
+ return -EINVAL;
+ if(copy_from_user(&tmp_fw,optval,optlen))
+ return -EFAULT;
+ err=ip_fw_ctl(optname, &tmp_fw,optlen);
+ return -err; /* -0 is 0 after all */
+#endif /* CONFIG_IP_FIREWALL */
+#ifdef CONFIG_IP_MASQUERADE
+ case IP_FW_MASQ_CTL:
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if(optlen<1)
+ return -EINVAL;
+ err=ip_masq_uctl(optname, optval ,optlen);
+ return err;
+
+#endif
+ default:
+ return(-ENOPROTOOPT);
+ }
+}
+
+/*
+ * Get the options. Note for future reference. The GET of IP options gets the
+ * _received_ ones. The set sets the _sent_ ones.
+ */
+
+int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
+{
+ int val;
+ int len;
+
+ if(level!=SOL_IP)
+ return -EOPNOTSUPP;
+
+#ifdef CONFIG_IP_MROUTE
+ if(optname>=MRT_BASE && optname <=MRT_BASE+10)
+ {
+ return ip_mroute_getsockopt(sk,optname,optval,optlen);
+ }
+#endif
+
+ if(get_user(len,optlen))
+ return -EFAULT;
+
+ switch(optname)
+ {
+ case IP_OPTIONS:
+ {
+ unsigned char optbuf[sizeof(struct ip_options)+40];
+ struct ip_options * opt = (struct ip_options*)optbuf;
+ lock_sock(sk);
+ opt->optlen = 0;
+ if (sk->opt)
+ memcpy(optbuf, sk->opt, sizeof(struct ip_options)+sk->opt->optlen);
+ release_sock(sk);
+ if (opt->optlen == 0)
+ return put_user(0, optlen);
+
+ ip_options_undo(opt);
+
+ len=min(len, opt->optlen);
+ if(put_user(len, optlen))
+ return -EFAULT;
+ if(copy_to_user(optval, opt->__data, len))
+ return -EFAULT;
+ return 0;
+ }
+ case IP_PKTINFO:
+ val = (sk->ip_cmsg_flags & IP_CMSG_PKTINFO) != 0;
+ break;
+ case IP_RECVTTL:
+ val = (sk->ip_cmsg_flags & IP_CMSG_TTL) != 0;
+ break;
+ case IP_RECVTOS:
+ val = (sk->ip_cmsg_flags & IP_CMSG_TOS) != 0;
+ break;
+ case IP_RECVOPTS:
+ val = (sk->ip_cmsg_flags & IP_CMSG_RECVOPTS) != 0;
+ break;
+ case IP_RETOPTS:
+ val = (sk->ip_cmsg_flags & IP_CMSG_RETOPTS) != 0;
+ break;
+ case IP_TOS:
+ val=sk->ip_tos;
+ break;
+ case IP_TTL:
+ val=sk->ip_ttl;
+ break;
+ case IP_HDRINCL:
+ val=sk->ip_hdrincl;
+ break;
+ case IP_MTU_DISCOVER:
+ val=sk->ip_pmtudisc;
+ break;
+ case IP_MTU:
+ val = 0;
+ lock_sock(sk);
+ if (sk->dst_cache)
+ val = sk->dst_cache->pmtu;
+ release_sock(sk);
+ if (!val)
+ return -ENOTCONN;
+ break;
+ case IP_RECVERR:
+ val=sk->ip_recverr;
+ break;
+ case IP_MULTICAST_TTL:
+ val=sk->ip_mc_ttl;
+ break;
+ case IP_MULTICAST_LOOP:
+ val=sk->ip_mc_loop;
+ break;
+ case IP_MULTICAST_IF:
+ {
+ struct ip_mreqn mreq;
+ len = min(len,sizeof(struct ip_mreqn));
+ if(put_user(len, optlen))
+ return -EFAULT;
+ mreq.imr_ifindex = sk->ip_mc_index;
+ mreq.imr_address.s_addr = sk->ip_mc_addr;
+ mreq.imr_multiaddr.s_addr = 0;
+ if(copy_to_user((void *)optval, &mreq, len))
+ return -EFAULT;
+ return 0;
+ }
+ default:
+ return(-ENOPROTOOPT);
+ }
+
+ if (len < sizeof(int) && len > 0 && val>=0 && val<255) {
+ unsigned char ucval = (unsigned char)val;
+ len = 1;
+ if(put_user(len, optlen))
+ return -EFAULT;
+ if(copy_to_user(optval,&ucval,1))
+ return -EFAULT;
+ } else {
+ len=min(sizeof(int),len);
+ if(put_user(len, optlen))
+ return -EFAULT;
+ if(copy_to_user(optval,&val,len))
+ return -EFAULT;
+ }
+ return 0;
+}
diff --git a/pfinet/linux-src/net/ipv4/ipconfig.c b/pfinet/linux-src/net/ipv4/ipconfig.c
new file mode 100644
index 00000000..0770bad1
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ipconfig.c
@@ -0,0 +1,970 @@
+/*
+ * $Id: ipconfig.c,v 1.20.2.1 1999/06/28 11:33:27 davem Exp $
+ *
+ * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
+ * information to configure own IP address and routes.
+ *
+ * Copyright (C) 1996--1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * Derived from network configuration code in fs/nfs/nfsroot.c,
+ * originally Copyright (C) 1995, 1996 Gero Kuhlmann and me.
+ *
+ * BOOTP rewritten to construct and analyse packets itself instead
+ * of misusing the IP layer. num_bugs_causing_wrong_arp_replies--;
+ * -- MJ, December 1998
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/utsname.h>
+#include <linux/in.h>
+#include <linux/if.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/socket.h>
+#include <linux/route.h>
+#include <linux/udp.h>
+#include <net/arp.h>
+#include <net/ip.h>
+#include <net/ipconfig.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+
+/* Define this to allow debugging output */
+#undef IPCONFIG_DEBUG
+
+#ifdef IPCONFIG_DEBUG
+#define DBG(x) printk x
+#else
+#define DBG(x) do { } while(0)
+#endif
+
+/* Define the timeout for waiting for a RARP/BOOTP reply */
+#define CONF_BASE_TIMEOUT (HZ*5) /* Initial timeout: 5 seconds */
+#define CONF_RETRIES 10 /* 10 retries */
+#define CONF_TIMEOUT_RANDOM (HZ) /* Maximum amount of randomization */
+#define CONF_TIMEOUT_MULT *5/4 /* Rate of timeout growth */
+#define CONF_TIMEOUT_MAX (HZ*30) /* Maximum allowed timeout */
+
+/* IP configuration */
+static char user_dev_name[IFNAMSIZ] __initdata = { 0, };/* Name of user-selected boot device */
+u32 ic_myaddr __initdata = INADDR_NONE; /* My IP address */
+u32 ic_servaddr __initdata = INADDR_NONE; /* Server IP address */
+u32 ic_gateway __initdata = INADDR_NONE; /* Gateway IP address */
+u32 ic_netmask __initdata = INADDR_NONE; /* Netmask for local subnet */
+int ic_enable __initdata = 1; /* Automatic IP configuration enabled */
+int ic_host_name_set __initdata = 0; /* Host name configured manually */
+int ic_set_manually __initdata = 0; /* IPconfig parameters set manually */
+
+u32 root_server_addr __initdata = INADDR_NONE; /* Address of boot server */
+u8 root_server_path[256] __initdata = { 0, }; /* Path to mount as root */
+
+#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
+
+#define CONFIG_IP_PNP_DYNAMIC
+
+static int ic_proto_enabled __initdata = 0 /* Protocols enabled */
+#ifdef CONFIG_IP_PNP_BOOTP
+ | IC_BOOTP
+#endif
+#ifdef CONFIG_IP_PNP_RARP
+ | IC_RARP
+#endif
+ ;
+static int ic_got_reply __initdata = 0; /* Protocol(s) we got reply from */
+
+#else
+
+static int ic_proto_enabled __initdata = 0;
+
+#endif
+
+static int ic_proto_have_if __initdata = 0;
+
+/*
+ * Network devices
+ */
+
+struct ic_device {
+ struct ic_device *next;
+ struct device *dev;
+ unsigned short flags;
+ int able;
+};
+
+static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
+static struct device *ic_dev __initdata = NULL; /* Selected device */
+
+static int __init ic_open_devs(void)
+{
+ struct ic_device *d, **last;
+ struct device *dev;
+ unsigned short oflags;
+
+ last = &ic_first_dev;
+ for (dev = dev_base; dev; dev = dev->next)
+ if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
+ (!(dev->flags & IFF_LOOPBACK) &&
+ (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
+ strncmp(dev->name, "dummy", 5))) {
+ int able = 0;
+ if (dev->mtu >= 364)
+ able |= IC_BOOTP;
+ else
+ printk(KERN_WARNING "BOOTP: Ignoring device %s, MTU %d too small", dev->name, dev->mtu);
+ if (!(dev->flags & IFF_NOARP))
+ able |= IC_RARP;
+ able &= ic_proto_enabled;
+ if (ic_proto_enabled && !able)
+ continue;
+ oflags = dev->flags;
+ if (dev_change_flags(dev, oflags | IFF_UP) < 0) {
+ printk(KERN_ERR "IP-Config: Failed to open %s\n", dev->name);
+ continue;
+ }
+ if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL)))
+ return -1;
+ d->dev = dev;
+ *last = d;
+ last = &d->next;
+ d->flags = oflags;
+ d->able = able;
+ ic_proto_have_if |= able;
+ DBG(("IP-Config: Opened %s (able=%d)\n", dev->name, able));
+ }
+ *last = NULL;
+
+ if (!ic_first_dev) {
+ if (user_dev_name[0])
+ printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name);
+ else
+ printk(KERN_ERR "IP-Config: No network devices available.\n");
+ return -1;
+ }
+ return 0;
+}
+
+static void __init ic_close_devs(void)
+{
+ struct ic_device *d, *next;
+ struct device *dev;
+
+ next = ic_first_dev;
+ while ((d = next)) {
+ next = d->next;
+ dev = d->dev;
+ if (dev != ic_dev) {
+ DBG(("IP-Config: Downing %s\n", dev->name));
+ dev_change_flags(dev, d->flags);
+ }
+ kfree_s(d, sizeof(struct ic_device));
+ }
+}
+
+/*
+ * Interface to various network functions.
+ */
+
+static inline void
+set_sockaddr(struct sockaddr_in *sin, u32 addr, u16 port)
+{
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = addr;
+ sin->sin_port = port;
+}
+
+static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
+{
+ int res;
+
+ mm_segment_t oldfs = get_fs();
+ set_fs(get_ds());
+ res = devinet_ioctl(cmd, arg);
+ set_fs(oldfs);
+ return res;
+}
+
+static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg)
+{
+ int res;
+
+ mm_segment_t oldfs = get_fs();
+ set_fs(get_ds());
+ res = ip_rt_ioctl(cmd, arg);
+ set_fs(oldfs);
+ return res;
+}
+
+/*
+ * Set up interface addresses and routes.
+ */
+
+static int __init ic_setup_if(void)
+{
+ struct ifreq ir;
+ struct sockaddr_in *sin = (void *) &ir.ifr_ifru.ifru_addr;
+ int err;
+
+ memset(&ir, 0, sizeof(ir));
+ strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
+ set_sockaddr(sin, ic_myaddr, 0);
+ if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) {
+ printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err);
+ return -1;
+ }
+ set_sockaddr(sin, ic_netmask, 0);
+ if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
+ printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err);
+ return -1;
+ }
+ set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
+ if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
+ printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err);
+ return -1;
+ }
+ return 0;
+}
+
+static int __init ic_setup_routes(void)
+{
+ /* No need to setup device routes, only the default route... */
+
+ if (ic_gateway != INADDR_NONE) {
+ struct rtentry rm;
+ int err;
+
+ memset(&rm, 0, sizeof(rm));
+ if ((ic_gateway ^ ic_myaddr) & ic_netmask) {
+ printk(KERN_ERR "IP-Config: Gateway not on directly connected network.\n");
+ return -1;
+ }
+ set_sockaddr((struct sockaddr_in *) &rm.rt_dst, 0, 0);
+ set_sockaddr((struct sockaddr_in *) &rm.rt_genmask, 0, 0);
+ set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0);
+ rm.rt_flags = RTF_UP | RTF_GATEWAY;
+ if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) {
+ printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Fill in default values for all missing parameters.
+ */
+
+static int __init ic_defaults(void)
+{
+ /*
+ * At this point we have no userspace running so need not
+ * claim locks on system_utsname
+ */
+
+ if (!ic_host_name_set)
+ strcpy(system_utsname.nodename, in_ntoa(ic_myaddr));
+
+ if (root_server_addr == INADDR_NONE)
+ root_server_addr = ic_servaddr;
+
+ if (ic_netmask == INADDR_NONE) {
+ if (IN_CLASSA(ntohl(ic_myaddr)))
+ ic_netmask = htonl(IN_CLASSA_NET);
+ else if (IN_CLASSB(ntohl(ic_myaddr)))
+ ic_netmask = htonl(IN_CLASSB_NET);
+ else if (IN_CLASSC(ntohl(ic_myaddr)))
+ ic_netmask = htonl(IN_CLASSC_NET);
+ else {
+ printk(KERN_ERR "IP-Config: Unable to guess netmask for address %08x\n", ic_myaddr);
+ return -1;
+ }
+ printk("IP-Config: Guessing netmask %s\n", in_ntoa(ic_netmask));
+ }
+
+ return 0;
+}
+
+/*
+ * RARP support.
+ */
+
+#ifdef CONFIG_IP_PNP_RARP
+
+static int ic_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt);
+
+static struct packet_type rarp_packet_type __initdata = {
+ __constant_htons(ETH_P_RARP),
+ NULL, /* Listen to all devices */
+ ic_rarp_recv,
+ NULL,
+ NULL
+};
+
+static inline void ic_rarp_init(void)
+{
+ dev_add_pack(&rarp_packet_type);
+}
+
+static inline void ic_rarp_cleanup(void)
+{
+ dev_remove_pack(&rarp_packet_type);
+}
+
+/*
+ * Process received RARP packet.
+ */
+static int __init
+ic_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+{
+ struct arphdr *rarp = (struct arphdr *)skb->h.raw;
+ unsigned char *rarp_ptr = (unsigned char *) (rarp + 1);
+ unsigned long sip, tip;
+ unsigned char *sha, *tha; /* s for "source", t for "target" */
+
+ /* If we already have a reply, just drop the packet */
+ if (ic_got_reply)
+ goto drop;
+
+ /* If this test doesn't pass, it's not IP, or we should ignore it anyway */
+ if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd))
+ goto drop;
+
+ /* If it's not a RARP reply, delete it. */
+ if (rarp->ar_op != htons(ARPOP_RREPLY))
+ goto drop;
+
+ /* If it's not Ethernet, delete it. */
+ if (rarp->ar_pro != htons(ETH_P_IP))
+ goto drop;
+
+ /* Extract variable-width fields */
+ sha = rarp_ptr;
+ rarp_ptr += dev->addr_len;
+ memcpy(&sip, rarp_ptr, 4);
+ rarp_ptr += 4;
+ tha = rarp_ptr;
+ rarp_ptr += dev->addr_len;
+ memcpy(&tip, rarp_ptr, 4);
+
+ /* Discard packets which are not meant for us. */
+ if (memcmp(tha, dev->dev_addr, dev->addr_len))
+ goto drop;
+
+ /* Discard packets which are not from specified server. */
+ if (ic_servaddr != INADDR_NONE && ic_servaddr != sip)
+ goto drop;
+
+ /* Victory! The packet is what we were looking for! */
+ if (!ic_got_reply) {
+ ic_got_reply = IC_RARP;
+ ic_dev = dev;
+ if (ic_myaddr == INADDR_NONE)
+ ic_myaddr = tip;
+ ic_servaddr = sip;
+ }
+
+ /* And throw the packet out... */
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+
+
+/*
+ * Send RARP request packet over all devices which allow RARP.
+ */
+static void __init ic_rarp_send(void)
+{
+ struct ic_device *d;
+
+ for (d=ic_first_dev; d; d=d->next)
+ if (d->able & IC_RARP) {
+ struct device *dev = d->dev;
+ arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
+ dev->dev_addr, dev->dev_addr);
+ }
+}
+
+#endif
+
+/*
+ * BOOTP support.
+ */
+
+#ifdef CONFIG_IP_PNP_BOOTP
+
+struct bootp_pkt { /* BOOTP packet format */
+ struct iphdr iph; /* IP header */
+ struct udphdr udph; /* UDP header */
+ u8 op; /* 1=request, 2=reply */
+ u8 htype; /* HW address type */
+ u8 hlen; /* HW address length */
+ u8 hops; /* Used only by gateways */
+ u32 xid; /* Transaction ID */
+ u16 secs; /* Seconds since we started */
+ u16 flags; /* Just what it says */
+ u32 client_ip; /* Client's IP address if known */
+ u32 your_ip; /* Assigned IP address */
+ u32 server_ip; /* Server's IP address */
+ u32 relay_ip; /* IP address of BOOTP relay */
+ u8 hw_addr[16]; /* Client's HW address */
+ u8 serv_name[64]; /* Server host name */
+ u8 boot_file[128]; /* Name of boot file */
+ u8 vendor_area[128]; /* Area for extensions */
+};
+
+#define BOOTP_REQUEST 1
+#define BOOTP_REPLY 2
+
+static u32 ic_bootp_xid;
+
+static int ic_bootp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt);
+
+static struct packet_type bootp_packet_type __initdata = {
+ __constant_htons(ETH_P_IP),
+ NULL, /* Listen to all devices */
+ ic_bootp_recv,
+ NULL,
+ NULL
+};
+
+
+/*
+ * Initialize BOOTP extension fields in the request.
+ */
+static void __init ic_bootp_init_ext(u8 *e)
+{
+ *e++ = 99; /* RFC1048 Magic Cookie */
+ *e++ = 130;
+ *e++ = 83;
+ *e++ = 99;
+ *e++ = 1; /* Subnet mask request */
+ *e++ = 4;
+ e += 4;
+ *e++ = 3; /* Default gateway request */
+ *e++ = 4;
+ e += 4;
+ *e++ = 12; /* Host name request */
+ *e++ = 32;
+ e += 32;
+ *e++ = 40; /* NIS Domain name request */
+ *e++ = 32;
+ e += 32;
+ *e++ = 17; /* Boot path */
+ *e++ = 32;
+ e += 32;
+ *e = 255; /* End of the list */
+}
+
+
+/*
+ * Initialize the BOOTP mechanism.
+ */
+static inline void ic_bootp_init(void)
+{
+ get_random_bytes(&ic_bootp_xid, sizeof(u32));
+ DBG(("BOOTP: XID=%08x\n", ic_bootp_xid));
+ dev_add_pack(&bootp_packet_type);
+}
+
+
+/*
+ * BOOTP cleanup.
+ */
+static inline void ic_bootp_cleanup(void)
+{
+ dev_remove_pack(&bootp_packet_type);
+}
+
+
+/*
+ * Send BOOTP request to single interface.
+ */
+static void __init ic_bootp_send_if(struct ic_device *d, u32 jiffies)
+{
+ struct device *dev = d->dev;
+ struct sk_buff *skb;
+ struct bootp_pkt *b;
+ int hh_len = (dev->hard_header_len + 15) & ~15;
+ struct iphdr *h;
+
+ /* Allocate packet */
+ skb = alloc_skb(sizeof(struct bootp_pkt) + hh_len + 15, GFP_KERNEL);
+ if (!skb)
+ return;
+ skb_reserve(skb, hh_len);
+ b = (struct bootp_pkt *) skb_put(skb, sizeof(struct bootp_pkt));
+ memset(b, 0, sizeof(struct bootp_pkt));
+
+ /* Construct IP header */
+ skb->nh.iph = h = &b->iph;
+ h->version = 4;
+ h->ihl = 5;
+ h->tot_len = htons(sizeof(struct bootp_pkt));
+ h->frag_off = htons(IP_DF);
+ h->ttl = 64;
+ h->protocol = IPPROTO_UDP;
+ h->daddr = INADDR_BROADCAST;
+ h->check = ip_fast_csum((unsigned char *) h, h->ihl);
+
+ /* Construct UDP header */
+ b->udph.source = htons(68);
+ b->udph.dest = htons(67);
+ b->udph.len = htons(sizeof(struct bootp_pkt) - sizeof(struct iphdr));
+ /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */
+
+ /* Construct BOOTP header */
+ b->op = BOOTP_REQUEST;
+ b->htype = dev->type;
+ b->hlen = dev->addr_len;
+ memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
+ b->secs = htons(jiffies / HZ);
+ b->xid = ic_bootp_xid;
+ ic_bootp_init_ext(b->vendor_area);
+
+ /* Chain packet down the line... */
+ skb->dev = dev;
+ skb->protocol = __constant_htons(ETH_P_IP);
+ if ((dev->hard_header &&
+ dev->hard_header(skb, dev, ntohs(skb->protocol), dev->broadcast, dev->dev_addr, skb->len) < 0) ||
+ dev_queue_xmit(skb) < 0)
+ printk("E");
+}
+
+
+/*
+ * Send BOOTP requests to all interfaces.
+ */
+static void __init ic_bootp_send(u32 jiffies)
+{
+ struct ic_device *d;
+
+ for(d=ic_first_dev; d; d=d->next)
+ if (d->able & IC_BOOTP)
+ ic_bootp_send_if(d, jiffies);
+}
+
+
+/*
+ * Copy BOOTP-supplied string if not already set.
+ */
+static int __init ic_bootp_string(char *dest, char *src, int len, int max)
+{
+ if (!len)
+ return 0;
+ if (len > max-1)
+ len = max-1;
+ strncpy(dest, src, len);
+ dest[len] = '\0';
+ return 1;
+}
+
+
+/*
+ * Process BOOTP extension.
+ */
+static void __init ic_do_bootp_ext(u8 *ext)
+{
+#ifdef IPCONFIG_DEBUG
+ u8 *c;
+
+ printk("BOOTP: Got extension %02x",*ext);
+ for(c=ext+2; c<ext+2+ext[1]; c++)
+ printk(" %02x", *c);
+ printk("\n");
+#endif
+
+ switch (*ext++) {
+ case 1: /* Subnet mask */
+ if (ic_netmask == INADDR_NONE)
+ memcpy(&ic_netmask, ext+1, 4);
+ break;
+ case 3: /* Default gateway */
+ if (ic_gateway == INADDR_NONE)
+ memcpy(&ic_gateway, ext+1, 4);
+ break;
+ case 12: /* Host name */
+ ic_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN);
+ ic_host_name_set = 1;
+ break;
+ case 40: /* NIS Domain name */
+ ic_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN);
+ break;
+ case 17: /* Root path */
+ if (!root_server_path[0])
+ ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path));
+ break;
+ }
+}
+
+
+/*
+ * Receive BOOTP reply.
+ */
+static int __init ic_bootp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+{
+ struct bootp_pkt *b = (struct bootp_pkt *) skb->nh.iph;
+ struct iphdr *h = &b->iph;
+ int len;
+
+ /* If we already have a reply, just drop the packet */
+ if (ic_got_reply)
+ goto drop;
+
+ /* Check whether it's a BOOTP packet */
+ if (skb->pkt_type == PACKET_OTHERHOST ||
+ skb->len < sizeof(struct udphdr) + sizeof(struct iphdr) ||
+ h->ihl != 5 ||
+ h->version != 4 ||
+ ip_fast_csum((char *) h, h->ihl) != 0 ||
+ skb->len < ntohs(h->tot_len) ||
+ h->protocol != IPPROTO_UDP ||
+ b->udph.source != htons(67) ||
+ b->udph.dest != htons(68) ||
+ ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr))
+ goto drop;
+
+ /* Fragments are not supported */
+ if (h->frag_off & htons(IP_OFFSET|IP_MF)) {
+ printk(KERN_ERR "BOOTP: Ignoring fragmented reply.\n");
+ goto drop;
+ }
+
+ /* Is it a reply to our BOOTP request? */
+ len = ntohs(b->udph.len) - sizeof(struct udphdr);
+ if (len < 300 || /* See RFC 951:2.1 */
+ b->op != BOOTP_REPLY ||
+ b->xid != ic_bootp_xid) {
+ printk("?");
+ goto drop;
+ }
+
+ /* Extract basic fields */
+ ic_myaddr = b->your_ip;
+ ic_servaddr = b->server_ip;
+ ic_got_reply = IC_BOOTP;
+ ic_dev = dev;
+
+ /* Parse extensions */
+ if (b->vendor_area[0] == 99 && /* Check magic cookie */
+ b->vendor_area[1] == 130 &&
+ b->vendor_area[2] == 83 &&
+ b->vendor_area[3] == 99) {
+ u8 *ext = &b->vendor_area[4];
+ u8 *end = (u8 *) b + ntohs(b->iph.tot_len);
+ while (ext < end && *ext != 0xff) {
+ if (*ext == 0) /* Padding */
+ ext++;
+ else {
+ u8 *opt = ext;
+ ext += ext[1] + 2;
+ if (ext <= end)
+ ic_do_bootp_ext(opt);
+ }
+ }
+ }
+
+ if (ic_gateway == INADDR_NONE && b->relay_ip)
+ ic_gateway = b->relay_ip;
+
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+
+
+#endif
+
+
+/*
+ * Dynamic IP configuration -- BOOTP and RARP.
+ */
+
+#ifdef CONFIG_IP_PNP_DYNAMIC
+
+static int __init ic_dynamic(void)
+{
+ int retries;
+ unsigned long timeout, jiff;
+ unsigned long start_jiffies;
+ int do_rarp = ic_proto_have_if & IC_RARP;
+ int do_bootp = ic_proto_have_if & IC_BOOTP;
+
+ /*
+ * If neither BOOTP nor RARP was selected, return with an error. This
+ * routine gets only called when some pieces of information are mis-
+ * sing, and without BOOTP and RARP we are not able to get that in-
+ * formation.
+ */
+ if (!ic_proto_enabled) {
+ printk(KERN_ERR "IP-Config: Incomplete network configuration information.\n");
+ return -1;
+ }
+
+#ifdef CONFIG_IP_PNP_BOOTP
+ if ((ic_proto_enabled ^ ic_proto_have_if) & IC_BOOTP)
+ printk(KERN_ERR "BOOTP: No suitable device found.\n");
+#endif
+
+#ifdef CONFIG_IP_PNP_RARP
+ if ((ic_proto_enabled ^ ic_proto_have_if) & IC_RARP)
+ printk(KERN_ERR "RARP: No suitable device found.\n");
+#endif
+
+ if (!ic_proto_have_if)
+ /* Error message already printed */
+ return -1;
+
+ /*
+ * Setup RARP and BOOTP protocols
+ */
+#ifdef CONFIG_IP_PNP_RARP
+ if (do_rarp)
+ ic_rarp_init();
+#endif
+#ifdef CONFIG_IP_PNP_BOOTP
+ if (do_bootp)
+ ic_bootp_init();
+#endif
+
+ /*
+ * Send requests and wait, until we get an answer. This loop
+ * seems to be a terrible waste of CPU time, but actually there is
+ * only one process running at all, so we don't need to use any
+ * scheduler functions.
+ * [Actually we could now, but the nothing else running note still
+ * applies.. - AC]
+ */
+ printk(KERN_NOTICE "Sending %s%s%s requests...",
+ do_bootp ? "BOOTP" : "",
+ do_bootp && do_rarp ? " and " : "",
+ do_rarp ? "RARP" : "");
+ start_jiffies = jiffies;
+ retries = CONF_RETRIES;
+ get_random_bytes(&timeout, sizeof(timeout));
+ timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM);
+ for(;;) {
+#ifdef CONFIG_IP_PNP_BOOTP
+ if (do_bootp)
+ ic_bootp_send(jiffies - start_jiffies);
+#endif
+#ifdef CONFIG_IP_PNP_RARP
+ if (do_rarp)
+ ic_rarp_send();
+#endif
+ printk(".");
+ jiff = jiffies + timeout;
+ while (jiffies < jiff && !ic_got_reply)
+ ;
+ if (ic_got_reply) {
+ printk(" OK\n");
+ break;
+ }
+ if (! --retries) {
+ printk(" timed out!\n");
+ break;
+ }
+ timeout = timeout CONF_TIMEOUT_MULT;
+ if (timeout > CONF_TIMEOUT_MAX)
+ timeout = CONF_TIMEOUT_MAX;
+ }
+
+#ifdef CONFIG_IP_PNP_RARP
+ if (do_rarp)
+ ic_rarp_cleanup();
+#endif
+#ifdef CONFIG_IP_PNP_BOOTP
+ if (do_bootp)
+ ic_bootp_cleanup();
+#endif
+
+ if (!ic_got_reply)
+ return -1;
+
+ printk("IP-Config: Got %s answer from %s, ",
+ (ic_got_reply & IC_BOOTP) ? "BOOTP" : "RARP",
+ in_ntoa(ic_servaddr));
+ printk("my address is %s\n", in_ntoa(ic_myaddr));
+
+ return 0;
+}
+
+#endif
+
+/*
+ * IP Autoconfig dispatcher.
+ */
+
+int __init ip_auto_config(void)
+{
+ if (!ic_enable)
+ return 0;
+
+ DBG(("IP-Config: Entered.\n"));
+
+ /* Setup all network devices */
+ if (ic_open_devs() < 0)
+ return -1;
+
+ /*
+ * If the config information is insufficient (e.g., our IP address or
+ * IP address of the boot server is missing or we have multiple network
+ * interfaces and no default was set), use BOOTP or RARP to get the
+ * missing values.
+ */
+ if (ic_myaddr == INADDR_NONE ||
+#ifdef CONFIG_ROOT_NFS
+ (root_server_addr == INADDR_NONE && ic_servaddr == INADDR_NONE) ||
+#endif
+ ic_first_dev->next) {
+#ifdef CONFIG_IP_PNP_DYNAMIC
+ if (ic_dynamic() < 0) {
+ printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n");
+ ic_close_devs();
+ return -1;
+ }
+#else
+ printk(KERN_ERR "IP-Config: Incomplete network configuration information.\n");
+ ic_close_devs();
+ return -1;
+#endif
+ } else {
+ ic_dev = ic_first_dev->dev; /* Device selected manually or only one device -> use it */
+ }
+
+ /*
+ * Use defaults whereever applicable.
+ */
+ if (ic_defaults() < 0)
+ return -1;
+
+ /*
+ * Close all network devices except the device we've
+ * autoconfigured and set up routes.
+ */
+ ic_close_devs();
+ if (ic_setup_if() < 0 || ic_setup_routes() < 0)
+ return -1;
+
+ DBG(("IP-Config: device=%s, local=%08x, server=%08x, boot=%08x, gw=%08x, mask=%08x\n",
+ ic_dev->name, ic_myaddr, ic_servaddr, root_server_addr, ic_gateway, ic_netmask));
+ DBG(("IP-Config: host=%s, domain=%s, path=`%s'\n", system_utsname.nodename,
+ system_utsname.domainname, root_server_path));
+ return 0;
+}
+
+/*
+ * Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel
+ * command line parameter. It consists of option fields separated by colons in
+ * the following order:
+ *
+ * <client-ip>:<server-ip>:<gw-ip>:<netmask>:<host name>:<device>:<bootp|rarp>
+ *
+ * Any of the fields can be empty which means to use a default value:
+ * <client-ip> - address given by BOOTP or RARP
+ * <server-ip> - address of host returning BOOTP or RARP packet
+ * <gw-ip> - none, or the address returned by BOOTP
+ * <netmask> - automatically determined from <client-ip>, or the
+ * one returned by BOOTP
+ * <host name> - <client-ip> in ASCII notation, or the name returned
+ * by BOOTP
+ * <device> - use all available devices
+ * <bootp|rarp|both|off> - use both protocols to determine my own address
+ */
+static int __init ic_proto_name(char *name)
+{
+ if (!strcmp(name, "off")) {
+ ic_proto_enabled = 0;
+ return 1;
+ }
+#ifdef CONFIG_IP_PNP_BOOTP
+ else if (!strcmp(name, "bootp")) {
+ ic_proto_enabled &= ~IC_RARP;
+ return 1;
+ }
+#endif
+#ifdef CONFIG_IP_PNP_RARP
+ else if (!strcmp(name, "rarp")) {
+ ic_proto_enabled &= ~IC_BOOTP;
+ return 1;
+ }
+#endif
+#ifdef CONFIG_IP_PNP_DYNAMIC
+ else if (!strcmp(name, "both")) {
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+void __init ip_auto_config_setup(char *addrs, int *ints)
+{
+ char *cp, *ip, *dp;
+ int num = 0;
+
+ ic_set_manually = 1;
+ if (!strcmp(addrs, "off")) {
+ ic_enable = 0;
+ return;
+ }
+ if (ic_proto_name(addrs))
+ return;
+
+ /* Parse the whole string */
+ ip = addrs;
+ while (ip && *ip) {
+ if ((cp = strchr(ip, ':')))
+ *cp++ = '\0';
+ if (strlen(ip) > 0) {
+ DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip));
+ switch (num) {
+ case 0:
+ if ((ic_myaddr = in_aton(ip)) == INADDR_ANY)
+ ic_myaddr = INADDR_NONE;
+ break;
+ case 1:
+ if ((ic_servaddr = in_aton(ip)) == INADDR_ANY)
+ ic_servaddr = INADDR_NONE;
+ break;
+ case 2:
+ if ((ic_gateway = in_aton(ip)) == INADDR_ANY)
+ ic_gateway = INADDR_NONE;
+ break;
+ case 3:
+ if ((ic_netmask = in_aton(ip)) == INADDR_ANY)
+ ic_netmask = INADDR_NONE;
+ break;
+ case 4:
+ if ((dp = strchr(ip, '.'))) {
+ *dp++ = '\0';
+ strncpy(system_utsname.domainname, dp, __NEW_UTS_LEN);
+ system_utsname.domainname[__NEW_UTS_LEN] = '\0';
+ }
+ strncpy(system_utsname.nodename, ip, __NEW_UTS_LEN);
+ system_utsname.nodename[__NEW_UTS_LEN] = '\0';
+ ic_host_name_set = 1;
+ break;
+ case 5:
+ strncpy(user_dev_name, ip, IFNAMSIZ);
+ user_dev_name[IFNAMSIZ-1] = '\0';
+ break;
+ case 6:
+ ic_proto_name(ip);
+ break;
+ }
+ }
+ ip = cp;
+ num++;
+ }
+}
diff --git a/pfinet/linux-src/net/ipv4/ipip.c b/pfinet/linux-src/net/ipv4/ipip.c
new file mode 100644
index 00000000..0aeef4a3
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ipip.c
@@ -0,0 +1,870 @@
+/*
+ * Linux NET3: IP/IP protocol decoder.
+ *
+ * Version: $Id: ipip.c,v 1.26 1999/03/25 10:04:32 davem Exp $
+ *
+ * Authors:
+ * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
+ *
+ * Fixes:
+ * Alan Cox : Merged and made usable non modular (its so tiny its silly as
+ * a module taking up 2 pages).
+ * Alan Cox : Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph)
+ * to keep ip_forward happy.
+ * Alan Cox : More fixes for 1.3.21, and firewall fix. Maybe this will work soon 8).
+ * Kai Schulte : Fixed #defines for IP_FIREWALL->FIREWALL
+ * David Woodhouse : Perform some basic ICMP handling.
+ * IPIP Routing without decapsulation.
+ * Carlos Picoto : GRE over IP support
+ * Alexey Kuznetsov: Reworked. Really, now it is truncated version of ipv4/ip_gre.c.
+ * I do not want to merge them together.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+/* tunnel.c: an IP tunnel driver
+
+ The purpose of this driver is to provide an IP tunnel through
+ which you can tunnel network traffic transparently across subnets.
+
+ This was written by looking at Nick Holloway's dummy driver
+ Thanks for the great code!
+
+ -Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
+
+ Minor tweaks:
+ Cleaned up the code a little and added some pre-1.3.0 tweaks.
+ dev->hard_header/hard_header_len changed to use no headers.
+ Comments/bracketing tweaked.
+ Made the tunnels use dev->name not tunnel: when error reporting.
+ Added tx_dropped stat
+
+ -Alan Cox (Alan.Cox@linux.org) 21 March 95
+
+ Reworked:
+ Changed to tunnel to destination gateway in addition to the
+ tunnel's pointopoint address
+ Almost completely rewritten
+ Note: There is currently no firewall or ICMP handling done.
+
+ -Sam Lantinga (slouken@cs.ucdavis.edu) 02/13/96
+
+*/
+
+/* Things I wish I had known when writing the tunnel driver:
+
+ When the tunnel_xmit() function is called, the skb contains the
+ packet to be sent (plus a great deal of extra info), and dev
+ contains the tunnel device that _we_ are.
+
+ When we are passed a packet, we are expected to fill in the
+ source address with our source IP address.
+
+ What is the proper way to allocate, copy and free a buffer?
+ After you allocate it, it is a "0 length" chunk of memory
+ starting at zero. If you want to add headers to the buffer
+ later, you'll have to call "skb_reserve(skb, amount)" with
+ the amount of memory you want reserved. Then, you call
+ "skb_put(skb, amount)" with the amount of space you want in
+ the buffer. skb_put() returns a pointer to the top (#0) of
+ that buffer. skb->len is set to the amount of space you have
+ "allocated" with skb_put(). You can then write up to skb->len
+ bytes to that buffer. If you need more, you can call skb_put()
+ again with the additional amount of space you need. You can
+ find out how much more space you can allocate by calling
+ "skb_tailroom(skb)".
+ Now, to add header space, call "skb_push(skb, header_len)".
+ This creates space at the beginning of the buffer and returns
+ a pointer to this new space. If later you need to strip a
+ header from a buffer, call "skb_pull(skb, header_len)".
+ skb_headroom() will return how much space is left at the top
+ of the buffer (before the main data). Remember, this headroom
+ space must be reserved before the skb_put() function is called.
+ */
+
+/*
+ This version of net/ipv4/ipip.c is cloned of net/ipv4/ip_gre.c
+
+ For comments look at net/ipv4/ip_gre.c --ANK
+ */
+
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/if_arp.h>
+#include <linux/mroute.h>
+#include <linux/init.h>
+
+#include <net/sock.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/protocol.h>
+#include <net/ipip.h>
+
+#define HASH_SIZE 16
+#define HASH(addr) ((addr^(addr>>4))&0xF)
+
+static int ipip_fb_tunnel_init(struct device *dev);
+static int ipip_tunnel_init(struct device *dev);
+
+static struct device ipip_fb_tunnel_dev = {
+ NULL, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip_fb_tunnel_init,
+};
+
+static struct ip_tunnel ipip_fb_tunnel = {
+ NULL, &ipip_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"tunl0", }
+};
+
+static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
+static struct ip_tunnel *tunnels_r[HASH_SIZE];
+static struct ip_tunnel *tunnels_l[HASH_SIZE];
+static struct ip_tunnel *tunnels_wc[1];
+static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
+
+static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local)
+{
+ unsigned h0 = HASH(remote);
+ unsigned h1 = HASH(local);
+ struct ip_tunnel *t;
+
+ for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr &&
+ remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ for (t = tunnels_r[h0]; t; t = t->next) {
+ if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ for (t = tunnels_l[h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
+ return t;
+ return NULL;
+}
+
+static struct ip_tunnel **ipip_bucket(struct ip_tunnel *t)
+{
+ u32 remote = t->parms.iph.daddr;
+ u32 local = t->parms.iph.saddr;
+ unsigned h = 0;
+ int prio = 0;
+
+ if (remote) {
+ prio |= 2;
+ h ^= HASH(remote);
+ }
+ if (local) {
+ prio |= 1;
+ h ^= HASH(local);
+ }
+ return &tunnels[prio][h];
+}
+
+
+static void ipip_tunnel_unlink(struct ip_tunnel *t)
+{
+ struct ip_tunnel **tp;
+
+ for (tp = ipip_bucket(t); *tp; tp = &(*tp)->next) {
+ if (t == *tp) {
+ *tp = t->next;
+ synchronize_bh();
+ break;
+ }
+ }
+}
+
+static void ipip_tunnel_link(struct ip_tunnel *t)
+{
+ struct ip_tunnel **tp = ipip_bucket(t);
+
+ t->next = *tp;
+ wmb();
+ *tp = t;
+}
+
+struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create)
+{
+ u32 remote = parms->iph.daddr;
+ u32 local = parms->iph.saddr;
+ struct ip_tunnel *t, **tp, *nt;
+ struct device *dev;
+ unsigned h = 0;
+ int prio = 0;
+
+ if (remote) {
+ prio |= 2;
+ h ^= HASH(remote);
+ }
+ if (local) {
+ prio |= 1;
+ h ^= HASH(local);
+ }
+ for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) {
+ if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
+ return t;
+ }
+ if (!create)
+ return NULL;
+
+ MOD_INC_USE_COUNT;
+ dev = kmalloc(sizeof(*dev) + sizeof(*t), GFP_KERNEL);
+ if (dev == NULL) {
+ MOD_DEC_USE_COUNT;
+ return NULL;
+ }
+ memset(dev, 0, sizeof(*dev) + sizeof(*t));
+ dev->priv = (void*)(dev+1);
+ nt = (struct ip_tunnel*)dev->priv;
+ nt->dev = dev;
+ dev->name = nt->parms.name;
+ dev->init = ipip_tunnel_init;
+ memcpy(&nt->parms, parms, sizeof(*parms));
+ if (dev->name[0] == 0) {
+ int i;
+ for (i=1; i<100; i++) {
+ sprintf(dev->name, "tunl%d", i);
+ if (dev_get(dev->name) == NULL)
+ break;
+ }
+ if (i==100)
+ goto failed;
+ memcpy(parms->name, dev->name, IFNAMSIZ);
+ }
+ if (register_netdevice(dev) < 0)
+ goto failed;
+
+ ipip_tunnel_link(nt);
+ /* Do not decrement MOD_USE_COUNT here. */
+ return nt;
+
+failed:
+ kfree(dev);
+ MOD_DEC_USE_COUNT;
+ return NULL;
+}
+
+
+static void ipip_tunnel_destroy(struct device *dev)
+{
+ if (dev == &ipip_fb_tunnel_dev) {
+ tunnels_wc[0] = NULL;
+ synchronize_bh();
+ } else {
+ ipip_tunnel_unlink((struct ip_tunnel*)dev->priv);
+ kfree(dev);
+ MOD_DEC_USE_COUNT;
+ }
+}
+
+void ipip_err(struct sk_buff *skb, unsigned char *dp, int len)
+{
+#ifndef I_WISH_WORLD_WERE_PERFECT
+
+/* It is not :-( All the routers (except for Linux) return only
+ 8 bytes of packet payload. It means, that precise relaying of
+ ICMP in the real Internet is absolutely infeasible.
+ */
+ struct iphdr *iph = (struct iphdr*)dp;
+ int type = skb->h.icmph->type;
+ int code = skb->h.icmph->code;
+ struct ip_tunnel *t;
+
+ if (len < sizeof(struct iphdr))
+ return;
+
+ switch (type) {
+ default:
+ case ICMP_PARAMETERPROB:
+ return;
+
+ case ICMP_DEST_UNREACH:
+ switch (code) {
+ case ICMP_SR_FAILED:
+ case ICMP_PORT_UNREACH:
+ /* Impossible event. */
+ return;
+ case ICMP_FRAG_NEEDED:
+ /* Soft state for pmtu is maintained by IP core. */
+ return;
+ default:
+ /* All others are translated to HOST_UNREACH.
+ rfc2003 contains "deep thoughts" about NET_UNREACH,
+ I believe they are just ether pollution. --ANK
+ */
+ break;
+ }
+ break;
+ case ICMP_TIME_EXCEEDED:
+ if (code != ICMP_EXC_TTL)
+ return;
+ break;
+ }
+
+ t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
+ if (t == NULL || t->parms.iph.daddr == 0)
+ return;
+ if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
+ return;
+
+ if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO)
+ t->err_count++;
+ else
+ t->err_count = 1;
+ t->err_time = jiffies;
+ return;
+#else
+ struct iphdr *iph = (struct iphdr*)dp;
+ int hlen = iph->ihl<<2;
+ struct iphdr *eiph;
+ int type = skb->h.icmph->type;
+ int code = skb->h.icmph->code;
+ int rel_type = 0;
+ int rel_code = 0;
+ int rel_info = 0;
+ struct sk_buff *skb2;
+ struct rtable *rt;
+
+ if (len < hlen + sizeof(struct iphdr))
+ return;
+ eiph = (struct iphdr*)(dp + hlen);
+
+ switch (type) {
+ default:
+ return;
+ case ICMP_PARAMETERPROB:
+ if (skb->h.icmph->un.gateway < hlen)
+ return;
+
+ /* So... This guy found something strange INSIDE encapsulated
+ packet. Well, he is fool, but what can we do ?
+ */
+ rel_type = ICMP_PARAMETERPROB;
+ rel_info = skb->h.icmph->un.gateway - hlen;
+ break;
+
+ case ICMP_DEST_UNREACH:
+ switch (code) {
+ case ICMP_SR_FAILED:
+ case ICMP_PORT_UNREACH:
+ /* Impossible event. */
+ return;
+ case ICMP_FRAG_NEEDED:
+ /* And it is the only really necesary thing :-) */
+ rel_info = ntohs(skb->h.icmph->un.frag.mtu);
+ if (rel_info < hlen+68)
+ return;
+ rel_info -= hlen;
+ /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
+ if (rel_info > ntohs(eiph->tot_len))
+ return;
+ break;
+ default:
+ /* All others are translated to HOST_UNREACH.
+ rfc2003 contains "deep thoughts" about NET_UNREACH,
+ I believe, it is just ether pollution. --ANK
+ */
+ rel_type = ICMP_DEST_UNREACH;
+ rel_code = ICMP_HOST_UNREACH;
+ break;
+ }
+ break;
+ case ICMP_TIME_EXCEEDED:
+ if (code != ICMP_EXC_TTL)
+ return;
+ break;
+ }
+
+ /* Prepare fake skb to feed it to icmp_send */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2 == NULL)
+ return;
+ dst_release(skb2->dst);
+ skb2->dst = NULL;
+ skb_pull(skb2, skb->data - (u8*)eiph);
+ skb2->nh.raw = skb2->data;
+
+ /* Try to guess incoming interface */
+ if (ip_route_output(&rt, eiph->saddr, 0, RT_TOS(eiph->tos), 0)) {
+ kfree_skb(skb2);
+ return;
+ }
+ skb2->dev = rt->u.dst.dev;
+
+ /* route "incoming" packet */
+ if (rt->rt_flags&RTCF_LOCAL) {
+ ip_rt_put(rt);
+ rt = NULL;
+ if (ip_route_output(&rt, eiph->daddr, eiph->saddr, eiph->tos, 0) ||
+ rt->u.dst.dev->type != ARPHRD_IPGRE) {
+ ip_rt_put(rt);
+ kfree_skb(skb2);
+ return;
+ }
+ } else {
+ ip_rt_put(rt);
+ if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) ||
+ skb2->dst->dev->type != ARPHRD_IPGRE) {
+ kfree_skb(skb2);
+ return;
+ }
+ }
+
+ /* change mtu on this route */
+ if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
+ if (rel_info > skb2->dst->pmtu) {
+ kfree_skb(skb2);
+ return;
+ }
+ skb2->dst->pmtu = rel_info;
+ rel_info = htonl(rel_info);
+ } else if (type == ICMP_TIME_EXCEEDED) {
+ struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv;
+ if (t->parms.iph.ttl) {
+ rel_type = ICMP_DEST_UNREACH;
+ rel_code = ICMP_HOST_UNREACH;
+ }
+ }
+
+ icmp_send(skb2, rel_type, rel_code, rel_info);
+ kfree_skb(skb2);
+ return;
+#endif
+}
+
+int ipip_rcv(struct sk_buff *skb, unsigned short len)
+{
+ struct iphdr *iph;
+ struct ip_tunnel *tunnel;
+
+ iph = skb->nh.iph;
+ skb->mac.raw = skb->nh.raw;
+ skb->nh.raw = skb_pull(skb, skb->h.raw - skb->data);
+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+ skb->protocol = __constant_htons(ETH_P_IP);
+ skb->ip_summed = 0;
+ skb->pkt_type = PACKET_HOST;
+
+ if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
+ tunnel->stat.rx_packets++;
+ tunnel->stat.rx_bytes += skb->len;
+ skb->dev = tunnel->dev;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ netif_rx(skb);
+ return 0;
+ }
+
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+ kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * This function assumes it is being called from dev_queue_xmit()
+ * and that skb is filled properly by that function.
+ */
+
+static int ipip_tunnel_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ struct net_device_stats *stats = &tunnel->stat;
+ struct iphdr *tiph = &tunnel->parms.iph;
+ u8 tos = tunnel->parms.iph.tos;
+ u16 df = tiph->frag_off;
+ struct rtable *rt; /* Route to the other host */
+ struct device *tdev; /* Device to other host */
+ struct iphdr *old_iph = skb->nh.iph;
+ struct iphdr *iph; /* Our new IP header */
+ int max_headroom; /* The extra header space needed */
+ u32 dst = tiph->daddr;
+ int mtu;
+
+ if (tunnel->recursion++) {
+ tunnel->stat.collisions++;
+ goto tx_error;
+ }
+
+ if (skb->protocol != __constant_htons(ETH_P_IP))
+ goto tx_error;
+
+ if (tos&1)
+ tos = old_iph->tos;
+
+ if (!dst) {
+ /* NBMA tunnel */
+ if ((rt = (struct rtable*)skb->dst) == NULL) {
+ tunnel->stat.tx_fifo_errors++;
+ goto tx_error;
+ }
+ if ((dst = rt->rt_gateway) == 0)
+ goto tx_error_icmp;
+ }
+
+ if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) {
+ tunnel->stat.tx_carrier_errors++;
+ goto tx_error_icmp;
+ }
+ tdev = rt->u.dst.dev;
+
+ if (tdev == dev) {
+ ip_rt_put(rt);
+ tunnel->stat.collisions++;
+ goto tx_error;
+ }
+
+ mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
+ if (mtu < 68) {
+ tunnel->stat.collisions++;
+ ip_rt_put(rt);
+ goto tx_error;
+ }
+ if (skb->dst && mtu < skb->dst->pmtu)
+ skb->dst->pmtu = mtu;
+
+ df |= (old_iph->frag_off&__constant_htons(IP_DF));
+
+ if ((old_iph->frag_off&__constant_htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) {
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
+ ip_rt_put(rt);
+ goto tx_error;
+ }
+
+ if (tunnel->err_count > 0) {
+ if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) {
+ tunnel->err_count--;
+ dst_link_failure(skb);
+ } else
+ tunnel->err_count = 0;
+ }
+
+ skb->h.raw = skb->nh.raw;
+
+ /*
+ * Okay, now see if we can stuff it in the buffer as-is.
+ */
+ max_headroom = (((tdev->hard_header_len+15)&~15)+sizeof(struct iphdr));
+
+ if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+ struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
+ if (!new_skb) {
+ ip_rt_put(rt);
+ stats->tx_dropped++;
+ dev_kfree_skb(skb);
+ tunnel->recursion--;
+ return 0;
+ }
+ if (skb->sk)
+ skb_set_owner_w(new_skb, skb->sk);
+ dev_kfree_skb(skb);
+ skb = new_skb;
+ }
+
+ skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
+ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+
+ /*
+ * Push down and install the IPIP header.
+ */
+
+ iph = skb->nh.iph;
+ iph->version = 4;
+ iph->ihl = sizeof(struct iphdr)>>2;
+ iph->frag_off = df;
+ iph->protocol = IPPROTO_IPIP;
+ iph->tos = tos;
+ iph->daddr = rt->rt_dst;
+ iph->saddr = rt->rt_src;
+
+ if ((iph->ttl = tiph->ttl) == 0)
+ iph->ttl = old_iph->ttl;
+
+ iph->tot_len = htons(skb->len);
+ iph->id = htons(ip_id_count++);
+ ip_send_check(iph);
+
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+ ip_send(skb);
+ tunnel->recursion--;
+ return 0;
+
+tx_error_icmp:
+ dst_link_failure(skb);
+tx_error:
+ stats->tx_errors++;
+ dev_kfree_skb(skb);
+ tunnel->recursion--;
+ return 0;
+}
+
+static int
+ipip_tunnel_ioctl (struct device *dev, struct ifreq *ifr, int cmd)
+{
+ int err = 0;
+ struct ip_tunnel_parm p;
+ struct ip_tunnel *t;
+
+ MOD_INC_USE_COUNT;
+
+ switch (cmd) {
+ case SIOCGETTUNNEL:
+ t = NULL;
+ if (dev == &ipip_fb_tunnel_dev) {
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
+ err = -EFAULT;
+ break;
+ }
+ t = ipip_tunnel_locate(&p, 0);
+ }
+ if (t == NULL)
+ t = (struct ip_tunnel*)dev->priv;
+ memcpy(&p, &t->parms, sizeof(p));
+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
+ err = -EFAULT;
+ break;
+
+ case SIOCADDTUNNEL:
+ case SIOCCHGTUNNEL:
+ err = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ goto done;
+
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ goto done;
+
+ err = -EINVAL;
+ if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP ||
+ p.iph.ihl != 5 || (p.iph.frag_off&__constant_htons(~IP_DF)))
+ goto done;
+ if (p.iph.ttl)
+ p.iph.frag_off |= __constant_htons(IP_DF);
+
+ t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
+
+ if (dev != &ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL &&
+ t != &ipip_fb_tunnel) {
+ if (t != NULL) {
+ if (t->dev != dev) {
+ err = -EEXIST;
+ break;
+ }
+ } else {
+ if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) ||
+ (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) {
+ err = -EINVAL;
+ break;
+ }
+ t = (struct ip_tunnel*)dev->priv;
+ start_bh_atomic();
+ ipip_tunnel_unlink(t);
+ t->parms.iph.saddr = p.iph.saddr;
+ t->parms.iph.daddr = p.iph.daddr;
+ memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ memcpy(dev->broadcast, &p.iph.daddr, 4);
+ ipip_tunnel_link(t);
+ end_bh_atomic();
+ netdev_state_change(dev);
+ }
+ }
+
+ if (t) {
+ err = 0;
+ if (cmd == SIOCCHGTUNNEL) {
+ t->parms.iph.ttl = p.iph.ttl;
+ t->parms.iph.tos = p.iph.tos;
+ t->parms.iph.frag_off = p.iph.frag_off;
+ }
+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
+ err = -EFAULT;
+ } else
+ err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
+ break;
+
+ case SIOCDELTUNNEL:
+ err = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ goto done;
+
+ if (dev == &ipip_fb_tunnel_dev) {
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ goto done;
+ err = -ENOENT;
+ if ((t = ipip_tunnel_locate(&p, 0)) == NULL)
+ goto done;
+ err = -EPERM;
+ if (t == &ipip_fb_tunnel)
+ goto done;
+ }
+ err = unregister_netdevice(dev);
+ break;
+
+ default:
+ err = -EINVAL;
+ }
+
+done:
+ MOD_DEC_USE_COUNT;
+ return err;
+}
+
+static struct net_device_stats *ipip_tunnel_get_stats(struct device *dev)
+{
+ return &(((struct ip_tunnel*)dev->priv)->stat);
+}
+
+static int ipip_tunnel_change_mtu(struct device *dev, int new_mtu)
+{
+ if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr))
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static void ipip_tunnel_init_gen(struct device *dev)
+{
+ struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
+
+ dev->destructor = ipip_tunnel_destroy;
+ dev->hard_start_xmit = ipip_tunnel_xmit;
+ dev->get_stats = ipip_tunnel_get_stats;
+ dev->do_ioctl = ipip_tunnel_ioctl;
+ dev->change_mtu = ipip_tunnel_change_mtu;
+
+ dev_init_buffers(dev);
+
+ dev->type = ARPHRD_TUNNEL;
+ dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr);
+ dev->mtu = 1500 - sizeof(struct iphdr);
+ dev->flags = IFF_NOARP;
+ dev->iflink = 0;
+ dev->addr_len = 4;
+ memcpy(dev->dev_addr, &t->parms.iph.saddr, 4);
+ memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
+}
+
+static int ipip_tunnel_init(struct device *dev)
+{
+ struct device *tdev = NULL;
+ struct ip_tunnel *tunnel;
+ struct iphdr *iph;
+
+ tunnel = (struct ip_tunnel*)dev->priv;
+ iph = &tunnel->parms.iph;
+
+ ipip_tunnel_init_gen(dev);
+
+ if (iph->daddr) {
+ struct rtable *rt;
+ if (!ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), tunnel->parms.link)) {
+ tdev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ }
+ dev->flags |= IFF_POINTOPOINT;
+ }
+
+ if (!tdev && tunnel->parms.link)
+ tdev = dev_get_by_index(tunnel->parms.link);
+
+ if (tdev) {
+ dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+ dev->mtu = tdev->mtu - sizeof(struct iphdr);
+ }
+ dev->iflink = tunnel->parms.link;
+
+ return 0;
+}
+
+#ifdef MODULE
+static int ipip_fb_tunnel_open(struct device *dev)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int ipip_fb_tunnel_close(struct device *dev)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+#endif
+
+__initfunc(int ipip_fb_tunnel_init(struct device *dev))
+{
+ struct iphdr *iph;
+
+ ipip_tunnel_init_gen(dev);
+#ifdef MODULE
+ dev->open = ipip_fb_tunnel_open;
+ dev->stop = ipip_fb_tunnel_close;
+#endif
+
+ iph = &ipip_fb_tunnel.parms.iph;
+ iph->version = 4;
+ iph->protocol = IPPROTO_IPIP;
+ iph->ihl = 5;
+
+ tunnels_wc[0] = &ipip_fb_tunnel;
+ return 0;
+}
+
+static struct inet_protocol ipip_protocol = {
+ ipip_rcv, /* IPIP handler */
+ ipip_err, /* TUNNEL error control */
+ 0, /* next */
+ IPPROTO_IPIP, /* protocol ID */
+ 0, /* copy */
+ NULL, /* data */
+ "IPIP" /* name */
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int ipip_init(void))
+#endif
+{
+ printk(KERN_INFO "IPv4 over IPv4 tunneling driver\n");
+
+ ipip_fb_tunnel_dev.priv = (void*)&ipip_fb_tunnel;
+ ipip_fb_tunnel_dev.name = ipip_fb_tunnel.parms.name;
+#ifdef MODULE
+ register_netdev(&ipip_fb_tunnel_dev);
+#else
+ register_netdevice(&ipip_fb_tunnel_dev);
+#endif
+
+ inet_add_protocol(&ipip_protocol);
+ return 0;
+}
+
+#ifdef MODULE
+
+void cleanup_module(void)
+{
+ if ( inet_del_protocol(&ipip_protocol) < 0 )
+ printk(KERN_INFO "ipip close: can't remove protocol\n");
+
+ unregister_netdevice(&ipip_fb_tunnel_dev);
+}
+
+#endif
diff --git a/pfinet/linux-src/net/ipv4/ipmr.c b/pfinet/linux-src/net/ipv4/ipmr.c
new file mode 100644
index 00000000..cd51cd9a
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/ipmr.c
@@ -0,0 +1,1609 @@
+/*
+ * IP multicast routing support for mrouted 3.6/3.8
+ *
+ * (c) 1995 Alan Cox, <alan@redhat.com>
+ * Linux Consultancy and Custom Driver Development
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Version: $Id: ipmr.c,v 1.40.2.2 1999/06/20 21:27:44 davem Exp $
+ *
+ * Fixes:
+ * Michael Chastain : Incorrect size of copying.
+ * Alan Cox : Added the cache manager code
+ * Alan Cox : Fixed the clone/copy bug and device race.
+ * Mike McLagan : Routing by source
+ * Malcolm Beattie : Buffer handling fixes.
+ * Alexey Kuznetsov : Double buffer free and other fixes.
+ * SVR Anand : Fixed several multicast bugs and problems.
+ * Alexey Kuznetsov : Status, optimisations and more.
+ * Brad Parker : Better behaviour on mrouted upcall
+ * overflow.
+ * Carlos Picoto : PIMv1 Support
+ * Pavlin Ivanov Radoslavov: PIMv2 Registers must checksum only PIM header
+ * Relax this requrement to work with older peers.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#include <linux/proc_fs.h>
+#include <linux/mroute.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/raw.h>
+#include <linux/notifier.h>
+#include <linux/if_arp.h>
+#include <linux/ip_fw.h>
+#include <linux/firewall.h>
+#include <net/ipip.h>
+#include <net/checksum.h>
+
+#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
+#define CONFIG_IP_PIMSM 1
+#endif
+
+/*
+ * Multicast router control variables
+ */
+
+static struct vif_device vif_table[MAXVIFS]; /* Devices */
+static unsigned long vifc_map; /* Active device map */
+static int maxvif;
+int mroute_do_assert = 0; /* Set in PIM assert */
+int mroute_do_pim = 0;
+static struct mfc_cache *mfc_cache_array[MFC_LINES]; /* Forwarding cache */
+int cache_resolve_queue_len = 0; /* Size of unresolved */
+
+static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local);
+static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert);
+static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm);
+
+extern struct inet_protocol pim_protocol;
+
+static
+struct device *ipmr_new_tunnel(struct vifctl *v)
+{
+ struct device *dev = NULL;
+
+ rtnl_lock();
+ dev = dev_get("tunl0");
+
+ if (dev) {
+ int err;
+ struct ifreq ifr;
+ mm_segment_t oldfs;
+ struct ip_tunnel_parm p;
+ struct in_device *in_dev;
+
+ memset(&p, 0, sizeof(p));
+ p.iph.daddr = v->vifc_rmt_addr.s_addr;
+ p.iph.saddr = v->vifc_lcl_addr.s_addr;
+ p.iph.version = 4;
+ p.iph.ihl = 5;
+ p.iph.protocol = IPPROTO_IPIP;
+ sprintf(p.name, "dvmrp%d", v->vifc_vifi);
+ ifr.ifr_ifru.ifru_data = (void*)&p;
+
+ oldfs = get_fs(); set_fs(KERNEL_DS);
+ err = dev->do_ioctl(dev, &ifr, SIOCADDTUNNEL);
+ set_fs(oldfs);
+
+ if (err == 0 && (dev = dev_get(p.name)) != NULL) {
+ dev->flags |= IFF_MULTICAST;
+
+ in_dev = dev->ip_ptr;
+ if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL)
+ goto failure;
+ in_dev->cnf.rp_filter = 0;
+
+ if (dev_open(dev))
+ goto failure;
+ }
+ }
+ rtnl_unlock();
+ return dev;
+
+failure:
+ unregister_netdevice(dev);
+ rtnl_unlock();
+ return NULL;
+}
+
+#ifdef CONFIG_IP_PIMSM
+
+static int reg_vif_num = -1;
+static struct device * reg_dev;
+
+static int reg_vif_xmit(struct sk_buff *skb, struct device *dev)
+{
+ ((struct net_device_stats*)dev->priv)->tx_bytes += skb->len;
+ ((struct net_device_stats*)dev->priv)->tx_packets++;
+ ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT);
+ kfree_skb(skb);
+ return 0;
+}
+
+static struct net_device_stats *reg_vif_get_stats(struct device *dev)
+{
+ return (struct net_device_stats*)dev->priv;
+}
+
+static
+struct device *ipmr_reg_vif(struct vifctl *v)
+{
+ struct device *dev;
+ struct in_device *in_dev;
+ int size;
+
+ size = sizeof(*dev) + IFNAMSIZ + sizeof(struct net_device_stats);
+ dev = kmalloc(size, GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ memset(dev, 0, size);
+
+ dev->priv = dev + 1;
+ dev->name = dev->priv + sizeof(struct net_device_stats);
+
+ strcpy(dev->name, "pimreg");
+
+ dev->type = ARPHRD_PIMREG;
+ dev->mtu = 1500 - sizeof(struct iphdr) - 8;
+ dev->flags = IFF_NOARP;
+ dev->hard_start_xmit = reg_vif_xmit;
+ dev->get_stats = reg_vif_get_stats;
+
+ rtnl_lock();
+
+ if (register_netdevice(dev)) {
+ rtnl_unlock();
+ kfree(dev);
+ return NULL;
+ }
+ dev->iflink = 0;
+
+ if ((in_dev = inetdev_init(dev)) == NULL)
+ goto failure;
+
+ in_dev->cnf.rp_filter = 0;
+
+ if (dev_open(dev))
+ goto failure;
+
+ rtnl_unlock();
+ reg_dev = dev;
+ return dev;
+
+failure:
+ unregister_netdevice(dev);
+ rtnl_unlock();
+ kfree(dev);
+ return NULL;
+}
+#endif
+
+/*
+ * Delete a VIF entry
+ */
+
+static int vif_delete(int vifi)
+{
+ struct vif_device *v;
+ struct device *dev;
+ struct in_device *in_dev;
+
+ if (vifi < 0 || vifi >= maxvif || !(vifc_map&(1<<vifi)))
+ return -EADDRNOTAVAIL;
+
+ v = &vif_table[vifi];
+
+ dev = v->dev;
+ v->dev = NULL;
+ vifc_map &= ~(1<<vifi);
+
+ if ((in_dev = dev->ip_ptr) != NULL)
+ in_dev->cnf.mc_forwarding = 0;
+
+ dev_set_allmulti(dev, -1);
+ ip_rt_multicast_event(in_dev);
+
+ if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER)) {
+#ifdef CONFIG_IP_PIMSM
+ if (vifi == reg_vif_num) {
+ reg_vif_num = -1;
+ reg_dev = NULL;
+ }
+#endif
+ unregister_netdevice(dev);
+ if (v->flags&VIFF_REGISTER)
+ kfree(dev);
+ }
+
+ if (vifi+1 == maxvif) {
+ int tmp;
+ for (tmp=vifi-1; tmp>=0; tmp--) {
+ if (vifc_map&(1<<tmp))
+ break;
+ }
+ maxvif = tmp+1;
+ }
+ return 0;
+}
+
+static void ipmr_update_threshoulds(struct mfc_cache *cache, unsigned char *ttls)
+{
+ int vifi;
+
+ start_bh_atomic();
+
+ cache->mfc_minvif = MAXVIFS;
+ cache->mfc_maxvif = 0;
+ memset(cache->mfc_ttls, 255, MAXVIFS);
+
+ for (vifi=0; vifi<maxvif; vifi++) {
+ if (vifc_map&(1<<vifi) && ttls[vifi] && ttls[vifi] < 255) {
+ cache->mfc_ttls[vifi] = ttls[vifi];
+ if (cache->mfc_minvif > vifi)
+ cache->mfc_minvif = vifi;
+ if (cache->mfc_maxvif <= vifi)
+ cache->mfc_maxvif = vifi + 1;
+ }
+ }
+ end_bh_atomic();
+}
+
+/*
+ * Delete a multicast route cache entry
+ */
+
+static void ipmr_cache_delete(struct mfc_cache *cache)
+{
+ struct sk_buff *skb;
+ int line;
+ struct mfc_cache **cp;
+
+ /*
+ * Find the right cache line
+ */
+
+ line=MFC_HASH(cache->mfc_mcastgrp,cache->mfc_origin);
+ cp=&(mfc_cache_array[line]);
+
+ if(cache->mfc_flags&MFC_QUEUED)
+ del_timer(&cache->mfc_timer);
+
+ /*
+ * Unlink the buffer
+ */
+
+ while(*cp!=NULL)
+ {
+ if(*cp==cache)
+ {
+ *cp=cache->next;
+ break;
+ }
+ cp=&((*cp)->next);
+ }
+
+ /*
+ * Free the buffer. If it is a pending resolution
+ * clean up the other resources.
+ */
+
+ if(cache->mfc_flags&MFC_QUEUED)
+ {
+ cache_resolve_queue_len--;
+ while((skb=skb_dequeue(&cache->mfc_unresolved))) {
+#ifdef CONFIG_RTNETLINK
+ if (skb->nh.iph->version == 0) {
+ struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
+ nlh->nlmsg_type = NLMSG_ERROR;
+ nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
+ skb_trim(skb, nlh->nlmsg_len);
+ ((struct nlmsgerr*)NLMSG_DATA(nlh))->error = -ETIMEDOUT;
+ netlink_unicast(rtnl, skb, NETLINK_CB(skb).dst_pid, MSG_DONTWAIT);
+ } else
+#endif
+ kfree_skb(skb);
+ }
+ }
+ kfree_s(cache,sizeof(cache));
+}
+
+/*
+ * Cache expiry timer
+ */
+
+static void ipmr_cache_timer(unsigned long data)
+{
+ struct mfc_cache *cache=(struct mfc_cache *)data;
+ ipmr_cache_delete(cache);
+}
+
+/*
+ * Insert a multicast cache entry
+ */
+
+static void ipmr_cache_insert(struct mfc_cache *c)
+{
+ int line=MFC_HASH(c->mfc_mcastgrp,c->mfc_origin);
+ c->next=mfc_cache_array[line];
+ mfc_cache_array[line]=c;
+}
+
+/*
+ * Find a multicast cache entry
+ */
+
+struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp)
+{
+ int line=MFC_HASH(mcastgrp,origin);
+ struct mfc_cache *cache;
+
+ cache=mfc_cache_array[line];
+ while(cache!=NULL)
+ {
+ if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
+ return cache;
+ cache=cache->next;
+ }
+ return NULL;
+}
+
+/*
+ * Allocate a multicast cache entry
+ */
+
+static struct mfc_cache *ipmr_cache_alloc(int priority)
+{
+ struct mfc_cache *c=(struct mfc_cache *)kmalloc(sizeof(struct mfc_cache), priority);
+ if(c==NULL)
+ return NULL;
+ memset(c, 0, sizeof(*c));
+ skb_queue_head_init(&c->mfc_unresolved);
+ init_timer(&c->mfc_timer);
+ c->mfc_timer.data=(long)c;
+ c->mfc_timer.function=ipmr_cache_timer;
+ c->mfc_minvif = MAXVIFS;
+ return c;
+}
+
+/*
+ * A cache entry has gone into a resolved state from queued
+ */
+
+static void ipmr_cache_resolve(struct mfc_cache *cache)
+{
+ struct sk_buff *skb;
+
+ start_bh_atomic();
+
+ /*
+ * Kill the queue entry timer.
+ */
+
+ del_timer(&cache->mfc_timer);
+
+ if (cache->mfc_flags&MFC_QUEUED) {
+ cache->mfc_flags&=~MFC_QUEUED;
+ cache_resolve_queue_len--;
+ }
+
+ end_bh_atomic();
+
+ /*
+ * Play the pending entries through our router
+ */
+ while((skb=skb_dequeue(&cache->mfc_unresolved))) {
+#ifdef CONFIG_RTNETLINK
+ if (skb->nh.iph->version == 0) {
+ int err;
+ struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
+
+ if (ipmr_fill_mroute(skb, cache, NLMSG_DATA(nlh)) > 0) {
+ nlh->nlmsg_len = skb->tail - (u8*)nlh;
+ } else {
+ nlh->nlmsg_type = NLMSG_ERROR;
+ nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
+ skb_trim(skb, nlh->nlmsg_len);
+ ((struct nlmsgerr*)NLMSG_DATA(nlh))->error = -EMSGSIZE;
+ }
+ err = netlink_unicast(rtnl, skb, NETLINK_CB(skb).dst_pid, MSG_DONTWAIT);
+ } else
+#endif
+ ip_mr_forward(skb, cache, 0);
+ }
+}
+
+/*
+ * Bounce a cache query up to mrouted. We could use netlink for this but mrouted
+ * expects the following bizarre scheme..
+ */
+
+static int ipmr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert)
+{
+ struct sk_buff *skb;
+ int ihl = pkt->nh.iph->ihl<<2;
+ struct igmphdr *igmp;
+ struct igmpmsg *msg;
+ int ret;
+
+ if (mroute_socket==NULL)
+ return -EINVAL;
+
+#ifdef CONFIG_IP_PIMSM
+ if (assert == IGMPMSG_WHOLEPKT)
+ skb = skb_realloc_headroom(pkt, sizeof(struct iphdr));
+ else
+#endif
+ skb = alloc_skb(128, GFP_ATOMIC);
+
+ if(!skb)
+ return -ENOBUFS;
+
+#ifdef CONFIG_IP_PIMSM
+ if (assert == IGMPMSG_WHOLEPKT) {
+ /* Ugly, but we have no choice with this interface.
+ Duplicate old header, fix ihl, length etc.
+ And all this only to mangle msg->im_msgtype and
+ to set msg->im_mbz to "mbz" :-)
+ */
+ msg = (struct igmpmsg*)skb_push(skb, sizeof(struct iphdr));
+ skb->nh.raw = skb->h.raw = (u8*)msg;
+ memcpy(msg, pkt->nh.raw, sizeof(struct iphdr));
+ msg->im_msgtype = IGMPMSG_WHOLEPKT;
+ msg->im_mbz = 0;
+ msg->im_vif = reg_vif_num;
+ skb->nh.iph->ihl = sizeof(struct iphdr) >> 2;
+ skb->nh.iph->tot_len = htons(ntohs(pkt->nh.iph->tot_len) + sizeof(struct iphdr));
+ } else
+#endif
+ {
+
+ /*
+ * Copy the IP header
+ */
+
+ skb->nh.iph = (struct iphdr *)skb_put(skb, ihl);
+ memcpy(skb->data,pkt->data,ihl);
+ skb->nh.iph->protocol = 0; /* Flag to the kernel this is a route add */
+ msg = (struct igmpmsg*)skb->nh.iph;
+ msg->im_vif = vifi;
+ skb->dst = dst_clone(pkt->dst);
+
+ /*
+ * Add our header
+ */
+
+ igmp=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
+ igmp->type =
+ msg->im_msgtype = assert;
+ igmp->code = 0;
+ skb->nh.iph->tot_len=htons(skb->len); /* Fix the length */
+ skb->h.raw = skb->nh.raw;
+ }
+
+ /*
+ * Deliver to mrouted
+ */
+ if ((ret=sock_queue_rcv_skb(mroute_socket,skb))<0) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "mroute: pending queue full, dropping entries.\n");
+ kfree_skb(skb);
+ }
+
+ return ret;
+}
+
+/*
+ * Queue a packet for resolution
+ */
+
+static int ipmr_cache_unresolved(struct mfc_cache *cache, vifi_t vifi, struct sk_buff *skb)
+{
+ if(cache==NULL)
+ {
+ /*
+ * Create a new entry if allowable
+ */
+ if(cache_resolve_queue_len>=10 || (cache=ipmr_cache_alloc(GFP_ATOMIC))==NULL)
+ {
+ kfree_skb(skb);
+ return -ENOBUFS;
+ }
+ /*
+ * Fill in the new cache entry
+ */
+ cache->mfc_parent=ALL_VIFS;
+ cache->mfc_origin=skb->nh.iph->saddr;
+ cache->mfc_mcastgrp=skb->nh.iph->daddr;
+ cache->mfc_flags=MFC_QUEUED;
+ /*
+ * Link to the unresolved list
+ */
+ ipmr_cache_insert(cache);
+ cache_resolve_queue_len++;
+ /*
+ * Fire off the expiry timer
+ */
+ cache->mfc_timer.expires=jiffies+10*HZ;
+ add_timer(&cache->mfc_timer);
+ /*
+ * Reflect first query at mrouted.
+ */
+ if(mroute_socket)
+ {
+ /* If the report failed throw the cache entry
+ out - Brad Parker
+
+ OK, OK, Brad. Only do not forget to free skb
+ and return :-) --ANK
+ */
+ if (ipmr_cache_report(skb, vifi, IGMPMSG_NOCACHE)<0) {
+ ipmr_cache_delete(cache);
+ kfree_skb(skb);
+ return -ENOBUFS;
+ }
+ }
+ }
+ /*
+ * See if we can append the packet
+ */
+ if(cache->mfc_queuelen>3)
+ {
+ kfree_skb(skb);
+ return -ENOBUFS;
+ }
+ cache->mfc_queuelen++;
+ skb_queue_tail(&cache->mfc_unresolved,skb);
+ return 0;
+}
+
+/*
+ * MFC cache manipulation by user space mroute daemon
+ */
+
+int ipmr_mfc_modify(int action, struct mfcctl *mfc)
+{
+ struct mfc_cache *cache;
+
+ if(!MULTICAST(mfc->mfcc_mcastgrp.s_addr))
+ return -EINVAL;
+ /*
+ * Find the cache line
+ */
+
+ start_bh_atomic();
+
+ cache=ipmr_cache_find(mfc->mfcc_origin.s_addr,mfc->mfcc_mcastgrp.s_addr);
+
+ /*
+ * Delete an entry
+ */
+ if(action==MRT_DEL_MFC)
+ {
+ if(cache)
+ {
+ ipmr_cache_delete(cache);
+ end_bh_atomic();
+ return 0;
+ }
+ end_bh_atomic();
+ return -ENOENT;
+ }
+ if(cache)
+ {
+
+ /*
+ * Update the cache, see if it frees a pending queue
+ */
+
+ cache->mfc_flags|=MFC_RESOLVED;
+ cache->mfc_parent=mfc->mfcc_parent;
+ ipmr_update_threshoulds(cache, mfc->mfcc_ttls);
+
+ /*
+ * Check to see if we resolved a queued list. If so we
+ * need to send on the frames and tidy up.
+ */
+
+ if(cache->mfc_flags&MFC_QUEUED)
+ ipmr_cache_resolve(cache); /* Unhook & send the frames */
+ end_bh_atomic();
+ return 0;
+ }
+
+ /*
+ * Unsolicited update - that's ok, add anyway.
+ */
+
+
+ cache=ipmr_cache_alloc(GFP_ATOMIC);
+ if(cache==NULL)
+ {
+ end_bh_atomic();
+ return -ENOMEM;
+ }
+ cache->mfc_flags=MFC_RESOLVED;
+ cache->mfc_origin=mfc->mfcc_origin.s_addr;
+ cache->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
+ cache->mfc_parent=mfc->mfcc_parent;
+ ipmr_update_threshoulds(cache, mfc->mfcc_ttls);
+ ipmr_cache_insert(cache);
+ end_bh_atomic();
+ return 0;
+}
+
+static void mrtsock_destruct(struct sock *sk)
+{
+ if (sk == mroute_socket) {
+ ipv4_devconf.mc_forwarding = 0;
+
+ mroute_socket=NULL;
+ synchronize_bh();
+
+ mroute_close(sk);
+ }
+}
+
+/*
+ * Socket options and virtual interface manipulation. The whole
+ * virtual interface system is a complete heap, but unfortunately
+ * that's how BSD mrouted happens to think. Maybe one day with a proper
+ * MOSPF/PIM router set up we can clean this up.
+ */
+
+int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
+{
+ struct vifctl vif;
+ struct mfcctl mfc;
+
+ if(optname!=MRT_INIT)
+ {
+ if(sk!=mroute_socket)
+ return -EACCES;
+ }
+
+ switch(optname)
+ {
+ case MRT_INIT:
+ if(sk->type!=SOCK_RAW || sk->num!=IPPROTO_IGMP)
+ return -EOPNOTSUPP;
+ if(optlen!=sizeof(int))
+ return -ENOPROTOOPT;
+ {
+ int opt;
+ if (get_user(opt,(int *)optval))
+ return -EFAULT;
+ if (opt != 1)
+ return -ENOPROTOOPT;
+ }
+ if(mroute_socket)
+ return -EADDRINUSE;
+ mroute_socket=sk;
+ ipv4_devconf.mc_forwarding = 1;
+ if (ip_ra_control(sk, 1, mrtsock_destruct) == 0)
+ return 0;
+ mrtsock_destruct(sk);
+ return -EADDRINUSE;
+ case MRT_DONE:
+ return ip_ra_control(sk, 0, NULL);
+ case MRT_ADD_VIF:
+ case MRT_DEL_VIF:
+ if(optlen!=sizeof(vif))
+ return -EINVAL;
+ if (copy_from_user(&vif,optval,sizeof(vif)))
+ return -EFAULT;
+ if(vif.vifc_vifi >= MAXVIFS)
+ return -ENFILE;
+ if(optname==MRT_ADD_VIF)
+ {
+ struct vif_device *v=&vif_table[vif.vifc_vifi];
+ struct device *dev;
+ struct in_device *in_dev;
+
+ /* Is vif busy ? */
+ if (vifc_map&(1<<vif.vifc_vifi))
+ return -EADDRINUSE;
+
+ switch (vif.vifc_flags) {
+#ifdef CONFIG_IP_PIMSM
+ case VIFF_REGISTER:
+
+ /*
+ * Special Purpose VIF in PIM
+ * All the packets will be sent to the daemon
+ */
+ if (reg_vif_num >= 0)
+ return -EADDRINUSE;
+ reg_vif_num = vif.vifc_vifi;
+ dev = ipmr_reg_vif(&vif);
+ if (!dev) {
+ reg_vif_num = -1;
+ return -ENOBUFS;
+ }
+ break;
+#endif
+ case VIFF_TUNNEL:
+ dev = ipmr_new_tunnel(&vif);
+ if (!dev)
+ return -ENOBUFS;
+ break;
+ case 0:
+ dev=ip_dev_find(vif.vifc_lcl_addr.s_addr);
+ if (!dev)
+ return -EADDRNOTAVAIL;
+ break;
+ default:
+#if 0
+ printk(KERN_DEBUG "ipmr_add_vif: flags %02x\n", vif.vifc_flags);
+#endif
+ return -EINVAL;
+ }
+
+ if ((in_dev = dev->ip_ptr) == NULL)
+ return -EADDRNOTAVAIL;
+ if (in_dev->cnf.mc_forwarding)
+ return -EADDRINUSE;
+ in_dev->cnf.mc_forwarding = 1;
+ dev_set_allmulti(dev, +1);
+ ip_rt_multicast_event(in_dev);
+
+ /*
+ * Fill in the VIF structures
+ */
+ start_bh_atomic();
+ v->rate_limit=vif.vifc_rate_limit;
+ v->local=vif.vifc_lcl_addr.s_addr;
+ v->remote=vif.vifc_rmt_addr.s_addr;
+ v->flags=vif.vifc_flags;
+ v->threshold=vif.vifc_threshold;
+ v->dev=dev;
+ v->bytes_in = 0;
+ v->bytes_out = 0;
+ v->pkt_in = 0;
+ v->pkt_out = 0;
+ v->link = dev->ifindex;
+ if (vif.vifc_flags&(VIFF_TUNNEL|VIFF_REGISTER))
+ v->link = dev->iflink;
+ vifc_map|=(1<<vif.vifc_vifi);
+ if (vif.vifc_vifi+1 > maxvif)
+ maxvif = vif.vifc_vifi+1;
+ end_bh_atomic();
+ return 0;
+ } else {
+ int ret;
+ rtnl_lock();
+ ret = vif_delete(vif.vifc_vifi);
+ rtnl_unlock();
+ return ret;
+ }
+
+ /*
+ * Manipulate the forwarding caches. These live
+ * in a sort of kernel/user symbiosis.
+ */
+ case MRT_ADD_MFC:
+ case MRT_DEL_MFC:
+ if(optlen!=sizeof(mfc))
+ return -EINVAL;
+ if (copy_from_user(&mfc,optval, sizeof(mfc)))
+ return -EFAULT;
+ return ipmr_mfc_modify(optname, &mfc);
+ /*
+ * Control PIM assert.
+ */
+ case MRT_ASSERT:
+ {
+ int v;
+ if(get_user(v,(int *)optval))
+ return -EFAULT;
+ mroute_do_assert=(v)?1:0;
+ return 0;
+ }
+#ifdef CONFIG_IP_PIMSM
+ case MRT_PIM:
+ {
+ int v;
+ if(get_user(v,(int *)optval))
+ return -EFAULT;
+ v = (v)?1:0;
+ if (v != mroute_do_pim) {
+ mroute_do_pim = v;
+ mroute_do_assert = v;
+#ifdef CONFIG_IP_PIMSM_V2
+ if (mroute_do_pim)
+ inet_add_protocol(&pim_protocol);
+ else
+ inet_del_protocol(&pim_protocol);
+#endif
+ }
+ return 0;
+ }
+#endif
+ /*
+ * Spurious command, or MRT_VERSION which you cannot
+ * set.
+ */
+ default:
+ return -ENOPROTOOPT;
+ }
+}
+
+/*
+ * Getsock opt support for the multicast routing system.
+ */
+
+int ip_mroute_getsockopt(struct sock *sk,int optname,char *optval,int *optlen)
+{
+ int olr;
+ int val;
+
+ if(sk!=mroute_socket)
+ return -EACCES;
+ if(optname!=MRT_VERSION &&
+#ifdef CONFIG_IP_PIMSM
+ optname!=MRT_PIM &&
+#endif
+ optname!=MRT_ASSERT)
+ return -ENOPROTOOPT;
+
+ if(get_user(olr, optlen))
+ return -EFAULT;
+
+ olr=min(olr,sizeof(int));
+ if(put_user(olr,optlen))
+ return -EFAULT;
+ if(optname==MRT_VERSION)
+ val=0x0305;
+#ifdef CONFIG_IP_PIMSM
+ else if(optname==MRT_PIM)
+ val=mroute_do_pim;
+#endif
+ else
+ val=mroute_do_assert;
+ if(copy_to_user(optval,&val,olr))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ * The IP multicast ioctl support routines.
+ */
+
+int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+ struct sioc_sg_req sr;
+ struct sioc_vif_req vr;
+ struct vif_device *vif;
+ struct mfc_cache *c;
+
+ switch(cmd)
+ {
+ case SIOCGETVIFCNT:
+ if (copy_from_user(&vr,(void *)arg,sizeof(vr)))
+ return -EFAULT;
+ if(vr.vifi>=maxvif)
+ return -EINVAL;
+ vif=&vif_table[vr.vifi];
+ if(vifc_map&(1<<vr.vifi))
+ {
+ vr.icount=vif->pkt_in;
+ vr.ocount=vif->pkt_out;
+ vr.ibytes=vif->bytes_in;
+ vr.obytes=vif->bytes_out;
+ if (copy_to_user((void *)arg,&vr,sizeof(vr)))
+ return -EFAULT;
+ return 0;
+ }
+ return -EADDRNOTAVAIL;
+ case SIOCGETSGCNT:
+ if (copy_from_user(&sr,(void *)arg,sizeof(sr)))
+ return -EFAULT;
+ for (c = mfc_cache_array[MFC_HASH(sr.grp.s_addr, sr.src.s_addr)];
+ c; c = c->next) {
+ if (sr.grp.s_addr == c->mfc_mcastgrp &&
+ sr.src.s_addr == c->mfc_origin) {
+ sr.pktcnt = c->mfc_pkt;
+ sr.bytecnt = c->mfc_bytes;
+ sr.wrong_if = c->mfc_wrong_if;
+ if (copy_to_user((void *)arg,&sr,sizeof(sr)))
+ return -EFAULT;
+ return 0;
+ }
+ }
+ return -EADDRNOTAVAIL;
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/*
+ * Close the multicast socket, and clear the vif tables etc
+ */
+
+void mroute_close(struct sock *sk)
+{
+ int i;
+
+ /*
+ * Shut down all active vif entries
+ */
+ rtnl_lock();
+ for(i=0; i<maxvif; i++)
+ vif_delete(i);
+ rtnl_unlock();
+
+ /*
+ * Wipe the cache
+ */
+ for(i=0;i<MFC_LINES;i++)
+ {
+ start_bh_atomic();
+ while(mfc_cache_array[i]!=NULL)
+ ipmr_cache_delete(mfc_cache_array[i]);
+ end_bh_atomic();
+ }
+}
+
+static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct vif_device *v;
+ int ct;
+ if (event != NETDEV_UNREGISTER)
+ return NOTIFY_DONE;
+ v=&vif_table[0];
+ for(ct=0;ct<maxvif;ct++) {
+ if (vifc_map&(1<<ct) && v->dev==ptr)
+ vif_delete(ct);
+ v++;
+ }
+ return NOTIFY_DONE;
+}
+
+
+static struct notifier_block ip_mr_notifier={
+ ipmr_device_event,
+ NULL,
+ 0
+};
+
+/*
+ * Encapsulate a packet by attaching a valid IPIP header to it.
+ * This avoids tunnel drivers and other mess and gives us the speed so
+ * important for multicast video.
+ */
+
+static void ip_encap(struct sk_buff *skb, u32 saddr, u32 daddr)
+{
+ struct iphdr *iph = (struct iphdr *)skb_push(skb,sizeof(struct iphdr));
+
+ iph->version = 4;
+ iph->tos = skb->nh.iph->tos;
+ iph->ttl = skb->nh.iph->ttl;
+ iph->frag_off = 0;
+ iph->daddr = daddr;
+ iph->saddr = saddr;
+ iph->protocol = IPPROTO_IPIP;
+ iph->ihl = 5;
+ iph->tot_len = htons(skb->len);
+ iph->id = htons(ip_id_count++);
+ ip_send_check(iph);
+
+ skb->h.ipiph = skb->nh.iph;
+ skb->nh.iph = iph;
+}
+
+/*
+ * Processing handlers for ipmr_forward
+ */
+
+static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c,
+ int vifi, int last)
+{
+ struct iphdr *iph = skb->nh.iph;
+ struct vif_device *vif = &vif_table[vifi];
+ struct device *dev;
+ struct rtable *rt;
+ int encap = 0;
+ struct sk_buff *skb2;
+
+#ifdef CONFIG_IP_PIMSM
+ if (vif->flags & VIFF_REGISTER) {
+ vif->pkt_out++;
+ vif->bytes_out+=skb->len;
+ ((struct net_device_stats*)vif->dev->priv)->tx_bytes += skb->len;
+ ((struct net_device_stats*)vif->dev->priv)->tx_packets++;
+ ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT);
+ return;
+ }
+#endif
+
+ if (vif->flags&VIFF_TUNNEL) {
+ if (ip_route_output(&rt, vif->remote, vif->local, RT_TOS(iph->tos), vif->link))
+ return;
+ encap = sizeof(struct iphdr);
+ } else {
+ if (ip_route_output(&rt, iph->daddr, 0, RT_TOS(iph->tos), vif->link))
+ return;
+ }
+
+ dev = rt->u.dst.dev;
+
+ if (skb->len+encap > rt->u.dst.pmtu && (ntohs(iph->frag_off) & IP_DF)) {
+ /* Do not fragment multicasts. Alas, IPv4 does not
+ allow to send ICMP, so that packets will disappear
+ to blackhole.
+ */
+
+ ip_statistics.IpFragFails++;
+ ip_rt_put(rt);
+ return;
+ }
+
+ encap += dev->hard_header_len;
+
+ if (skb_headroom(skb) < encap || skb_cloned(skb) || !last)
+ skb2 = skb_realloc_headroom(skb, (encap + 15)&~15);
+ else if (atomic_read(&skb->users) != 1)
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ else {
+ atomic_inc(&skb->users);
+ skb2 = skb;
+ }
+
+ if (skb2 == NULL) {
+ ip_rt_put(rt);
+ return;
+ }
+
+ vif->pkt_out++;
+ vif->bytes_out+=skb->len;
+
+ dst_release(skb2->dst);
+ skb2->dst = &rt->u.dst;
+ iph = skb2->nh.iph;
+ ip_decrease_ttl(iph);
+
+#ifdef CONFIG_FIREWALL
+ if (call_fw_firewall(PF_INET, vif->dev, skb2->nh.iph, NULL, &skb2) < FW_ACCEPT) {
+ kfree_skb(skb2);
+ return;
+ }
+ if (call_out_firewall(PF_INET, vif->dev, skb2->nh.iph, NULL, &skb2) < FW_ACCEPT) {
+ kfree_skb(skb2);
+ return;
+ }
+#endif
+ if (vif->flags & VIFF_TUNNEL) {
+ ip_encap(skb2, vif->local, vif->remote);
+#ifdef CONFIG_FIREWALL
+ /* Double output firewalling on tunnels: one is on tunnel
+ another one is on real device.
+ */
+ if (call_out_firewall(PF_INET, dev, skb2->nh.iph, NULL, &skb2) < FW_ACCEPT) {
+ kfree_skb(skb2);
+ return;
+ }
+#endif
+ ((struct ip_tunnel *)vif->dev->priv)->stat.tx_packets++;
+ ((struct ip_tunnel *)vif->dev->priv)->stat.tx_bytes+=skb2->len;
+ }
+
+ IPCB(skb2)->flags |= IPSKB_FORWARDED;
+
+
+ /*
+ * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
+ * not only before forwarding, but after forwarding on all output
+ * interfaces. It is clear, if mrouter runs a multicasting
+ * program, it should receive packets not depending to what interface
+ * program is joined.
+ * If we will not make it, the program will have to join on all
+ * interfaces. On the other hand, multihoming host (or router, but
+ * not mrouter) cannot join to more than one interface - it will
+ * result in receiving multiple packets.
+ */
+ if (skb2->len <= rt->u.dst.pmtu)
+ skb2->dst->output(skb2);
+ else
+ ip_fragment(skb2, skb2->dst->output);
+}
+
+int ipmr_find_vif(struct device *dev)
+{
+ int ct;
+ for (ct=0; ct<maxvif; ct++) {
+ if (vifc_map&(1<<ct) && vif_table[ct].dev == dev)
+ return ct;
+ }
+ return ALL_VIFS;
+}
+
+/* "local" means that we should preserve one skb (for local delivery) */
+
+int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local)
+{
+ int psend = -1;
+ int vif, ct;
+
+ vif = cache->mfc_parent;
+ cache->mfc_pkt++;
+ cache->mfc_bytes += skb->len;
+
+ /*
+ * Wrong interface: drop packet and (maybe) send PIM assert.
+ */
+ if (vif_table[vif].dev != skb->dev) {
+ int true_vifi;
+
+ if (((struct rtable*)skb->dst)->key.iif == 0) {
+ /* It is our own packet, looped back.
+ Very complicated situation...
+
+ The best workaround until routing daemons will be
+ fixed is not to redistribute packet, if it was
+ send through wrong interface. It means, that
+ multicast applications WILL NOT work for
+ (S,G), which have default multicast route pointing
+ to wrong oif. In any case, it is not a good
+ idea to use multicasting applications on router.
+ */
+ goto dont_forward;
+ }
+
+ cache->mfc_wrong_if++;
+ true_vifi = ipmr_find_vif(skb->dev);
+
+ if (true_vifi < MAXVIFS && mroute_do_assert &&
+ /* pimsm uses asserts, when switching from RPT to SPT,
+ so that we cannot check that packet arrived on an oif.
+ It is bad, but otherwise we would need to move pretty
+ large chunk of pimd to kernel. Ough... --ANK
+ */
+ (mroute_do_pim || cache->mfc_ttls[true_vifi] < 255) &&
+ jiffies - cache->mfc_last_assert > MFC_ASSERT_THRESH) {
+ cache->mfc_last_assert = jiffies;
+ ipmr_cache_report(skb, true_vifi, IGMPMSG_WRONGVIF);
+ }
+ goto dont_forward;
+ }
+
+ vif_table[vif].pkt_in++;
+ vif_table[vif].bytes_in+=skb->len;
+
+ /*
+ * Forward the frame
+ */
+ for (ct = cache->mfc_maxvif-1; ct >= cache->mfc_minvif; ct--) {
+ if (skb->nh.iph->ttl > cache->mfc_ttls[ct]) {
+ if (psend != -1)
+ ipmr_queue_xmit(skb, cache, psend, 0);
+ psend=ct;
+ }
+ }
+ if (psend != -1)
+ ipmr_queue_xmit(skb, cache, psend, !local);
+
+dont_forward:
+ if (!local)
+ kfree_skb(skb);
+ return 0;
+}
+
+
+/*
+ * Multicast packets for forwarding arrive here
+ */
+
+int ip_mr_input(struct sk_buff *skb)
+{
+ struct mfc_cache *cache;
+ int local = ((struct rtable*)skb->dst)->rt_flags&RTCF_LOCAL;
+
+ /* Packet is looped back after forward, it should not be
+ forwarded second time, but still can be delivered locally.
+ */
+ if (IPCB(skb)->flags&IPSKB_FORWARDED)
+ goto dont_forward;
+
+ if (!local) {
+ if (IPCB(skb)->opt.router_alert) {
+ if (ip_call_ra_chain(skb))
+ return 0;
+ } else if (skb->nh.iph->protocol == IPPROTO_IGMP && mroute_socket) {
+ /* IGMPv1 (and broken IGMPv2 implementations sort of
+ Cisco IOS <= 11.2(8)) do not put router alert
+ option to IGMP packets destined to routable
+ groups. It is very bad, because it means
+ that we can forward NO IGMP messages.
+ */
+ raw_rcv(mroute_socket, skb);
+ return 0;
+ }
+ }
+
+ cache = ipmr_cache_find(skb->nh.iph->saddr, skb->nh.iph->daddr);
+
+ /*
+ * No usable cache entry
+ */
+
+ if (cache==NULL || (cache->mfc_flags&MFC_QUEUED)) {
+ int vif;
+
+ if (local) {
+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+ ip_local_deliver(skb);
+ if (skb2 == NULL)
+ return -ENOBUFS;
+ skb = skb2;
+ }
+
+ vif = ipmr_find_vif(skb->dev);
+ if (vif != ALL_VIFS) {
+ ipmr_cache_unresolved(cache, vif, skb);
+ return -EAGAIN;
+ }
+ kfree_skb(skb);
+ return 0;
+ }
+
+ ip_mr_forward(skb, cache, local);
+
+ if (local)
+ return ip_local_deliver(skb);
+ return 0;
+
+dont_forward:
+ if (local)
+ return ip_local_deliver(skb);
+ kfree_skb(skb);
+ return 0;
+}
+
+#ifdef CONFIG_IP_PIMSM_V1
+/*
+ * Handle IGMP messages of PIMv1
+ */
+
+int pim_rcv_v1(struct sk_buff * skb, unsigned short len)
+{
+ struct igmphdr *pim = (struct igmphdr*)skb->h.raw;
+ struct iphdr *encap;
+
+ if (!mroute_do_pim ||
+ len < sizeof(*pim) + sizeof(*encap) ||
+ pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER ||
+ reg_dev == NULL) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ encap = (struct iphdr*)(skb->h.raw + sizeof(struct igmphdr));
+ /*
+ Check that:
+ a. packet is really destinted to a multicast group
+ b. packet is not a NULL-REGISTER
+ c. packet is not truncated
+ */
+ if (!MULTICAST(encap->daddr) ||
+ ntohs(encap->tot_len) == 0 ||
+ ntohs(encap->tot_len) + sizeof(*pim) > len) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ skb->mac.raw = skb->nh.raw;
+ skb_pull(skb, (u8*)encap - skb->data);
+ skb->nh.iph = (struct iphdr *)skb->data;
+ skb->dev = reg_dev;
+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+ skb->protocol = __constant_htons(ETH_P_IP);
+ skb->ip_summed = 0;
+ skb->pkt_type = PACKET_HOST;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
+ ((struct net_device_stats*)reg_dev->priv)->rx_packets++;
+ netif_rx(skb);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_IP_PIMSM_V2
+int pim_rcv(struct sk_buff * skb, unsigned short len)
+{
+ struct pimreghdr *pim = (struct pimreghdr*)skb->h.raw;
+ struct iphdr *encap;
+
+ if (len < sizeof(*pim) + sizeof(*encap) ||
+ pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) ||
+ (pim->flags&PIM_NULL_REGISTER) ||
+ reg_dev == NULL ||
+ (ip_compute_csum((void *)pim, sizeof(*pim)) &&
+ ip_compute_csum((void *)pim, len))) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ /* check if the inner packet is destined to mcast group */
+ encap = (struct iphdr*)(skb->h.raw + sizeof(struct pimreghdr));
+ if (!MULTICAST(encap->daddr) ||
+ ntohs(encap->tot_len) == 0 ||
+ ntohs(encap->tot_len) + sizeof(*pim) > len) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ skb->mac.raw = skb->nh.raw;
+ skb_pull(skb, (u8*)encap - skb->data);
+ skb->nh.iph = (struct iphdr *)skb->data;
+ skb->dev = reg_dev;
+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+ skb->protocol = __constant_htons(ETH_P_IP);
+ skb->ip_summed = 0;
+ skb->pkt_type = PACKET_HOST;
+ dst_release(skb->dst);
+ ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
+ ((struct net_device_stats*)reg_dev->priv)->rx_packets++;
+ skb->dst = NULL;
+ netif_rx(skb);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_RTNETLINK
+
+static int
+ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)
+{
+ int ct;
+ struct rtnexthop *nhp;
+ struct device *dev = vif_table[c->mfc_parent].dev;
+ u8 *b = skb->tail;
+ struct rtattr *mp_head;
+
+ if (dev)
+ RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex);
+
+ mp_head = (struct rtattr*)skb_put(skb, RTA_LENGTH(0));
+
+ for (ct = c->mfc_minvif; ct < c->mfc_maxvif; ct++) {
+ if (c->mfc_ttls[ct] < 255) {
+ if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
+ goto rtattr_failure;
+ nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
+ nhp->rtnh_flags = 0;
+ nhp->rtnh_hops = c->mfc_ttls[ct];
+ nhp->rtnh_ifindex = vif_table[ct].dev->ifindex;
+ nhp->rtnh_len = sizeof(*nhp);
+ }
+ }
+ mp_head->rta_type = RTA_MULTIPATH;
+ mp_head->rta_len = skb->tail - (u8*)mp_head;
+ rtm->rtm_type = RTN_MULTICAST;
+ return 1;
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -EMSGSIZE;
+}
+
+int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
+{
+ struct mfc_cache *cache;
+ struct rtable *rt = (struct rtable*)skb->dst;
+
+ start_bh_atomic();
+ cache = ipmr_cache_find(rt->rt_src, rt->rt_dst);
+ if (cache==NULL || (cache->mfc_flags&MFC_QUEUED)) {
+ struct device *dev;
+ int vif;
+ int err;
+
+ if (nowait) {
+ end_bh_atomic();
+ return -EAGAIN;
+ }
+
+ dev = skb->dev;
+ if (dev == NULL || (vif = ipmr_find_vif(dev)) == ALL_VIFS) {
+ end_bh_atomic();
+ return -ENODEV;
+ }
+ skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
+ skb->nh.iph->ihl = sizeof(struct iphdr)>>2;
+ skb->nh.iph->saddr = rt->rt_src;
+ skb->nh.iph->daddr = rt->rt_dst;
+ skb->nh.iph->version = 0;
+ err = ipmr_cache_unresolved(cache, vif, skb);
+ end_bh_atomic();
+ return err;
+ }
+ /* Resolved cache entry is not changed by net bh,
+ so that we are allowed to enable it.
+ */
+ end_bh_atomic();
+
+ if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY))
+ cache->mfc_flags |= MFC_NOTIFY;
+ return ipmr_fill_mroute(skb, cache, rtm);
+}
+#endif
+
+/*
+ * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
+ */
+
+int ipmr_vif_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ struct vif_device *vif;
+ int len=0;
+ off_t pos=0;
+ off_t begin=0;
+ int size;
+ int ct;
+
+ len += sprintf(buffer,
+ "Interface BytesIn PktsIn BytesOut PktsOut Flags Local Remote\n");
+ pos=len;
+
+ for (ct=0;ct<maxvif;ct++)
+ {
+ char *name = "none";
+ vif=&vif_table[ct];
+ if(!(vifc_map&(1<<ct)))
+ continue;
+ if (vif->dev)
+ name = vif->dev->name;
+ size = sprintf(buffer+len, "%2d %-10s %8ld %7ld %8ld %7ld %05X %08X %08X\n",
+ ct, name, vif->bytes_in, vif->pkt_in, vif->bytes_out, vif->pkt_out,
+ vif->flags, vif->local, vif->remote);
+ len+=size;
+ pos+=size;
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ break;
+ }
+
+ *start=buffer+(offset-begin);
+ len-=(offset-begin);
+ if(len>length)
+ len=length;
+ return len;
+}
+
+int ipmr_mfc_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ struct mfc_cache *mfc;
+ int len=0;
+ off_t pos=0;
+ off_t begin=0;
+ int size;
+ int ct;
+
+ len += sprintf(buffer,
+ "Group Origin Iif Pkts Bytes Wrong Oifs\n");
+ pos=len;
+
+ for (ct=0;ct<MFC_LINES;ct++)
+ {
+ start_bh_atomic();
+ mfc=mfc_cache_array[ct];
+ while(mfc!=NULL)
+ {
+ int n;
+
+ /*
+ * Interface forwarding map
+ */
+ size = sprintf(buffer+len, "%08lX %08lX %-3d %8ld %8ld %8ld",
+ (unsigned long)mfc->mfc_mcastgrp,
+ (unsigned long)mfc->mfc_origin,
+ mfc->mfc_parent == ALL_VIFS ? -1 : mfc->mfc_parent,
+ (mfc->mfc_flags & MFC_QUEUED) ? mfc->mfc_unresolved.qlen : mfc->mfc_pkt,
+ mfc->mfc_bytes,
+ mfc->mfc_wrong_if);
+ for(n=mfc->mfc_minvif;n<mfc->mfc_maxvif;n++)
+ {
+ if(vifc_map&(1<<n) && mfc->mfc_ttls[n] < 255)
+ size += sprintf(buffer+len+size, " %2d:%-3d", n, mfc->mfc_ttls[n]);
+ }
+ size += sprintf(buffer+len+size, "\n");
+ len+=size;
+ pos+=size;
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ {
+ end_bh_atomic();
+ goto done;
+ }
+ mfc=mfc->next;
+ }
+ end_bh_atomic();
+ }
+done:
+ *start=buffer+(offset-begin);
+ len-=(offset-begin);
+ if(len>length)
+ len=length;
+ if (len < 0) {
+ len = 0;
+ }
+ return len;
+}
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_ipmr_vif = {
+ PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ipmr_vif_info
+};
+static struct proc_dir_entry proc_net_ipmr_mfc = {
+ PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ipmr_mfc_info
+};
+#endif
+
+#ifdef CONFIG_IP_PIMSM_V2
+struct inet_protocol pim_protocol =
+{
+ pim_rcv, /* PIM handler */
+ NULL, /* PIM error control */
+ NULL, /* next */
+ IPPROTO_PIM, /* protocol ID */
+ 0, /* copy */
+ NULL, /* data */
+ "PIM" /* name */
+};
+#endif
+
+
+/*
+ * Setup for IP multicast routing
+ */
+
+__initfunc(void ip_mr_init(void))
+{
+ printk(KERN_INFO "Linux IP multicast router 0.06 plus PIM-SM\n");
+ register_netdevice_notifier(&ip_mr_notifier);
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&proc_net_ipmr_vif);
+ proc_net_register(&proc_net_ipmr_mfc);
+#endif
+}
diff --git a/pfinet/linux-src/net/ipv4/proc.c b/pfinet/linux-src/net/ipv4/proc.c
new file mode 100644
index 00000000..1640a056
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/proc.c
@@ -0,0 +1,387 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * This file implements the various access functions for the
+ * PROC file system. It is mainly used for debugging and
+ * statistics.
+ *
+ * Version: $Id: proc.c,v 1.34 1999/02/08 11:20:34 davem Exp $
+ *
+ * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
+ * Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
+ * Erik Schoenfelder, <schoenfr@ibr.cs.tu-bs.de>
+ *
+ * Fixes:
+ * Alan Cox : UDP sockets show the rxqueue/txqueue
+ * using hint flag for the netinfo.
+ * Pauline Middelink : identd support
+ * Alan Cox : Make /proc safer.
+ * Erik Schoenfelder : /proc/net/snmp
+ * Alan Cox : Handle dead sockets properly.
+ * Gerhard Koerting : Show both timers
+ * Alan Cox : Allow inode to be NULL (kernel socket)
+ * Andi Kleen : Add support for open_requests and
+ * split functions for more readibility.
+ * Andi Kleen : Add support for /proc/net/netstat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/system.h>
+#include <linux/sched.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <linux/un.h>
+#include <linux/in.h>
+#include <linux/param.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/raw.h>
+
+/* Format a single open_request into tmpbuf. */
+static inline void get__openreq(struct sock *sk, struct open_request *req,
+ char *tmpbuf,
+ int i)
+{
+ sprintf(tmpbuf, "%4d: %08lX:%04X %08lX:%04X"
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u",
+ i,
+ (long unsigned int)req->af.v4_req.loc_addr,
+ ntohs(sk->sport),
+ (long unsigned int)req->af.v4_req.rmt_addr,
+ ntohs(req->rmt_port),
+ TCP_SYN_RECV,
+ 0,0, /* could print option size, but that is af dependent. */
+ 1, /* timers active (only the expire timer) */
+ (unsigned long)(req->expires - jiffies),
+ req->retrans,
+ sk->socket ? sk->socket->inode->i_uid : 0,
+ 0, /* non standard timer */
+ 0 /* open_requests have no inode */
+ );
+}
+
+/* Format a single socket into tmpbuf. */
+static inline void get__sock(struct sock *sp, char *tmpbuf, int i, int format)
+{
+ unsigned long dest, src;
+ unsigned short destp, srcp;
+ int timer_active, timer_active1, timer_active2;
+ int tw_bucket = 0;
+ unsigned long timer_expires;
+ struct tcp_opt *tp = &sp->tp_pinfo.af_tcp;
+
+ dest = sp->daddr;
+ src = sp->rcv_saddr;
+ destp = sp->dport;
+ srcp = sp->sport;
+
+ /* FIXME: The fact that retransmit_timer occurs as a field
+ * in two different parts of the socket structure is,
+ * to say the least, confusing. This code now uses the
+ * right retransmit_timer variable, but I'm not sure
+ * the rest of the timer stuff is still correct.
+ * In particular I'm not sure what the timeout value
+ * is suppose to reflect (as opposed to tm->when). -- erics
+ */
+
+ destp = ntohs(destp);
+ srcp = ntohs(srcp);
+ if((format == 0) && (sp->state == TCP_TIME_WAIT)) {
+ extern int tcp_tw_death_row_slot;
+ struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sp;
+ int slot_dist;
+
+ tw_bucket = 1;
+ timer_active1 = timer_active2 = 0;
+ timer_active = 3;
+ slot_dist = tw->death_slot;
+ if(slot_dist > tcp_tw_death_row_slot)
+ slot_dist = (TCP_TWKILL_SLOTS - slot_dist) + tcp_tw_death_row_slot;
+ else
+ slot_dist = tcp_tw_death_row_slot - slot_dist;
+ timer_expires = jiffies + (slot_dist * TCP_TWKILL_PERIOD);
+ } else {
+ timer_active1 = del_timer(&tp->retransmit_timer);
+ timer_active2 = del_timer(&sp->timer);
+ if (!timer_active1) tp->retransmit_timer.expires=0;
+ if (!timer_active2) sp->timer.expires=0;
+ timer_active = 0;
+ timer_expires = (unsigned) -1;
+ }
+ if (timer_active1 && tp->retransmit_timer.expires < timer_expires) {
+ timer_active = 1;
+ timer_expires = tp->retransmit_timer.expires;
+ }
+ if (timer_active2 && sp->timer.expires < timer_expires) {
+ timer_active = 2;
+ timer_expires = sp->timer.expires;
+ }
+ if(timer_active == 0)
+ timer_expires = jiffies;
+ sprintf(tmpbuf, "%4d: %08lX:%04X %08lX:%04X"
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
+ i, src, srcp, dest, destp, sp->state,
+ (tw_bucket ?
+ 0 :
+ (format == 0) ?
+ tp->write_seq-tp->snd_una : atomic_read(&sp->wmem_alloc)),
+ (tw_bucket ?
+ 0 :
+ (format == 0) ?
+ tp->rcv_nxt-tp->copied_seq: atomic_read(&sp->rmem_alloc)),
+ timer_active, timer_expires-jiffies,
+ (tw_bucket ? 0 : tp->retransmits),
+ (!tw_bucket && sp->socket) ? sp->socket->inode->i_uid : 0,
+ (!tw_bucket && timer_active) ? sp->timeout : 0,
+ (!tw_bucket && sp->socket) ? sp->socket->inode->i_ino : 0);
+
+ if (timer_active1) add_timer(&tp->retransmit_timer);
+ if (timer_active2) add_timer(&sp->timer);
+}
+
+/*
+ * Get__netinfo returns the length of that string.
+ *
+ * KNOWN BUGS
+ * As in get_unix_netinfo, the buffer might be too small. If this
+ * happens, get__netinfo returns only part of the available infos.
+ *
+ * Assumes that buffer length is a multiply of 128 - if not it will
+ * write past the end.
+ */
+static int
+get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t offset, int length)
+{
+ struct sock *sp, *next;
+ int len=0, i = 0;
+ off_t pos=0;
+ off_t begin;
+ char tmpbuf[129];
+
+ if (offset < 128)
+ len += sprintf(buffer, "%-127s\n",
+ " sl local_address rem_address st tx_queue "
+ "rx_queue tr tm->when retrnsmt uid timeout inode");
+ pos = 128;
+ SOCKHASH_LOCK();
+ sp = pro->sklist_next;
+ while(sp != (struct sock *)pro) {
+ if (format == 0 && sp->state == TCP_LISTEN) {
+ struct open_request *req;
+
+ for (req = sp->tp_pinfo.af_tcp.syn_wait_queue; req;
+ i++, req = req->dl_next) {
+ if (req->sk)
+ continue;
+ pos += 128;
+ if (pos < offset)
+ continue;
+ get__openreq(sp, req, tmpbuf, i);
+ len += sprintf(buffer+len, "%-127s\n", tmpbuf);
+ if(len >= length)
+ goto out;
+ }
+ }
+
+ pos += 128;
+ if (pos < offset)
+ goto next;
+
+ get__sock(sp, tmpbuf, i, format);
+
+ len += sprintf(buffer+len, "%-127s\n", tmpbuf);
+ if(len >= length)
+ break;
+ next:
+ next = sp->sklist_next;
+ sp = next;
+ i++;
+ }
+out:
+ SOCKHASH_UNLOCK();
+
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len>length)
+ len = length;
+ if (len<0)
+ len = 0;
+ return len;
+}
+
+int tcp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ return get__netinfo(&tcp_prot, buffer,0, start, offset, length);
+}
+
+int udp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ return get__netinfo(&udp_prot, buffer,1, start, offset, length);
+}
+
+int raw_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ return get__netinfo(&raw_prot, buffer,1, start, offset, length);
+}
+
+/*
+ * Report socket allocation statistics [mea@utu.fi]
+ */
+int afinet_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ /* From net/socket.c */
+ extern int socket_get_info(char *, char **, off_t, int);
+
+ int len = socket_get_info(buffer,start,offset,length);
+
+ len += sprintf(buffer+len,"TCP: inuse %d highest %d\n",
+ tcp_prot.inuse, tcp_prot.highestinuse);
+ len += sprintf(buffer+len,"UDP: inuse %d highest %d\n",
+ udp_prot.inuse, udp_prot.highestinuse);
+ len += sprintf(buffer+len,"RAW: inuse %d highest %d\n",
+ raw_prot.inuse, raw_prot.highestinuse);
+ if (offset >= len)
+ {
+ *start = buffer;
+ return 0;
+ }
+ *start = buffer + offset;
+ len -= offset;
+ if (len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
+
+/*
+ * Called from the PROCfs module. This outputs /proc/net/snmp.
+ */
+
+int snmp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ extern struct tcp_mib tcp_statistics;
+ extern struct udp_mib udp_statistics;
+ int len;
+/*
+ extern unsigned long tcp_rx_miss, tcp_rx_hit1,tcp_rx_hit2;
+*/
+
+ len = sprintf (buffer,
+ "Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates\n"
+ "Ip: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+ ip_statistics.IpForwarding, ip_statistics.IpDefaultTTL,
+ ip_statistics.IpInReceives, ip_statistics.IpInHdrErrors,
+ ip_statistics.IpInAddrErrors, ip_statistics.IpForwDatagrams,
+ ip_statistics.IpInUnknownProtos, ip_statistics.IpInDiscards,
+ ip_statistics.IpInDelivers, ip_statistics.IpOutRequests,
+ ip_statistics.IpOutDiscards, ip_statistics.IpOutNoRoutes,
+ ip_statistics.IpReasmTimeout, ip_statistics.IpReasmReqds,
+ ip_statistics.IpReasmOKs, ip_statistics.IpReasmFails,
+ ip_statistics.IpFragOKs, ip_statistics.IpFragFails,
+ ip_statistics.IpFragCreates);
+
+ len += sprintf (buffer + len,
+ "Icmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps\n"
+ "Icmp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+ icmp_statistics.IcmpInMsgs, icmp_statistics.IcmpInErrors,
+ icmp_statistics.IcmpInDestUnreachs, icmp_statistics.IcmpInTimeExcds,
+ icmp_statistics.IcmpInParmProbs, icmp_statistics.IcmpInSrcQuenchs,
+ icmp_statistics.IcmpInRedirects, icmp_statistics.IcmpInEchos,
+ icmp_statistics.IcmpInEchoReps, icmp_statistics.IcmpInTimestamps,
+ icmp_statistics.IcmpInTimestampReps, icmp_statistics.IcmpInAddrMasks,
+ icmp_statistics.IcmpInAddrMaskReps, icmp_statistics.IcmpOutMsgs,
+ icmp_statistics.IcmpOutErrors, icmp_statistics.IcmpOutDestUnreachs,
+ icmp_statistics.IcmpOutTimeExcds, icmp_statistics.IcmpOutParmProbs,
+ icmp_statistics.IcmpOutSrcQuenchs, icmp_statistics.IcmpOutRedirects,
+ icmp_statistics.IcmpOutEchos, icmp_statistics.IcmpOutEchoReps,
+ icmp_statistics.IcmpOutTimestamps, icmp_statistics.IcmpOutTimestampReps,
+ icmp_statistics.IcmpOutAddrMasks, icmp_statistics.IcmpOutAddrMaskReps);
+
+ len += sprintf (buffer + len,
+ "Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts\n"
+ "Tcp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+ tcp_statistics.TcpRtoAlgorithm, tcp_statistics.TcpRtoMin,
+ tcp_statistics.TcpRtoMax, tcp_statistics.TcpMaxConn,
+ tcp_statistics.TcpActiveOpens, tcp_statistics.TcpPassiveOpens,
+ tcp_statistics.TcpAttemptFails, tcp_statistics.TcpEstabResets,
+ tcp_statistics.TcpCurrEstab, tcp_statistics.TcpInSegs,
+ tcp_statistics.TcpOutSegs, tcp_statistics.TcpRetransSegs,
+ tcp_statistics.TcpInErrs, tcp_statistics.TcpOutRsts);
+
+ len += sprintf (buffer + len,
+ "Udp: InDatagrams NoPorts InErrors OutDatagrams\nUdp: %lu %lu %lu %lu\n",
+ udp_statistics.UdpInDatagrams, udp_statistics.UdpNoPorts,
+ udp_statistics.UdpInErrors, udp_statistics.UdpOutDatagrams);
+/*
+ len += sprintf( buffer + len,
+ "TCP fast path RX: H2: %ul H1: %ul L: %ul\n",
+ tcp_rx_hit2,tcp_rx_hit1,tcp_rx_miss);
+*/
+
+ if (offset >= len)
+ {
+ *start = buffer;
+ return 0;
+ }
+ *start = buffer + offset;
+ len -= offset;
+ if (len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
+/*
+ * Output /proc/net/netstat
+ */
+
+int netstat_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ extern struct linux_mib net_statistics;
+ int len;
+
+ len = sprintf(buffer,
+ "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
+ " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
+ " OutOfWindowIcmps LockDroppedIcmps\n"
+ "TcpExt: %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+ net_statistics.SyncookiesSent,
+ net_statistics.SyncookiesRecv,
+ net_statistics.SyncookiesFailed,
+ net_statistics.EmbryonicRsts,
+ net_statistics.PruneCalled,
+ net_statistics.RcvPruned,
+ net_statistics.OfoPruned,
+ net_statistics.OutOfWindowIcmps,
+ net_statistics.LockDroppedIcmps);
+
+ if (offset >= len)
+ {
+ *start = buffer;
+ return 0;
+ }
+ *start = buffer + offset;
+ len -= offset;
+ if (len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
diff --git a/pfinet/linux-src/net/ipv4/protocol.c b/pfinet/linux-src/net/ipv4/protocol.c
new file mode 100644
index 00000000..b47480be
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/protocol.c
@@ -0,0 +1,211 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * INET protocol dispatch tables.
+ *
+ * Version: $Id: protocol.c,v 1.9 1997/10/29 20:27:34 kuznet Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * Fixes:
+ * Alan Cox : Ahah! udp icmp errors don't work because
+ * udp_err is never called!
+ * Alan Cox : Added new fields for init and ready for
+ * proper fragmentation (_NO_ 4K limits!)
+ * Richard Colella : Hang on hash collision
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/config.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/timer.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/ipip.h>
+#include <linux/igmp.h>
+
+#define IPPROTO_PREVIOUS NULL
+
+#ifdef CONFIG_IP_MULTICAST
+
+static struct inet_protocol igmp_protocol =
+{
+ igmp_rcv, /* IGMP handler */
+ NULL, /* IGMP error control */
+ IPPROTO_PREVIOUS, /* next */
+ IPPROTO_IGMP, /* protocol ID */
+ 0, /* copy */
+ NULL, /* data */
+ "IGMP" /* name */
+};
+
+#undef IPPROTO_PREVIOUS
+#define IPPROTO_PREVIOUS &igmp_protocol
+
+#endif
+
+static struct inet_protocol tcp_protocol =
+{
+ tcp_v4_rcv, /* TCP handler */
+ tcp_v4_err, /* TCP error control */
+ IPPROTO_PREVIOUS,
+ IPPROTO_TCP, /* protocol ID */
+ 0, /* copy */
+ NULL, /* data */
+ "TCP" /* name */
+};
+
+#undef IPPROTO_PREVIOUS
+#define IPPROTO_PREVIOUS &tcp_protocol
+
+static struct inet_protocol udp_protocol =
+{
+ udp_rcv, /* UDP handler */
+ udp_err, /* UDP error control */
+ IPPROTO_PREVIOUS, /* next */
+ IPPROTO_UDP, /* protocol ID */
+ 0, /* copy */
+ NULL, /* data */
+ "UDP" /* name */
+};
+
+#undef IPPROTO_PREVIOUS
+#define IPPROTO_PREVIOUS &udp_protocol
+
+
+static struct inet_protocol icmp_protocol =
+{
+ icmp_rcv, /* ICMP handler */
+ NULL, /* ICMP error control */
+ IPPROTO_PREVIOUS, /* next */
+ IPPROTO_ICMP, /* protocol ID */
+ 0, /* copy */
+ NULL, /* data */
+ "ICMP" /* name */
+};
+
+#undef IPPROTO_PREVIOUS
+#define IPPROTO_PREVIOUS &icmp_protocol
+
+
+struct inet_protocol *inet_protocol_base = IPPROTO_PREVIOUS;
+
+struct inet_protocol *inet_protos[MAX_INET_PROTOS] =
+{
+ NULL
+};
+
+
+/*
+ * Find a protocol in the protocol tables given its
+ * IP type.
+ */
+
+struct inet_protocol *inet_get_protocol(unsigned char prot)
+{
+ unsigned char hash;
+ struct inet_protocol *p;
+
+ hash = prot & (MAX_INET_PROTOS - 1);
+ for (p = inet_protos[hash] ; p != NULL; p=p->next)
+ {
+ if (p->protocol == prot)
+ return((struct inet_protocol *) p);
+ }
+ return(NULL);
+}
+
+/*
+ * Add a protocol handler to the hash tables
+ */
+
+void inet_add_protocol(struct inet_protocol *prot)
+{
+ unsigned char hash;
+ struct inet_protocol *p2;
+
+ hash = prot->protocol & (MAX_INET_PROTOS - 1);
+ prot ->next = inet_protos[hash];
+ inet_protos[hash] = prot;
+ prot->copy = 0;
+
+ /*
+ * Set the copy bit if we need to.
+ */
+
+ p2 = (struct inet_protocol *) prot->next;
+ while(p2 != NULL)
+ {
+ if (p2->protocol == prot->protocol)
+ {
+ prot->copy = 1;
+ break;
+ }
+ p2 = (struct inet_protocol *) p2->next;
+ }
+}
+
+/*
+ * Remove a protocol from the hash tables.
+ */
+
+int inet_del_protocol(struct inet_protocol *prot)
+{
+ struct inet_protocol *p;
+ struct inet_protocol *lp = NULL;
+ unsigned char hash;
+
+ hash = prot->protocol & (MAX_INET_PROTOS - 1);
+ if (prot == inet_protos[hash])
+ {
+ inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
+ return(0);
+ }
+
+ p = (struct inet_protocol *) inet_protos[hash];
+ while(p != NULL)
+ {
+ /*
+ * We have to worry if the protocol being deleted is
+ * the last one on the list, then we may need to reset
+ * someone's copied bit.
+ */
+ if (p->next != NULL && p->next == prot)
+ {
+ /*
+ * if we are the last one with this protocol and
+ * there is a previous one, reset its copy bit.
+ */
+ if (p->copy == 0 && lp != NULL)
+ lp->copy = 0;
+ p->next = prot->next;
+ return(0);
+ }
+ if (p->next != NULL && p->next->protocol == prot->protocol)
+ lp = p;
+
+ p = (struct inet_protocol *) p->next;
+ }
+ return(-1);
+}
diff --git a/pfinet/linux-src/net/ipv4/rarp.c b/pfinet/linux-src/net/ipv4/rarp.c
new file mode 100644
index 00000000..7f7c7e3f
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/rarp.c
@@ -0,0 +1,606 @@
+/* linux/net/inet/rarp.c
+ *
+ * Copyright (C) 1994 by Ross Martin
+ * Based on linux/net/inet/arp.c, Copyright (C) 1994 by Florian La Roche
+ *
+ * $Id: rarp.c,v 1.25 1998/06/19 13:22:34 davem Exp $
+ *
+ * This module implements the Reverse Address Resolution Protocol
+ * (RARP, RFC 903), which is used to convert low level addresses such
+ * as Ethernet addresses into high level addresses such as IP addresses.
+ * The most common use of RARP is as a means for a diskless workstation
+ * to discover its IP address during a network boot.
+ *
+ **
+ *** WARNING:::::::::::::::::::::::::::::::::WARNING
+ ****
+ ***** SUN machines seem determined to boot solely from the person who
+ **** answered their RARP query. NEVER add a SUN to your RARP table
+ *** unless you have all the rest to boot the box from it.
+ **
+ *
+ * Currently, only Ethernet address -> IP address is likely to work.
+ * (Is RARP ever used for anything else?)
+ *
+ * This code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes
+ * Alan Cox : Rarp delete on device down needed as
+ * reported by Walter Wolfgang.
+ * Mike McLagan : Routing by source
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/in.h>
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <stdarg.h>
+#include <linux/inet.h>
+#include <linux/etherdevice.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/arp.h>
+#include <net/rarp.h>
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+#include <net/ax25.h>
+#endif
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+
+extern int (*rarp_ioctl_hook)(unsigned int,void*);
+
+/*
+ * This structure defines the RARP mapping cache. As long as we make
+ * changes in this structure, we keep interrupts off.
+ */
+
+struct rarp_table
+{
+ struct rarp_table *next; /* Linked entry list */
+ unsigned long ip; /* ip address of entry */
+ unsigned char ha[MAX_ADDR_LEN]; /* Hardware address */
+ unsigned char hlen; /* Length of hardware address */
+ unsigned char htype; /* Type of hardware in use */
+ struct device *dev; /* Device the entry is tied to */
+};
+
+struct rarp_table *rarp_tables = NULL;
+
+static int rarp_rcv(struct sk_buff *, struct device *, struct packet_type *);
+
+static struct packet_type rarp_packet_type =
+{
+ 0, /* Should be: __constant_htons(ETH_P_RARP) - but this _doesn't_ come out constant! */
+ 0, /* copy */
+ rarp_rcv,
+ NULL,
+ NULL
+};
+
+static int initflag = 1;
+
+
+/*
+ * Release the memory for this entry.
+ */
+
+static inline void rarp_release_entry(struct rarp_table *entry)
+{
+ kfree_s(entry, sizeof(struct rarp_table));
+ MOD_DEC_USE_COUNT;
+ return;
+}
+
+/*
+ * Delete a RARP mapping entry in the cache.
+ */
+
+static void rarp_destroy(unsigned long ip_addr)
+{
+ struct rarp_table *entry;
+ struct rarp_table **pentry;
+
+ start_bh_atomic();
+ pentry = &rarp_tables;
+ while ((entry = *pentry) != NULL)
+ {
+ if (entry->ip == ip_addr)
+ {
+ *pentry = entry->next;
+ end_bh_atomic();
+ rarp_release_entry(entry);
+ return;
+ }
+ pentry = &entry->next;
+ }
+ end_bh_atomic();
+}
+
+/*
+ * Flush a device.
+ */
+
+static void rarp_destroy_dev(struct device *dev)
+{
+ struct rarp_table *entry;
+ struct rarp_table **pentry;
+
+ start_bh_atomic();
+ pentry = &rarp_tables;
+ while ((entry = *pentry) != NULL)
+ {
+ if (entry->dev == dev)
+ {
+ *pentry = entry->next;
+ rarp_release_entry(entry);
+ }
+ else
+ pentry = &entry->next;
+ }
+ end_bh_atomic();
+}
+
+static int rarp_device_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ if(event!=NETDEV_DOWN)
+ return NOTIFY_DONE;
+ rarp_destroy_dev((struct device *)ptr);
+ return NOTIFY_DONE;
+}
+
+/*
+ * Called once when data first added to rarp cache with ioctl.
+ */
+
+static struct notifier_block rarp_dev_notifier={
+ rarp_device_event,
+ NULL,
+ 0
+};
+
+static int rarp_pkt_inited=0;
+
+static void rarp_init_pkt (void)
+{
+ /* Register the packet type */
+ rarp_packet_type.type=htons(ETH_P_RARP);
+ dev_add_pack(&rarp_packet_type);
+ register_netdevice_notifier(&rarp_dev_notifier);
+ rarp_pkt_inited=1;
+}
+
+#ifdef MODULE
+
+static void rarp_end_pkt(void)
+{
+ if(!rarp_pkt_inited)
+ return;
+ dev_remove_pack(&rarp_packet_type);
+ unregister_netdevice_notifier(&rarp_dev_notifier);
+ rarp_pkt_inited=0;
+}
+
+#endif
+
+/*
+ * Receive an arp request by the device layer. Maybe it should be
+ * rewritten to use the incoming packet for the reply. The current
+ * "overhead" time isn't that high...
+ */
+
+static int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+{
+/*
+ * We shouldn't use this type conversion. Check later.
+ */
+ struct arphdr *rarp = (struct arphdr *) skb->data;
+ unsigned char *rarp_ptr = skb_pull(skb,sizeof(struct arphdr));
+ struct rarp_table *entry;
+ struct in_device *in_dev = dev->ip_ptr;
+ long sip,tip;
+ unsigned char *sha,*tha; /* s for "source", t for "target" */
+
+/*
+ * If this test doesn't pass, it's not IP, or we should ignore it anyway
+ */
+
+ if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)
+ || dev->flags&IFF_NOARP || !in_dev || !in_dev->ifa_list)
+ {
+ kfree_skb(skb);
+ return 0;
+ }
+
+/*
+ * If it's not a RARP request, delete it.
+ */
+ if (rarp->ar_op != htons(ARPOP_RREQUEST))
+ {
+ kfree_skb(skb);
+ return 0;
+ }
+
+/*
+ * For now we will only deal with IP addresses.
+ */
+
+ if (
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ (rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
+#endif
+ (rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25)
+ || rarp->ar_pln != 4)
+ {
+ /*
+ * This packet is not for us. Remove it.
+ */
+ kfree_skb(skb);
+ return 0;
+ }
+
+/*
+ * Extract variable width fields
+ */
+
+ sha=rarp_ptr;
+ rarp_ptr+=dev->addr_len;
+ memcpy(&sip,rarp_ptr,4);
+ rarp_ptr+=4;
+ tha=rarp_ptr;
+ rarp_ptr+=dev->addr_len;
+ memcpy(&tip,rarp_ptr,4);
+
+/*
+ * Process entry. Use tha for table lookup according to RFC903.
+ */
+
+ for (entry = rarp_tables; entry != NULL; entry = entry->next)
+ if (!memcmp(entry->ha, tha, rarp->ar_hln))
+ break;
+
+ if (entry != NULL)
+ {
+ sip=entry->ip;
+
+ arp_send(ARPOP_RREPLY, ETH_P_RARP, sip, dev, in_dev->ifa_list->ifa_address, sha,
+ dev->dev_addr, sha);
+ }
+
+ kfree_skb(skb);
+ return 0;
+}
+
+
+/*
+ * Set (create) a RARP cache entry.
+ */
+
+static int rarp_req_set(struct arpreq *req)
+{
+ struct arpreq r;
+ struct rarp_table *entry;
+ struct sockaddr_in *si;
+ int htype, hlen;
+ unsigned long ip;
+ struct rtable *rt;
+ struct device * dev;
+ int err;
+
+ err = copy_from_user(&r, req, sizeof(r));
+ if (err)
+ return -EFAULT;
+
+ /*
+ * We only understand about IP addresses...
+ */
+
+ if (r.arp_pa.sa_family != AF_INET)
+ return -EPFNOSUPPORT;
+
+ switch (r.arp_ha.sa_family)
+ {
+ case ARPHRD_ETHER:
+ htype = ARPHRD_ETHER;
+ hlen = ETH_ALEN;
+ break;
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ case ARPHRD_AX25:
+ htype = ARPHRD_AX25;
+ hlen = 7;
+ break;
+#endif
+ default:
+ return -EPFNOSUPPORT;
+ }
+
+ si = (struct sockaddr_in *) &r.arp_pa;
+ ip = si->sin_addr.s_addr;
+ if (ip == 0)
+ {
+ printk(KERN_DEBUG "RARP: SETRARP: requested PA is 0.0.0.0 !\n");
+ return -EINVAL;
+ }
+
+/*
+ * Is it reachable directly ?
+ */
+
+ err = ip_route_output(&rt, ip, 0, 1, 0);
+ if (err)
+ return err;
+ if (rt->rt_flags&(RTCF_LOCAL|RTCF_BROADCAST|RTCF_MULTICAST|RTCF_DNAT)) {
+ ip_rt_put(rt);
+ return -EINVAL;
+ }
+ dev = rt->u.dst.dev;
+
+/*
+ * Is there an existing entry for this address? Find out...
+ */
+
+ for (entry = rarp_tables; entry != NULL; entry = entry->next)
+ if (entry->ip == ip)
+ break;
+
+/*
+ * If no entry was found, create a new one.
+ */
+
+ if (entry == NULL)
+ {
+ entry = (struct rarp_table *) kmalloc(sizeof(struct rarp_table),
+ GFP_ATOMIC);
+ if (entry == NULL)
+ {
+ return -ENOMEM;
+ }
+ if (initflag)
+ {
+ rarp_init_pkt();
+ initflag=0;
+ }
+
+ /* Block interrupts until table modification is finished */
+
+ cli();
+ entry->next = rarp_tables;
+ rarp_tables = entry;
+ }
+ cli();
+ entry->ip = ip;
+ entry->hlen = hlen;
+ entry->htype = htype;
+ memcpy(&entry->ha, &r.arp_ha.sa_data, hlen);
+ entry->dev = dev;
+ sti();
+
+ /* Don't unlink if we have entries to serve. */
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+
+/*
+ * Get a RARP cache entry.
+ */
+
+static int rarp_req_get(struct arpreq *req)
+{
+ struct arpreq r;
+ struct rarp_table *entry;
+ struct sockaddr_in *si;
+ unsigned long ip;
+ int err;
+
+/*
+ * We only understand about IP addresses...
+ */
+
+ err = copy_from_user(&r, req, sizeof(r));
+ if (err)
+ return -EFAULT;
+
+ if (r.arp_pa.sa_family != AF_INET)
+ return -EPFNOSUPPORT;
+
+/*
+ * Is there an existing entry for this address?
+ */
+
+ si = (struct sockaddr_in *) &r.arp_pa;
+ ip = si->sin_addr.s_addr;
+
+ for (entry = rarp_tables; entry != NULL; entry = entry->next)
+ if (entry->ip == ip)
+ break;
+
+ if (entry == NULL)
+ {
+ return -ENXIO;
+ }
+
+/*
+ * We found it; copy into structure.
+ */
+
+ memcpy(r.arp_ha.sa_data, &entry->ha, entry->hlen);
+ r.arp_ha.sa_family = entry->htype;
+
+/*
+ * Copy the information back
+ */
+
+ return copy_to_user(req, &r, sizeof(r)) ? -EFAULT : 0;
+}
+
+
+/*
+ * Handle a RARP layer I/O control request.
+ */
+
+int rarp_ioctl(unsigned int cmd, void *arg)
+{
+ struct arpreq r;
+ struct sockaddr_in *si;
+ int err;
+
+ switch(cmd)
+ {
+ case SIOCDRARP:
+ if (!suser())
+ return -EPERM;
+ err = copy_from_user(&r, arg, sizeof(r));
+ if (err)
+ return -EFAULT;
+ if (r.arp_pa.sa_family != AF_INET)
+ return -EPFNOSUPPORT;
+ si = (struct sockaddr_in *) &r.arp_pa;
+ rarp_destroy(si->sin_addr.s_addr);
+ return 0;
+
+ case SIOCGRARP:
+
+ return rarp_req_get((struct arpreq *)arg);
+ case SIOCSRARP:
+ if (!suser())
+ return -EPERM;
+ return rarp_req_set((struct arpreq *)arg);
+ default:
+ return -EINVAL;
+ }
+
+ /*NOTREACHED*/
+ return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+int rarp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len=0;
+ off_t begin=0;
+ off_t pos=0;
+ int size;
+ struct rarp_table *entry;
+ char ipbuffer[20];
+ unsigned long netip;
+ if (initflag)
+ {
+ size = sprintf(buffer,"RARP disabled until entries added to cache.\n");
+ pos+=size;
+ len+=size;
+ }
+ else
+ {
+ size = sprintf(buffer,
+ "IP address HW type HW address\n");
+ pos+=size;
+ len+=size;
+
+ for(entry=rarp_tables; entry!=NULL; entry=entry->next)
+ {
+ netip=htonl(entry->ip); /* switch to network order */
+ sprintf(ipbuffer,"%d.%d.%d.%d",
+ (unsigned int)(netip>>24)&255,
+ (unsigned int)(netip>>16)&255,
+ (unsigned int)(netip>>8)&255,
+ (unsigned int)(netip)&255);
+
+ size = sprintf(buffer+len,
+ "%-17s%-20s%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ipbuffer,
+ "10Mbps Ethernet",
+ (unsigned int)entry->ha[0],
+ (unsigned int)entry->ha[1],
+ (unsigned int)entry->ha[2],
+ (unsigned int)entry->ha[3],
+ (unsigned int)entry->ha[4],
+ (unsigned int)entry->ha[5]);
+
+ len+=size;
+ pos=begin+len;
+
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ break;
+ }
+ }
+
+ *start = buffer+(offset-begin); /* Start of wanted data */
+ len -= (offset-begin); /* Start slop */
+ if (len>length)
+ len = length; /* Ending slop */
+ return len;
+}
+
+struct proc_dir_entry proc_net_rarp = {
+ PROC_NET_RARP, 4, "rarp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ rarp_get_info
+};
+#endif
+
+__initfunc(void
+rarp_init(void))
+{
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&proc_net_rarp);
+#endif
+ rarp_ioctl_hook = rarp_ioctl;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+ rarp_init();
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ struct rarp_table *rt, *rt_next;
+#ifdef CONFIG_PROC_FS
+ proc_net_unregister(PROC_NET_RARP);
+#endif
+ rarp_ioctl_hook = NULL;
+ cli();
+ /* Destroy the RARP-table */
+ rt = rarp_tables;
+ rarp_tables = NULL;
+ sti();
+ /* ... and free it. */
+ for ( ; rt != NULL; rt = rt_next) {
+ rt_next = rt->next;
+ rarp_release_entry(rt);
+ }
+ rarp_end_pkt();
+}
+#endif
diff --git a/pfinet/linux-src/net/ipv4/raw.c b/pfinet/linux-src/net/ipv4/raw.c
new file mode 100644
index 00000000..5e7910dd
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/raw.c
@@ -0,0 +1,573 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * RAW - implementation of IP "raw" sockets.
+ *
+ * Version: $Id: raw.c,v 1.39.2.1 1999/06/20 20:14:50 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * Fixes:
+ * Alan Cox : verify_area() fixed up
+ * Alan Cox : ICMP error handling
+ * Alan Cox : EMSGSIZE if you send too big a packet
+ * Alan Cox : Now uses generic datagrams and shared skbuff
+ * library. No more peek crashes, no more backlogs
+ * Alan Cox : Checks sk->broadcast.
+ * Alan Cox : Uses skb_free_datagram/skb_copy_datagram
+ * Alan Cox : Raw passes ip options too
+ * Alan Cox : Setsocketopt added
+ * Alan Cox : Fixed error return for broadcasts
+ * Alan Cox : Removed wake_up calls
+ * Alan Cox : Use ttl/tos
+ * Alan Cox : Cleaned up old debugging
+ * Alan Cox : Use new kernel side addresses
+ * Arnt Gulbrandsen : Fixed MSG_DONTROUTE in raw sockets.
+ * Alan Cox : BSD style RAW socket demultiplexing.
+ * Alan Cox : Beginnings of mrouted support.
+ * Alan Cox : Added IP_HDRINCL option.
+ * Alan Cox : Skip broadcast check if BSDism set.
+ * David S. Miller : New socket lookup architecture.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/mroute.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/raw.h>
+#include <net/checksum.h>
+
+#ifdef CONFIG_IP_MROUTE
+struct sock *mroute_socket=NULL;
+#endif
+
+struct sock *raw_v4_htable[RAWV4_HTABLE_SIZE];
+
+static void raw_v4_hash(struct sock *sk)
+{
+ struct sock **skp = &raw_v4_htable[sk->num & (RAWV4_HTABLE_SIZE - 1)];
+
+ SOCKHASH_LOCK();
+ if ((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+ *skp = sk;
+ sk->pprev = skp;
+ SOCKHASH_UNLOCK();
+}
+
+static void raw_v4_unhash(struct sock *sk)
+{
+ SOCKHASH_LOCK();
+ if (sk->pprev) {
+ if (sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ }
+ SOCKHASH_UNLOCK();
+}
+
+/* Grumble... icmp and ip_input want to get at this... */
+struct sock *raw_v4_lookup(struct sock *sk, unsigned short num,
+ unsigned long raddr, unsigned long laddr, int dif)
+{
+ struct sock *s = sk;
+
+ SOCKHASH_LOCK();
+ for(s = sk; s; s = s->next) {
+ if((s->num == num) &&
+ !(s->dead && (s->state == TCP_CLOSE)) &&
+ !(s->daddr && s->daddr != raddr) &&
+ !(s->rcv_saddr && s->rcv_saddr != laddr) &&
+ !(s->bound_dev_if && s->bound_dev_if != dif))
+ break; /* gotcha */
+ }
+ SOCKHASH_UNLOCK();
+ return s;
+}
+
+void raw_err (struct sock *sk, struct sk_buff *skb)
+{
+ int type = skb->h.icmph->type;
+ int code = skb->h.icmph->code;
+ u32 info = 0;
+ int err = 0;
+ int harderr = 0;
+
+ /* Report error on raw socket, if:
+ 1. User requested ip_recverr.
+ 2. Socket is connected (otherwise the error indication
+ is useless without ip_recverr and error is hard.
+ */
+ if (!sk->ip_recverr && sk->state != TCP_ESTABLISHED)
+ return;
+
+ switch (type) {
+ default:
+ case ICMP_TIME_EXCEEDED:
+ err = EHOSTUNREACH;
+ break;
+ case ICMP_SOURCE_QUENCH:
+ return;
+ case ICMP_PARAMETERPROB:
+ err = EPROTO;
+ info = ntohl(skb->h.icmph->un.gateway)>>24;
+ harderr = 1;
+ break;
+ case ICMP_DEST_UNREACH:
+ err = EHOSTUNREACH;
+ if (code > NR_ICMP_UNREACH)
+ break;
+ err = icmp_err_convert[code].errno;
+ harderr = icmp_err_convert[code].fatal;
+ if (code == ICMP_FRAG_NEEDED) {
+ harderr = (sk->ip_pmtudisc != IP_PMTUDISC_DONT);
+ err = EMSGSIZE;
+ info = ntohs(skb->h.icmph->un.frag.mtu);
+ }
+ }
+
+ if (sk->ip_recverr)
+ ip_icmp_error(sk, skb, err, 0, info, (u8 *)(skb->h.icmph + 1));
+
+ if (sk->ip_recverr || harderr) {
+ sk->err = err;
+ sk->error_report(sk);
+ }
+}
+
+static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
+{
+ /* Charge it to the socket. */
+
+ if (sock_queue_rcv_skb(sk,skb)<0)
+ {
+ ip_statistics.IpInDiscards++;
+ kfree_skb(skb);
+ return -1;
+ }
+
+ ip_statistics.IpInDelivers++;
+ return 0;
+}
+
+/*
+ * This should be the easiest of all, all we do is
+ * copy it into a buffer. All demultiplexing is done
+ * in ip.c
+ */
+
+int raw_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ /* Now we need to copy this into memory. */
+ skb_trim(skb, ntohs(skb->nh.iph->tot_len));
+
+ skb->h.raw = skb->nh.raw;
+
+ raw_rcv_skb(sk, skb);
+ return 0;
+}
+
+struct rawfakehdr
+{
+ struct iovec *iov;
+ u32 saddr;
+};
+
+/*
+ * Send a RAW IP packet.
+ */
+
+/*
+ * Callback support is trivial for SOCK_RAW
+ */
+
+static int raw_getfrag(const void *p, char *to, unsigned int offset, unsigned int fraglen)
+{
+ struct rawfakehdr *rfh = (struct rawfakehdr *) p;
+ return memcpy_fromiovecend(to, rfh->iov, offset, fraglen);
+}
+
+/*
+ * IPPROTO_RAW needs extra work.
+ */
+
+static int raw_getrawfrag(const void *p, char *to, unsigned int offset, unsigned int fraglen)
+{
+ struct rawfakehdr *rfh = (struct rawfakehdr *) p;
+
+ if (memcpy_fromiovecend(to, rfh->iov, offset, fraglen))
+ return -EFAULT;
+
+ if (offset==0) {
+ struct iphdr *iph = (struct iphdr *)to;
+ if (!iph->saddr)
+ iph->saddr = rfh->saddr;
+ iph->check=0;
+ iph->tot_len=htons(fraglen); /* This is right as you can't frag
+ RAW packets */
+ /*
+ * Deliberate breach of modularity to keep
+ * ip_build_xmit clean (well less messy).
+ */
+ if (!iph->id)
+ iph->id = htons(ip_id_count++);
+ iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
+ }
+ return 0;
+}
+
+static int raw_sendmsg(struct sock *sk, struct msghdr *msg, int len)
+{
+ struct ipcm_cookie ipc;
+ struct rawfakehdr rfh;
+ struct rtable *rt = NULL;
+ int free = 0;
+ u32 daddr;
+ u8 tos;
+ int err;
+
+ /* This check is ONLY to check for arithmetic overflow
+ on integer(!) len. Not more! Real check will be made
+ in ip_build_xmit --ANK
+
+ BTW socket.c -> af_*.c -> ... make multiple
+ invalid conversions size_t -> int. We MUST repair it f.e.
+ by replacing all of them with size_t and revise all
+ the places sort of len += sizeof(struct iphdr)
+ If len was ULONG_MAX-10 it would be cathastrophe --ANK
+ */
+
+ if (len < 0 || len > 0xFFFF)
+ return -EMSGSIZE;
+
+ /*
+ * Check the flags.
+ */
+
+ if (msg->msg_flags & MSG_OOB) /* Mirror BSD error message compatibility */
+ return -EOPNOTSUPP;
+
+ if (msg->msg_flags & ~(MSG_DONTROUTE|MSG_DONTWAIT))
+ return(-EINVAL);
+
+ /*
+ * Get and verify the address.
+ */
+
+ if (msg->msg_namelen) {
+ struct sockaddr_in *usin = (struct sockaddr_in*)msg->msg_name;
+ if (msg->msg_namelen < sizeof(*usin))
+ return(-EINVAL);
+ if (usin->sin_family != AF_INET) {
+ static int complained;
+ if (!complained++)
+ printk(KERN_INFO "%s forgot to set AF_INET in raw sendmsg. Fix it!\n", current->comm);
+ if (usin->sin_family)
+ return -EINVAL;
+ }
+ daddr = usin->sin_addr.s_addr;
+ /* ANK: I did not forget to get protocol from port field.
+ * I just do not know, who uses this weirdness.
+ * IP_HDRINCL is much more convenient.
+ */
+ } else {
+ if (sk->state != TCP_ESTABLISHED)
+ return(-EINVAL);
+ daddr = sk->daddr;
+ }
+
+ ipc.addr = sk->saddr;
+ ipc.opt = NULL;
+ ipc.oif = sk->bound_dev_if;
+
+ if (msg->msg_controllen) {
+ int tmp = ip_cmsg_send(msg, &ipc);
+ if (tmp)
+ return tmp;
+ if (ipc.opt)
+ free=1;
+ }
+
+ rfh.saddr = ipc.addr;
+ ipc.addr = daddr;
+
+ if (!ipc.opt)
+ ipc.opt = sk->opt;
+
+ if (ipc.opt) {
+ err = -EINVAL;
+ /* Linux does not mangle headers on raw sockets,
+ * so that IP options + IP_HDRINCL is non-sense.
+ */
+ if (sk->ip_hdrincl)
+ goto done;
+ if (ipc.opt->srr) {
+ if (!daddr)
+ goto done;
+ daddr = ipc.opt->faddr;
+ }
+ }
+ tos = RT_TOS(sk->ip_tos) | sk->localroute;
+ if (msg->msg_flags&MSG_DONTROUTE)
+ tos |= RTO_ONLINK;
+
+ if (MULTICAST(daddr)) {
+ if (!ipc.oif)
+ ipc.oif = sk->ip_mc_index;
+ if (!rfh.saddr)
+ rfh.saddr = sk->ip_mc_addr;
+ }
+
+ err = ip_route_output(&rt, daddr, rfh.saddr, tos, ipc.oif);
+
+ if (err)
+ goto done;
+
+ err = -EACCES;
+ if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast)
+ goto done;
+
+ rfh.iov = msg->msg_iov;
+ rfh.saddr = rt->rt_src;
+ if (!ipc.addr)
+ ipc.addr = rt->rt_dst;
+ err=ip_build_xmit(sk, sk->ip_hdrincl ? raw_getrawfrag : raw_getfrag,
+ &rfh, len, &ipc, rt, msg->msg_flags);
+
+done:
+ if (free)
+ kfree(ipc.opt);
+ ip_rt_put(rt);
+
+ return err<0 ? err : len;
+}
+
+static void raw_close(struct sock *sk, long timeout)
+{
+ /* Observation: when raw_close is called, processes have
+ no access to socket anymore. But net still has.
+ Step one, detach it from networking:
+
+ A. Remove from hash tables.
+ */
+ sk->state = TCP_CLOSE;
+ raw_v4_unhash(sk);
+ /*
+ B. Raw sockets may have direct kernel refereneces. Kill them.
+ */
+ ip_ra_control(sk, 0, NULL);
+
+ /* In this point socket cannot receive new packets anymore */
+
+
+ /* But we still have packets pending on receive
+ queue and probably, our own packets waiting in device queues.
+ sock_destroy will drain receive queue, but transmitted
+ packets will delay socket destruction.
+ Set sk->dead=1 in order to prevent wakeups, when these
+ packet will be freed.
+ */
+ sk->dead=1;
+ destroy_sock(sk);
+
+ /* That's all. No races here. */
+}
+
+/* This gets rid of all the nasties in af_inet. -DaveM */
+static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+ struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
+ int chk_addr_ret;
+
+ if((sk->state != TCP_CLOSE) || (addr_len < sizeof(struct sockaddr_in)))
+ return -EINVAL;
+ chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
+ if(addr->sin_addr.s_addr != 0 && chk_addr_ret != RTN_LOCAL &&
+ chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) {
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ /* Superuser may bind to any address to allow transparent proxying. */
+ if(chk_addr_ret != RTN_UNICAST || !capable(CAP_NET_ADMIN))
+#endif
+ return -EADDRNOTAVAIL;
+ }
+ sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr;
+ if(chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
+ sk->saddr = 0; /* Use device */
+ dst_release(xchg(&sk->dst_cache, NULL));
+ return 0;
+}
+
+/*
+ * This should be easy, if there is something there
+ * we return it, otherwise we block.
+ */
+
+int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
+ int noblock, int flags,int *addr_len)
+{
+ int copied=0;
+ struct sk_buff *skb;
+ int err;
+ struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
+
+ if (flags & MSG_OOB)
+ return -EOPNOTSUPP;
+
+ if (addr_len)
+ *addr_len=sizeof(*sin);
+
+ if (flags & MSG_ERRQUEUE)
+ return ip_recv_error(sk, msg, len);
+
+ skb=skb_recv_datagram(sk,flags,noblock,&err);
+ if(skb==NULL)
+ return err;
+
+ copied = skb->len;
+ if (len < copied)
+ {
+ msg->msg_flags |= MSG_TRUNC;
+ copied = len;
+ }
+
+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+ if (err)
+ goto done;
+
+ sk->stamp=skb->stamp;
+
+ /* Copy the address. */
+ if (sin) {
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = skb->nh.iph->saddr;
+ }
+ if (sk->ip_cmsg_flags)
+ ip_cmsg_recv(msg, skb);
+done:
+ skb_free_datagram(sk, skb);
+ return (err ? : copied);
+}
+
+static int raw_init(struct sock *sk)
+{
+ struct raw_opt *tp = &(sk->tp_pinfo.tp_raw4);
+ if (sk->num == IPPROTO_ICMP)
+ memset(&tp->filter, 0, sizeof(tp->filter));
+ return 0;
+}
+
+static int raw_seticmpfilter(struct sock *sk, char *optval, int optlen)
+{
+ if (optlen > sizeof(struct icmp_filter))
+ optlen = sizeof(struct icmp_filter);
+ if (copy_from_user(&sk->tp_pinfo.tp_raw4.filter, optval, optlen))
+ return -EFAULT;
+ return 0;
+}
+
+static int raw_geticmpfilter(struct sock *sk, char *optval, int *optlen)
+{
+ int len;
+
+ if (get_user(len,optlen))
+ return -EFAULT;
+ if (len > sizeof(struct icmp_filter))
+ len = sizeof(struct icmp_filter);
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &sk->tp_pinfo.tp_raw4.filter, len))
+ return -EFAULT;
+ return 0;
+}
+
+static int raw_setsockopt(struct sock *sk, int level, int optname,
+ char *optval, int optlen)
+{
+ if (level != SOL_RAW)
+ return ip_setsockopt(sk, level, optname, optval, optlen);
+
+ switch (optname) {
+ case ICMP_FILTER:
+ if (sk->num != IPPROTO_ICMP)
+ return -EOPNOTSUPP;
+ return raw_seticmpfilter(sk, optval, optlen);
+ };
+
+ return -ENOPROTOOPT;
+}
+
+static int raw_getsockopt(struct sock *sk, int level, int optname,
+ char *optval, int *optlen)
+{
+ if (level != SOL_RAW)
+ return ip_getsockopt(sk, level, optname, optval, optlen);
+
+ switch (optname) {
+ case ICMP_FILTER:
+ if (sk->num != IPPROTO_ICMP)
+ return -EOPNOTSUPP;
+ return raw_geticmpfilter(sk, optval, optlen);
+ };
+
+ return -ENOPROTOOPT;
+}
+
+struct proto raw_prot = {
+ (struct sock *)&raw_prot, /* sklist_next */
+ (struct sock *)&raw_prot, /* sklist_prev */
+ raw_close, /* close */
+ udp_connect, /* connect */
+ NULL, /* accept */
+ NULL, /* retransmit */
+ NULL, /* write_wakeup */
+ NULL, /* read_wakeup */
+ datagram_poll, /* poll */
+#ifdef CONFIG_IP_MROUTE
+ ipmr_ioctl, /* ioctl */
+#else
+ NULL, /* ioctl */
+#endif
+ raw_init, /* init */
+ NULL, /* destroy */
+ NULL, /* shutdown */
+ raw_setsockopt, /* setsockopt */
+ raw_getsockopt, /* getsockopt */
+ raw_sendmsg, /* sendmsg */
+ raw_recvmsg, /* recvmsg */
+ raw_bind, /* bind */
+ raw_rcv_skb, /* backlog_rcv */
+ raw_v4_hash, /* hash */
+ raw_v4_unhash, /* unhash */
+ NULL, /* get_port */
+ 128, /* max_header */
+ 0, /* retransmits */
+ "RAW", /* name */
+ 0, /* inuse */
+ 0 /* highestinuse */
+};
diff --git a/pfinet/linux-src/net/ipv4/route.c b/pfinet/linux-src/net/ipv4/route.c
new file mode 100644
index 00000000..06eb5fe5
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/route.c
@@ -0,0 +1,2048 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * ROUTE - implementation of the IP router.
+ *
+ * Version: $Id: route.c,v 1.67.2.3 1999/08/08 08:43:12 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Linus Torvalds, <Linus.Torvalds@helsinki.fi>
+ * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Fixes:
+ * Alan Cox : Verify area fixes.
+ * Alan Cox : cli() protects routing changes
+ * Rui Oliveira : ICMP routing table updates
+ * (rco@di.uminho.pt) Routing table insertion and update
+ * Linus Torvalds : Rewrote bits to be sensible
+ * Alan Cox : Added BSD route gw semantics
+ * Alan Cox : Super /proc >4K
+ * Alan Cox : MTU in route table
+ * Alan Cox : MSS actually. Also added the window
+ * clamper.
+ * Sam Lantinga : Fixed route matching in rt_del()
+ * Alan Cox : Routing cache support.
+ * Alan Cox : Removed compatibility cruft.
+ * Alan Cox : RTF_REJECT support.
+ * Alan Cox : TCP irtt support.
+ * Jonathan Naylor : Added Metric support.
+ * Miquel van Smoorenburg : BSD API fixes.
+ * Miquel van Smoorenburg : Metrics.
+ * Alan Cox : Use __u32 properly
+ * Alan Cox : Aligned routing errors more closely with BSD
+ * our system is still very different.
+ * Alan Cox : Faster /proc handling
+ * Alexey Kuznetsov : Massive rework to support tree based routing,
+ * routing caches and better behaviour.
+ *
+ * Olaf Erb : irtt wasn't being copied right.
+ * Bjorn Ekwall : Kerneld route support.
+ * Alan Cox : Multicast fixed (I hope)
+ * Pavel Krauz : Limited broadcast fixed
+ * Mike McLagan : Routing by source
+ * Alexey Kuznetsov : End of old history. Splitted to fib.c and
+ * route.c and rewritten from scratch.
+ * Andi Kleen : Load-limit warning messages.
+ * Vitaly E. Lavrov : Transparent proxy revived after year coma.
+ * Vitaly E. Lavrov : Race condition in ip_route_input_slow.
+ * Tobias Ringstrom : Uninitialized res.type in ip_route_output_slow.
+ * Vladimir V. Ivanov : IP rule info (flowid) is really useful.
+ * Marc Boucher : routing by fwmark
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#include <linux/pkt_sched.h>
+#include <linux/mroute.h>
+#include <net/protocol.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/sock.h>
+#include <net/ip_fib.h>
+#include <net/arp.h>
+#include <net/tcp.h>
+#include <net/icmp.h>
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+#endif
+
+#define IP_MAX_MTU 0xFFF0
+
+#define RT_GC_TIMEOUT (300*HZ)
+
+int ip_rt_min_delay = 2*HZ;
+int ip_rt_max_delay = 10*HZ;
+int ip_rt_gc_thresh = RT_HASH_DIVISOR;
+int ip_rt_max_size = RT_HASH_DIVISOR*16;
+int ip_rt_gc_timeout = RT_GC_TIMEOUT;
+int ip_rt_gc_interval = 60*HZ;
+int ip_rt_gc_min_interval = 5*HZ;
+int ip_rt_redirect_number = 9;
+int ip_rt_redirect_load = HZ/50;
+int ip_rt_redirect_silence = ((HZ/50) << (9+1));
+int ip_rt_error_cost = HZ;
+int ip_rt_error_burst = 5*HZ;
+int ip_rt_gc_elasticity = 8;
+int ip_rt_mtu_expires = 10*60*HZ;
+
+static unsigned long rt_deadline = 0;
+
+#define RTprint(a...) printk(KERN_DEBUG a)
+
+static void rt_run_flush(unsigned long dummy);
+
+static struct timer_list rt_flush_timer =
+ { NULL, NULL, 0, 0L, rt_run_flush };
+static struct timer_list rt_periodic_timer =
+ { NULL, NULL, 0, 0L, NULL };
+
+/*
+ * Interface to generic destination cache.
+ */
+
+static struct dst_entry * ipv4_dst_check(struct dst_entry * dst, u32);
+static struct dst_entry * ipv4_dst_reroute(struct dst_entry * dst,
+ struct sk_buff *);
+static struct dst_entry * ipv4_negative_advice(struct dst_entry *);
+static void ipv4_link_failure(struct sk_buff *skb);
+static int rt_garbage_collect(void);
+
+
+struct dst_ops ipv4_dst_ops =
+{
+ AF_INET,
+ __constant_htons(ETH_P_IP),
+ RT_HASH_DIVISOR,
+
+ rt_garbage_collect,
+ ipv4_dst_check,
+ ipv4_dst_reroute,
+ NULL,
+ ipv4_negative_advice,
+ ipv4_link_failure,
+};
+
+__u8 ip_tos2prio[16] = {
+ TC_PRIO_BESTEFFORT,
+ TC_PRIO_FILLER,
+ TC_PRIO_BESTEFFORT,
+ TC_PRIO_FILLER,
+ TC_PRIO_BULK,
+ TC_PRIO_FILLER,
+ TC_PRIO_BULK,
+ TC_PRIO_FILLER,
+ TC_PRIO_INTERACTIVE,
+ TC_PRIO_FILLER,
+ TC_PRIO_INTERACTIVE,
+ TC_PRIO_FILLER,
+ TC_PRIO_INTERACTIVE_BULK,
+ TC_PRIO_FILLER,
+ TC_PRIO_INTERACTIVE_BULK,
+ TC_PRIO_FILLER
+};
+
+
+/*
+ * Route cache.
+ */
+
+struct rtable *rt_hash_table[RT_HASH_DIVISOR];
+
+static int rt_intern_hash(unsigned hash, struct rtable * rth, struct rtable ** res);
+
+static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
+{
+ unsigned hash = ((daddr&0xF0F0F0F0)>>4)|((daddr&0x0F0F0F0F)<<4);
+ hash = hash^saddr^tos;
+ hash = hash^(hash>>16);
+ return (hash^(hash>>8)) & 0xFF;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static int rt_cache_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len=0;
+ off_t pos=0;
+ char temp[129];
+ struct rtable *r;
+ int i;
+
+ pos = 128;
+
+ if (offset<128) {
+ sprintf(buffer,"%-127s\n", "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\tHHUptod\tSpecDst");
+ len = 128;
+ }
+
+
+ start_bh_atomic();
+
+ for (i = 0; i<RT_HASH_DIVISOR; i++) {
+ for (r = rt_hash_table[i]; r; r = r->u.rt_next) {
+ /*
+ * Spin through entries until we are ready
+ */
+ pos += 128;
+
+ if (pos <= offset) {
+ len = 0;
+ continue;
+ }
+ sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
+ r->u.dst.dev ? r->u.dst.dev->name : "*",
+ (unsigned long)r->rt_dst,
+ (unsigned long)r->rt_gateway,
+ r->rt_flags,
+ atomic_read(&r->u.dst.use),
+ atomic_read(&r->u.dst.refcnt),
+ 0,
+ (unsigned long)r->rt_src, (int)r->u.dst.pmtu,
+ r->u.dst.window,
+ (int)r->u.dst.rtt, r->key.tos,
+ r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1,
+ r->u.dst.hh ? (r->u.dst.hh->hh_output == dev_queue_xmit) : 0,
+ r->rt_spec_dst);
+ sprintf(buffer+len,"%-127s\n",temp);
+ len += 128;
+ if (pos >= offset+length)
+ goto done;
+ }
+ }
+
+done:
+ end_bh_atomic();
+
+ *start = buffer+len-(pos-offset);
+ len = pos-offset;
+ if (len>length)
+ len = length;
+ return len;
+}
+#endif
+
+static __inline__ void rt_free(struct rtable *rt)
+{
+ dst_free(&rt->u.dst);
+}
+
+static __inline__ void rt_drop(struct rtable *rt)
+{
+ ip_rt_put(rt);
+ dst_free(&rt->u.dst);
+}
+
+static __inline__ int rt_fast_clean(struct rtable *rth)
+{
+ /* Kill broadcast/multicast entries very aggresively, if they
+ collide in hash table with more useful entries */
+ return ((rth->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
+ && rth->key.iif && rth->u.rt_next);
+}
+
+static __inline__ int rt_valuable(struct rtable *rth)
+{
+ return ((rth->rt_flags&(RTCF_REDIRECTED|RTCF_NOTIFY))
+ || rth->u.dst.expires);
+}
+
+static __inline__ int rt_may_expire(struct rtable *rth, int tmo1, int tmo2)
+{
+ int age;
+
+ if (atomic_read(&rth->u.dst.use))
+ return 0;
+
+ if (rth->u.dst.expires && (long)(rth->u.dst.expires - jiffies) <= 0)
+ return 1;
+
+ age = jiffies - rth->u.dst.lastuse;
+ if (age <= tmo1 && !rt_fast_clean(rth))
+ return 0;
+ if (age <= tmo2 && rt_valuable(rth))
+ return 0;
+ return 1;
+}
+
+static void rt_check_expire(unsigned long dummy)
+{
+ int i;
+ static int rover;
+ struct rtable *rth, **rthp;
+ unsigned long now = jiffies;
+
+ for (i=0; i<RT_HASH_DIVISOR/5; i++) {
+ unsigned tmo = ip_rt_gc_timeout;
+
+ rover = (rover + 1) & (RT_HASH_DIVISOR-1);
+ rthp = &rt_hash_table[rover];
+
+ while ((rth = *rthp) != NULL) {
+ if (rth->u.dst.expires) {
+ /* Entrie is expired even if it is in use */
+ if ((long)(now - rth->u.dst.expires) <= 0) {
+ tmo >>= 1;
+ rthp = &rth->u.rt_next;
+ continue;
+ }
+ } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) {
+ tmo >>= 1;
+ rthp = &rth->u.rt_next;
+ continue;
+ }
+
+ /*
+ * Cleanup aged off entries.
+ */
+ *rthp = rth->u.rt_next;
+ rt_free(rth);
+ }
+
+ /* Fallback loop breaker. */
+ if ((jiffies - now) > 0)
+ break;
+ }
+ rt_periodic_timer.expires = now + ip_rt_gc_interval;
+ add_timer(&rt_periodic_timer);
+}
+
+static void rt_run_flush(unsigned long dummy)
+{
+ int i;
+ struct rtable * rth, * next;
+
+ rt_deadline = 0;
+
+ start_bh_atomic();
+ for (i=0; i<RT_HASH_DIVISOR; i++) {
+ if ((rth = xchg(&rt_hash_table[i], NULL)) == NULL)
+ continue;
+ end_bh_atomic();
+
+ for (; rth; rth=next) {
+ next = rth->u.rt_next;
+ rth->u.rt_next = NULL;
+ rt_free(rth);
+ }
+
+ start_bh_atomic();
+ }
+ end_bh_atomic();
+}
+
+void rt_cache_flush(int delay)
+{
+ unsigned long now = jiffies;
+ int user_mode = !in_interrupt();
+
+ if (delay < 0)
+ delay = ip_rt_min_delay;
+
+ start_bh_atomic();
+
+ if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) {
+ long tmo = (long)(rt_deadline - now);
+
+ /* If flush timer is already running
+ and flush request is not immediate (delay > 0):
+
+ if deadline is not achieved, prolongate timer to "delay",
+ otherwise fire it at deadline time.
+ */
+
+ if (user_mode && tmo < ip_rt_max_delay-ip_rt_min_delay)
+ tmo = 0;
+
+ if (delay > tmo)
+ delay = tmo;
+ }
+
+ if (delay <= 0) {
+ end_bh_atomic();
+ rt_run_flush(0);
+ return;
+ }
+
+ if (rt_deadline == 0)
+ rt_deadline = now + ip_rt_max_delay;
+
+ rt_flush_timer.expires = now + delay;
+ add_timer(&rt_flush_timer);
+ end_bh_atomic();
+}
+
+/*
+ Short description of GC goals.
+
+ We want to build algorithm, which will keep routing cache
+ at some equilibrium point, when number of aged off entries
+ is kept approximately equal to newly generated ones.
+
+ Current expiration strength is variable "expire".
+ We try to adjust it dynamically, so that if networking
+ is idle expires is large enough to keep enough of warm entries,
+ and when load increases it reduces to limit cache size.
+ */
+
+static int rt_garbage_collect(void)
+{
+ static unsigned expire = RT_GC_TIMEOUT;
+ static unsigned long last_gc;
+ static int rover;
+ static int equilibrium;
+ struct rtable *rth, **rthp;
+ unsigned long now = jiffies;
+ int goal;
+
+ /*
+ * Garbage collection is pretty expensive,
+ * do not make it too frequently.
+ */
+ if (now - last_gc < ip_rt_gc_min_interval &&
+ atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
+ return 0;
+
+ /* Calculate number of entries, which we want to expire now. */
+ goal = atomic_read(&ipv4_dst_ops.entries) - RT_HASH_DIVISOR*ip_rt_gc_elasticity;
+ if (goal <= 0) {
+ if (equilibrium < ipv4_dst_ops.gc_thresh)
+ equilibrium = ipv4_dst_ops.gc_thresh;
+ goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
+ if (goal > 0) {
+ equilibrium += min(goal/2, RT_HASH_DIVISOR);
+ goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
+ }
+ } else {
+ /* We are in dangerous area. Try to reduce cache really
+ * aggressively.
+ */
+ goal = max(goal/2, RT_HASH_DIVISOR);
+ equilibrium = atomic_read(&ipv4_dst_ops.entries) - goal;
+ }
+
+ if (now - last_gc >= ip_rt_gc_min_interval)
+ last_gc = now;
+
+ if (goal <= 0) {
+ equilibrium += goal;
+ goto work_done;
+ }
+
+ do {
+ int i, k;
+
+ start_bh_atomic();
+ for (i=0, k=rover; i<RT_HASH_DIVISOR; i++) {
+ unsigned tmo = expire;
+
+ k = (k + 1) & (RT_HASH_DIVISOR-1);
+ rthp = &rt_hash_table[k];
+ while ((rth = *rthp) != NULL) {
+ if (!rt_may_expire(rth, tmo, expire)) {
+ tmo >>= 1;
+ rthp = &rth->u.rt_next;
+ continue;
+ }
+ *rthp = rth->u.rt_next;
+ rth->u.rt_next = NULL;
+ rt_free(rth);
+ goal--;
+ }
+ if (goal <= 0)
+ break;
+ }
+ rover = k;
+ end_bh_atomic();
+
+ if (goal <= 0)
+ goto work_done;
+
+ /* Goal is not achieved. We stop process if:
+
+ - if expire reduced to zero. Otherwise, expire is halfed.
+ - if table is not full.
+ - if we are called from interrupt.
+ - jiffies check is just fallback/debug loop breaker.
+ We will not spin here for long time in any case.
+ */
+
+ if (expire == 0)
+ break;
+
+ expire >>= 1;
+#if RT_CACHE_DEBUG >= 2
+ printk(KERN_DEBUG "expire>> %u %d %d %d\n", expire, atomic_read(&ipv4_dst_ops.entries), goal, i);
+#endif
+
+ if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
+ return 0;
+ } while (!in_interrupt() && jiffies - now < 1);
+
+ if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
+ return 0;
+ if (net_ratelimit())
+ printk("dst cache overflow\n");
+ return 1;
+
+work_done:
+ expire += ip_rt_gc_min_interval;
+ if (expire > ip_rt_gc_timeout ||
+ atomic_read(&ipv4_dst_ops.entries) < ipv4_dst_ops.gc_thresh)
+ expire = ip_rt_gc_timeout;
+#if RT_CACHE_DEBUG >= 2
+ printk(KERN_DEBUG "expire++ %u %d %d %d\n", expire, atomic_read(&ipv4_dst_ops.entries), goal, rover);
+#endif
+ return 0;
+}
+
+static int rt_intern_hash(unsigned hash, struct rtable * rt, struct rtable ** rp)
+{
+ struct rtable *rth, **rthp;
+ unsigned long now = jiffies;
+ int attempts = !in_interrupt();
+
+restart:
+ start_bh_atomic();
+
+ rthp = &rt_hash_table[hash];
+
+ while ((rth = *rthp) != NULL) {
+ if (memcmp(&rth->key, &rt->key, sizeof(rt->key)) == 0) {
+ /* Put it first */
+ *rthp = rth->u.rt_next;
+ rth->u.rt_next = rt_hash_table[hash];
+ rt_hash_table[hash] = rth;
+
+ atomic_inc(&rth->u.dst.refcnt);
+ atomic_inc(&rth->u.dst.use);
+ rth->u.dst.lastuse = now;
+ end_bh_atomic();
+
+ rt_drop(rt);
+ *rp = rth;
+ return 0;
+ }
+
+ rthp = &rth->u.rt_next;
+ }
+
+ /* Try to bind route to arp only if it is output
+ route or unicast forwarding path.
+ */
+ if (rt->rt_type == RTN_UNICAST || rt->key.iif == 0) {
+ if (!arp_bind_neighbour(&rt->u.dst)) {
+ end_bh_atomic();
+
+ /* Neighbour tables are full and nothing
+ can be released. Try to shrink route cache,
+ it is most likely it holds some neighbour records.
+ */
+ if (attempts-- > 0) {
+ int saved_elasticity = ip_rt_gc_elasticity;
+ int saved_int = ip_rt_gc_min_interval;
+ ip_rt_gc_elasticity = 1;
+ ip_rt_gc_min_interval = 0;
+ rt_garbage_collect();
+ ip_rt_gc_min_interval = saved_int;
+ ip_rt_gc_elasticity = saved_elasticity;
+ goto restart;
+ }
+
+ rt_drop(rt);
+ if (net_ratelimit())
+ printk("neighbour table overflow\n");
+ return -ENOBUFS;
+ }
+ }
+
+ rt->u.rt_next = rt_hash_table[hash];
+#if RT_CACHE_DEBUG >= 2
+ if (rt->u.rt_next) {
+ struct rtable * trt;
+ printk("rt_cache @%02x: %08x", hash, rt->rt_dst);
+ for (trt=rt->u.rt_next; trt; trt=trt->u.rt_next)
+ printk(" . %08x", trt->rt_dst);
+ printk("\n");
+ }
+#endif
+ rt_hash_table[hash] = rt;
+ end_bh_atomic();
+ *rp = rt;
+ return 0;
+}
+
+static void rt_del(unsigned hash, struct rtable *rt)
+{
+ struct rtable **rthp;
+
+ start_bh_atomic();
+ ip_rt_put(rt);
+ for (rthp = &rt_hash_table[hash]; *rthp; rthp = &(*rthp)->u.rt_next) {
+ if (*rthp == rt) {
+ *rthp = rt->u.rt_next;
+ rt_free(rt);
+ break;
+ }
+ }
+ end_bh_atomic();
+}
+
+void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
+ u32 saddr, u8 tos, struct device *dev)
+{
+ int i, k;
+ struct in_device *in_dev = dev->ip_ptr;
+ struct rtable *rth, **rthp;
+ u32 skeys[2] = { saddr, 0 };
+ int ikeys[2] = { dev->ifindex, 0 };
+
+ tos &= IPTOS_TOS_MASK;
+
+ if (!in_dev)
+ return;
+
+ if (new_gw == old_gw || !IN_DEV_RX_REDIRECTS(in_dev)
+ || MULTICAST(new_gw) || BADCLASS(new_gw) || ZERONET(new_gw))
+ goto reject_redirect;
+
+ if (!IN_DEV_SHARED_MEDIA(in_dev)) {
+ if (!inet_addr_onlink(in_dev, new_gw, old_gw))
+ goto reject_redirect;
+ if (IN_DEV_SEC_REDIRECTS(in_dev) && ip_fib_check_default(new_gw, dev))
+ goto reject_redirect;
+ } else {
+ if (inet_addr_type(new_gw) != RTN_UNICAST)
+ goto reject_redirect;
+ }
+
+ for (i=0; i<2; i++) {
+ for (k=0; k<2; k++) {
+ unsigned hash = rt_hash_code(daddr, skeys[i]^(ikeys[k]<<5), tos);
+
+ rthp=&rt_hash_table[hash];
+
+ while ( (rth = *rthp) != NULL) {
+ struct rtable *rt;
+
+ if (rth->key.dst != daddr ||
+ rth->key.src != skeys[i] ||
+ rth->key.tos != tos ||
+ rth->key.oif != ikeys[k] ||
+ rth->key.iif != 0) {
+ rthp = &rth->u.rt_next;
+ continue;
+ }
+
+ if (rth->rt_dst != daddr ||
+ rth->rt_src != saddr ||
+ rth->u.dst.error ||
+ rth->rt_gateway != old_gw ||
+ rth->u.dst.dev != dev)
+ break;
+
+ dst_clone(&rth->u.dst);
+
+ rt = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops);
+ if (rt == NULL) {
+ ip_rt_put(rth);
+ return;
+ }
+
+ /*
+ * Copy all the information.
+ */
+ *rt = *rth;
+ atomic_set(&rt->u.dst.refcnt, 1);
+ atomic_set(&rt->u.dst.use, 1);
+ rt->u.dst.lastuse = jiffies;
+ rt->u.dst.neighbour = NULL;
+ rt->u.dst.hh = NULL;
+ rt->u.dst.obsolete = 0;
+
+ rt->rt_flags |= RTCF_REDIRECTED;
+
+ /* Gateway is different ... */
+ rt->rt_gateway = new_gw;
+
+ /* Redirect received -> path was valid */
+ dst_confirm(&rth->u.dst);
+
+ if (!arp_bind_neighbour(&rt->u.dst) ||
+ !(rt->u.dst.neighbour->nud_state&NUD_VALID)) {
+ if (rt->u.dst.neighbour)
+ neigh_event_send(rt->u.dst.neighbour, NULL);
+ ip_rt_put(rth);
+ rt_drop(rt);
+ break;
+ }
+
+ rt_del(hash, rth);
+
+ if (!rt_intern_hash(hash, rt, &rt))
+ ip_rt_put(rt);
+ break;
+ }
+ }
+ }
+ return;
+
+reject_redirect:
+#ifdef CONFIG_IP_ROUTE_VERBOSE
+ if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
+ printk(KERN_INFO "Redirect from %lX/%s to %lX ignored."
+ "Path = %lX -> %lX, tos %02x\n",
+ ntohl(old_gw), dev->name, ntohl(new_gw),
+ ntohl(saddr), ntohl(daddr), tos);
+#endif
+}
+
+static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
+{
+ struct rtable *rt = (struct rtable*)dst;
+
+ if (rt != NULL) {
+ if (dst->obsolete) {
+ ip_rt_put(rt);
+ return NULL;
+ }
+ if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) {
+ unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos);
+#if RT_CACHE_DEBUG >= 1
+ printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos);
+#endif
+ rt_del(hash, rt);
+ return NULL;
+ }
+ }
+ return dst;
+}
+
+/*
+ * Algorithm:
+ * 1. The first ip_rt_redirect_number redirects are sent
+ * with exponential backoff, then we stop sending them at all,
+ * assuming that the host ignores our redirects.
+ * 2. If we did not see packets requiring redirects
+ * during ip_rt_redirect_silence, we assume that the host
+ * forgot redirected route and start to send redirects again.
+ *
+ * This algorithm is much cheaper and more intelligent than dumb load limiting
+ * in icmp.c.
+ *
+ * NOTE. Do not forget to inhibit load limiting for redirects (redundant)
+ * and "frag. need" (breaks PMTU discovery) in icmp.c.
+ */
+
+void ip_rt_send_redirect(struct sk_buff *skb)
+{
+ struct rtable *rt = (struct rtable*)skb->dst;
+ struct in_device *in_dev = (struct in_device*)rt->u.dst.dev->ip_ptr;
+
+ if (!in_dev || !IN_DEV_TX_REDIRECTS(in_dev))
+ return;
+
+ /* No redirected packets during ip_rt_redirect_silence;
+ * reset the algorithm.
+ */
+ if (jiffies - rt->u.dst.rate_last > ip_rt_redirect_silence)
+ rt->u.dst.rate_tokens = 0;
+
+ /* Too many ignored redirects; do not send anything
+ * set u.dst.rate_last to the last seen redirected packet.
+ */
+ if (rt->u.dst.rate_tokens >= ip_rt_redirect_number) {
+ rt->u.dst.rate_last = jiffies;
+ return;
+ }
+
+ /* Check for load limit; set rate_last to the latest sent
+ * redirect.
+ */
+ if (jiffies - rt->u.dst.rate_last > (ip_rt_redirect_load<<rt->u.dst.rate_tokens)) {
+ icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
+ rt->u.dst.rate_last = jiffies;
+ ++rt->u.dst.rate_tokens;
+#ifdef CONFIG_IP_ROUTE_VERBOSE
+ if (IN_DEV_LOG_MARTIANS(in_dev) &&
+ rt->u.dst.rate_tokens == ip_rt_redirect_number && net_ratelimit())
+ printk(KERN_WARNING "host %08x/if%d ignores redirects for %08x to %08x.\n",
+ rt->rt_src, rt->rt_iif, rt->rt_dst, rt->rt_gateway);
+#endif
+ }
+}
+
+static int ip_error(struct sk_buff *skb)
+{
+ struct rtable *rt = (struct rtable*)skb->dst;
+ unsigned long now;
+ int code;
+
+ switch (rt->u.dst.error) {
+ case EINVAL:
+ default:
+ kfree_skb(skb);
+ return 0;
+ case EHOSTUNREACH:
+ code = ICMP_HOST_UNREACH;
+ break;
+ case ENETUNREACH:
+ code = ICMP_NET_UNREACH;
+ break;
+ case EACCES:
+ code = ICMP_PKT_FILTERED;
+ break;
+ }
+
+ now = jiffies;
+ if ((rt->u.dst.rate_tokens += (now - rt->u.dst.rate_last)) > ip_rt_error_burst)
+ rt->u.dst.rate_tokens = ip_rt_error_burst;
+ rt->u.dst.rate_last = now;
+ if (rt->u.dst.rate_tokens >= ip_rt_error_cost) {
+ rt->u.dst.rate_tokens -= ip_rt_error_cost;
+ icmp_send(skb, ICMP_DEST_UNREACH, code, 0);
+ }
+
+ kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * The last two values are not from the RFC but
+ * are needed for AMPRnet AX.25 paths.
+ */
+
+static unsigned short mtu_plateau[] =
+{32000, 17914, 8166, 4352, 2002, 1492, 576, 296, 216, 128 };
+
+static __inline__ unsigned short guess_mtu(unsigned short old_mtu)
+{
+ int i;
+
+ for (i = 0; i < sizeof(mtu_plateau)/sizeof(mtu_plateau[0]); i++)
+ if (old_mtu > mtu_plateau[i])
+ return mtu_plateau[i];
+ return 68;
+}
+
+unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
+{
+ int i;
+ unsigned short old_mtu = ntohs(iph->tot_len);
+ struct rtable *rth;
+ u32 skeys[2] = { iph->saddr, 0, };
+ u32 daddr = iph->daddr;
+ u8 tos = iph->tos & IPTOS_TOS_MASK;
+ unsigned short est_mtu = 0;
+
+ if (ipv4_config.no_pmtu_disc)
+ return 0;
+
+ for (i=0; i<2; i++) {
+ unsigned hash = rt_hash_code(daddr, skeys[i], tos);
+
+ for (rth = rt_hash_table[hash]; rth; rth = rth->u.rt_next) {
+ if (rth->key.dst == daddr &&
+ rth->key.src == skeys[i] &&
+ rth->rt_dst == daddr &&
+ rth->rt_src == iph->saddr &&
+ rth->key.tos == tos &&
+ rth->key.iif == 0 &&
+ !(rth->u.dst.mxlock&(1<<RTAX_MTU))) {
+ unsigned short mtu = new_mtu;
+
+ if (new_mtu < 68 || new_mtu >= old_mtu) {
+
+ /* BSD 4.2 compatibility hack :-( */
+ if (mtu == 0 && old_mtu >= rth->u.dst.pmtu &&
+ old_mtu >= 68 + (iph->ihl<<2))
+ old_mtu -= iph->ihl<<2;
+
+ mtu = guess_mtu(old_mtu);
+ }
+ if (mtu <= rth->u.dst.pmtu) {
+ if (mtu < rth->u.dst.pmtu) {
+ dst_confirm(&rth->u.dst);
+ rth->u.dst.pmtu = mtu;
+ dst_set_expires(&rth->u.dst, ip_rt_mtu_expires);
+ }
+ est_mtu = mtu;
+ }
+ }
+ }
+ }
+ return est_mtu ? : new_mtu;
+}
+
+void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu)
+{
+ if (dst->pmtu > mtu && mtu >= 68 &&
+ !(dst->mxlock&(1<<RTAX_MTU))) {
+ dst->pmtu = mtu;
+ dst_set_expires(dst, ip_rt_mtu_expires);
+ }
+}
+
+static struct dst_entry * ipv4_dst_check(struct dst_entry * dst, u32 cookie)
+{
+ dst_release(dst);
+ return NULL;
+}
+
+static struct dst_entry * ipv4_dst_reroute(struct dst_entry * dst,
+ struct sk_buff *skb)
+{
+ return NULL;
+}
+
+static void ipv4_link_failure(struct sk_buff *skb)
+{
+ struct rtable *rt;
+
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+
+ rt = (struct rtable *) skb->dst;
+ if (rt)
+ dst_set_expires(&rt->u.dst, 0);
+}
+
+static int ip_rt_bug(struct sk_buff *skb)
+{
+ printk(KERN_DEBUG "ip_rt_bug: %08x -> %08x, %s\n", skb->nh.iph->saddr,
+ skb->nh.iph->daddr, skb->dev ? skb->dev->name : "?");
+ kfree_skb(skb);
+ return 0;
+}
+
+/*
+ We do not cache source address of outgoing interface,
+ because it is used only by IP RR, TS and SRR options,
+ so that it out of fast path.
+
+ BTW remember: "addr" is allowed to be not aligned
+ in IP options!
+ */
+
+void ip_rt_get_source(u8 *addr, struct rtable *rt)
+{
+ u32 src;
+ struct fib_result res;
+
+ if (rt->key.iif == 0)
+ src = rt->rt_src;
+ else if (fib_lookup(&rt->key, &res) == 0 && res.type != RTN_NAT)
+ src = FIB_RES_PREFSRC(res);
+ else
+ src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+ memcpy(addr, &src, 4);
+}
+
+#ifdef CONFIG_NET_CLS_ROUTE
+static void set_class_tag(struct rtable *rt, u32 tag)
+{
+ if (!(rt->u.dst.tclassid&0xFFFF))
+ rt->u.dst.tclassid |= tag&0xFFFF;
+ if (!(rt->u.dst.tclassid&0xFFFF0000))
+ rt->u.dst.tclassid |= tag&0xFFFF0000;
+}
+#endif
+
+static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
+{
+ struct fib_info *fi = res->fi;
+
+ if (fi) {
+ if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
+ rt->rt_gateway = FIB_RES_GW(*res);
+ rt->u.dst.mxlock = fi->fib_metrics[RTAX_LOCK-1];
+ rt->u.dst.pmtu = fi->fib_mtu;
+ if (fi->fib_mtu == 0) {
+ rt->u.dst.pmtu = rt->u.dst.dev->mtu;
+ if (rt->u.dst.pmtu > IP_MAX_MTU)
+ rt->u.dst.pmtu = IP_MAX_MTU;
+ if (rt->u.dst.pmtu < 68)
+ rt->u.dst.pmtu = 68;
+ if (rt->u.dst.mxlock&(1<<RTAX_MTU) &&
+ rt->rt_gateway != rt->rt_dst &&
+ rt->u.dst.pmtu > 576)
+ rt->u.dst.pmtu = 576;
+ }
+ rt->u.dst.window= fi->fib_window ? : 0;
+ rt->u.dst.rtt = fi->fib_rtt ? : TCP_TIMEOUT_INIT;
+#ifdef CONFIG_NET_CLS_ROUTE
+ rt->u.dst.tclassid = FIB_RES_NH(*res).nh_tclassid;
+#endif
+ } else {
+ rt->u.dst.pmtu = rt->u.dst.dev->mtu;
+ if (rt->u.dst.pmtu > IP_MAX_MTU)
+ rt->u.dst.pmtu = IP_MAX_MTU;
+ if (rt->u.dst.pmtu < 68)
+ rt->u.dst.pmtu = 68;
+ rt->u.dst.window= 0;
+ rt->u.dst.rtt = TCP_TIMEOUT_INIT;
+ }
+#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ set_class_tag(rt, fib_rules_tclass(res));
+#endif
+ set_class_tag(rt, itag);
+#endif
+ rt->rt_type = res->type;
+}
+
+static int
+ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
+ u8 tos, struct device *dev, int our)
+{
+ unsigned hash;
+ struct rtable *rth;
+ u32 spec_dst;
+ struct in_device *in_dev = dev->ip_ptr;
+ u32 itag = 0;
+
+ /* Primary sanity checks. */
+
+ if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr) ||
+ in_dev == NULL || skb->protocol != __constant_htons(ETH_P_IP))
+ return -EINVAL;
+
+ if (ZERONET(saddr)) {
+ if (!LOCAL_MCAST(daddr))
+ return -EINVAL;
+ spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
+ } else if (fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag) < 0)
+ return -EINVAL;
+
+ rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops);
+ if (!rth)
+ return -ENOBUFS;
+
+ rth->u.dst.output= ip_rt_bug;
+
+ atomic_set(&rth->u.dst.use, 1);
+ rth->key.dst = daddr;
+ rth->rt_dst = daddr;
+ rth->key.tos = tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->key.fwmark = skb->fwmark;
+#endif
+ rth->key.src = saddr;
+ rth->rt_src = saddr;
+#ifdef CONFIG_IP_ROUTE_NAT
+ rth->rt_dst_map = daddr;
+ rth->rt_src_map = saddr;
+#endif
+#ifdef CONFIG_NET_CLS_ROUTE
+ rth->u.dst.tclassid = itag;
+#endif
+ rth->rt_iif =
+ rth->key.iif = dev->ifindex;
+ rth->u.dst.dev = &loopback_dev;
+ rth->key.oif = 0;
+ rth->rt_gateway = daddr;
+ rth->rt_spec_dst= spec_dst;
+ rth->rt_type = RTN_MULTICAST;
+ rth->rt_flags = RTCF_MULTICAST;
+ if (our) {
+ rth->u.dst.input= ip_local_deliver;
+ rth->rt_flags |= RTCF_LOCAL;
+ }
+
+#ifdef CONFIG_IP_MROUTE
+ if (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
+ rth->u.dst.input = ip_mr_input;
+#endif
+
+ hash = rt_hash_code(daddr, saddr^(dev->ifindex<<5), tos);
+ return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+}
+
+/*
+ * NOTE. We drop all the packets that has local source
+ * addresses, because every properly looped back packet
+ * must have correct destination already attached by output routine.
+ *
+ * Such approach solves two big problems:
+ * 1. Not simplex devices are handled properly.
+ * 2. IP spoofing attempts are filtered with 100% of guarantee.
+ */
+
+int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
+ u8 tos, struct device *dev)
+{
+ struct rt_key key;
+ struct fib_result res;
+ struct in_device *in_dev = dev->ip_ptr;
+ struct in_device *out_dev;
+ unsigned flags = 0;
+ u32 itag = 0;
+ struct rtable * rth;
+ unsigned hash;
+ u32 spec_dst;
+ int err = -EINVAL;
+
+ /*
+ * IP on this device is disabled.
+ */
+
+ if (!in_dev)
+ return -EINVAL;
+
+ key.dst = daddr;
+ key.src = saddr;
+ key.tos = tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ key.fwmark = skb->fwmark;
+#endif
+ key.iif = dev->ifindex;
+ key.oif = 0;
+ key.scope = RT_SCOPE_UNIVERSE;
+
+ hash = rt_hash_code(daddr, saddr^(key.iif<<5), tos);
+
+ /* Check for the most weird martians, which can be not detected
+ by fib_lookup.
+ */
+
+ if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr))
+ goto martian_source;
+
+ if (daddr == 0xFFFFFFFF || (saddr == 0 && daddr == 0))
+ goto brd_input;
+
+ /* Accept zero addresses only to limited broadcast;
+ * I even do not know to fix it or not. Waiting for complains :-)
+ */
+ if (ZERONET(saddr))
+ goto martian_source;
+
+ if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))
+ goto martian_destination;
+
+ /*
+ * Now we are ready to route packet.
+ */
+ if ((err = fib_lookup(&key, &res))) {
+ if (!IN_DEV_FORWARD(in_dev))
+ return -EINVAL;
+ goto no_route;
+ }
+
+#ifdef CONFIG_IP_ROUTE_NAT
+ /* Policy is applied before mapping destination,
+ but rerouting after map should be made with old source.
+ */
+
+ if (1) {
+ u32 src_map = saddr;
+ if (res.r)
+ src_map = fib_rules_policy(saddr, &res, &flags);
+
+ if (res.type == RTN_NAT) {
+ key.dst = fib_rules_map_destination(daddr, &res);
+ if (fib_lookup(&key, &res) || res.type != RTN_UNICAST)
+ return -EINVAL;
+ flags |= RTCF_DNAT;
+ }
+ key.src = src_map;
+ }
+#endif
+
+ if (res.type == RTN_BROADCAST)
+ goto brd_input;
+
+ if (res.type == RTN_LOCAL) {
+ int result;
+ result = fib_validate_source(saddr, daddr, tos, loopback_dev.ifindex,
+ dev, &spec_dst, &itag);
+ if (result < 0)
+ goto martian_source;
+ if (result)
+ flags |= RTCF_DIRECTSRC;
+ spec_dst = daddr;
+ goto local_input;
+ }
+
+ if (!IN_DEV_FORWARD(in_dev))
+ return -EINVAL;
+ if (res.type != RTN_UNICAST)
+ goto martian_destination;
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (res.fi->fib_nhs > 1 && key.oif == 0)
+ fib_select_multipath(&key, &res);
+#endif
+ out_dev = FIB_RES_DEV(res)->ip_ptr;
+ if (out_dev == NULL) {
+ if (net_ratelimit())
+ printk(KERN_CRIT "Bug in ip_route_input_slow(). Please, report\n");
+ return -EINVAL;
+ }
+
+ err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev, &spec_dst, &itag);
+ if (err < 0)
+ goto martian_source;
+
+ if (err)
+ flags |= RTCF_DIRECTSRC;
+
+ if (out_dev == in_dev && err && !(flags&(RTCF_NAT|RTCF_MASQ)) &&
+ (IN_DEV_SHARED_MEDIA(out_dev)
+ || inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
+ flags |= RTCF_DOREDIRECT;
+
+ if (skb->protocol != __constant_htons(ETH_P_IP)) {
+ /* Not IP (i.e. ARP). Do not create route, if it is
+ * invalid for proxy arp. DNAT routes are always valid.
+ */
+ if (out_dev == in_dev && !(flags&RTCF_DNAT))
+ return -EINVAL;
+ }
+
+ rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops);
+ if (!rth)
+ return -ENOBUFS;
+
+ atomic_set(&rth->u.dst.use, 1);
+ rth->key.dst = daddr;
+ rth->rt_dst = daddr;
+ rth->key.tos = tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->key.fwmark = skb->fwmark;
+#endif
+ rth->key.src = saddr;
+ rth->rt_src = saddr;
+ rth->rt_gateway = daddr;
+#ifdef CONFIG_IP_ROUTE_NAT
+ rth->rt_src_map = key.src;
+ rth->rt_dst_map = key.dst;
+ if (flags&RTCF_DNAT)
+ rth->rt_gateway = key.dst;
+#endif
+ rth->rt_iif =
+ rth->key.iif = dev->ifindex;
+ rth->u.dst.dev = out_dev->dev;
+ rth->key.oif = 0;
+ rth->rt_spec_dst= spec_dst;
+
+ rth->u.dst.input = ip_forward;
+ rth->u.dst.output = ip_output;
+
+ rt_set_nexthop(rth, &res, itag);
+
+ rth->rt_flags = flags;
+
+#ifdef CONFIG_NET_FASTROUTE
+ if (netdev_fastroute && !(flags&(RTCF_NAT|RTCF_MASQ|RTCF_DOREDIRECT))) {
+ struct device *odev = rth->u.dst.dev;
+ if (odev != dev &&
+ dev->accept_fastpath &&
+ odev->mtu >= dev->mtu &&
+ dev->accept_fastpath(dev, &rth->u.dst) == 0)
+ rth->rt_flags |= RTCF_FAST;
+ }
+#endif
+
+ return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+
+brd_input:
+ if (skb->protocol != __constant_htons(ETH_P_IP))
+ return -EINVAL;
+
+ if (ZERONET(saddr)) {
+ spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
+ } else {
+ err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag);
+ if (err < 0)
+ goto martian_source;
+ if (err)
+ flags |= RTCF_DIRECTSRC;
+ }
+ flags |= RTCF_BROADCAST;
+ res.type = RTN_BROADCAST;
+
+local_input:
+ rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops);
+ if (!rth)
+ return -ENOBUFS;
+
+ rth->u.dst.output= ip_rt_bug;
+
+ atomic_set(&rth->u.dst.use, 1);
+ rth->key.dst = daddr;
+ rth->rt_dst = daddr;
+ rth->key.tos = tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->key.fwmark = skb->fwmark;
+#endif
+ rth->key.src = saddr;
+ rth->rt_src = saddr;
+#ifdef CONFIG_IP_ROUTE_NAT
+ rth->rt_dst_map = key.dst;
+ rth->rt_src_map = key.src;
+#endif
+#ifdef CONFIG_NET_CLS_ROUTE
+ rth->u.dst.tclassid = itag;
+#endif
+ rth->rt_iif =
+ rth->key.iif = dev->ifindex;
+ rth->u.dst.dev = &loopback_dev;
+ rth->key.oif = 0;
+ rth->rt_gateway = daddr;
+ rth->rt_spec_dst= spec_dst;
+ rth->u.dst.input= ip_local_deliver;
+ rth->rt_flags = flags|RTCF_LOCAL;
+ if (res.type == RTN_UNREACHABLE) {
+ rth->u.dst.input= ip_error;
+ rth->u.dst.error= -err;
+ rth->rt_flags &= ~RTCF_LOCAL;
+ }
+ rth->rt_type = res.type;
+ return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+
+no_route:
+ spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
+ res.type = RTN_UNREACHABLE;
+ goto local_input;
+
+ /*
+ * Do not cache martian addresses: they should be logged (RFC1812)
+ */
+martian_destination:
+#ifdef CONFIG_IP_ROUTE_VERBOSE
+ if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
+ printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name);
+#endif
+ return -EINVAL;
+
+martian_source:
+#ifdef CONFIG_IP_ROUTE_VERBOSE
+ if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
+ /*
+ * RFC1812 recommenadtion, if source is martian,
+ * the only hint is MAC header.
+ */
+ printk(KERN_WARNING "martian source %08x for %08x, dev %s\n", saddr, daddr, dev->name);
+ if (dev->hard_header_len) {
+ int i;
+ unsigned char *p = skb->mac.raw;
+ printk(KERN_WARNING "ll header:");
+ for (i=0; i<dev->hard_header_len; i++, p++)
+ printk(" %02x", *p);
+ printk("\n");
+ }
+ }
+#endif
+ return -EINVAL;
+}
+
+int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
+ u8 tos, struct device *dev)
+{
+ struct rtable * rth;
+ unsigned hash;
+ int iif = dev->ifindex;
+
+ tos &= IPTOS_TOS_MASK;
+ hash = rt_hash_code(daddr, saddr^(iif<<5), tos);
+
+ for (rth=rt_hash_table[hash]; rth; rth=rth->u.rt_next) {
+ if (rth->key.dst == daddr &&
+ rth->key.src == saddr &&
+ rth->key.iif == iif &&
+ rth->key.oif == 0 &&
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->key.fwmark == skb->fwmark &&
+#endif
+ rth->key.tos == tos) {
+ rth->u.dst.lastuse = jiffies;
+ atomic_inc(&rth->u.dst.use);
+ atomic_inc(&rth->u.dst.refcnt);
+ skb->dst = (struct dst_entry*)rth;
+ return 0;
+ }
+ }
+
+ /* Multicast recognition logic is moved from route cache to here.
+ The problem was that too many Ethernet cards have broken/missing
+ hardware multicast filters :-( As result the host on multicasting
+ network acquires a lot of useless route cache entries, sort of
+ SDR messages from all the world. Now we try to get rid of them.
+ Really, provided software IP multicast filter is organized
+ reasonably (at least, hashed), it does not result in a slowdown
+ comparing with route cache reject entries.
+ Note, that multicast routers are not affected, because
+ route cache entry is created eventually.
+ */
+ if (MULTICAST(daddr)) {
+ int our = ip_check_mc(dev, daddr);
+ if (!our
+#ifdef CONFIG_IP_MROUTE
+ && (LOCAL_MCAST(daddr) || !dev->ip_ptr ||
+ !IN_DEV_MFORWARD((struct in_device*)dev->ip_ptr))
+#endif
+ ) return -EINVAL;
+ return ip_route_input_mc(skb, daddr, saddr, tos, dev, our);
+ }
+ return ip_route_input_slow(skb, daddr, saddr, tos, dev);
+}
+
+/*
+ * Major route resolver routine.
+ */
+
+int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif)
+{
+ struct rt_key key;
+ struct fib_result res;
+ unsigned flags = 0;
+ struct rtable *rth;
+ struct device *dev_out = NULL;
+ unsigned hash;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ u32 nochecksrc = (tos & RTO_TPROXY);
+#endif
+
+ tos &= IPTOS_TOS_MASK|RTO_ONLINK;
+ key.dst = daddr;
+ key.src = saddr;
+ key.tos = tos&IPTOS_TOS_MASK;
+ key.iif = loopback_dev.ifindex;
+ key.oif = oif;
+ key.scope = (tos&RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
+ res.fi = NULL;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+ res.r = NULL;
+#endif
+
+ if (saddr) {
+ if (MULTICAST(saddr) || BADCLASS(saddr) || ZERONET(saddr))
+ return -EINVAL;
+
+ /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
+ dev_out = ip_dev_find(saddr);
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ /* If address is not local, test for transparent proxy flag;
+ if address is local --- clear the flag.
+ */
+ if (dev_out == NULL) {
+ if (nochecksrc == 0 || inet_addr_type(saddr) != RTN_UNICAST)
+ return -EINVAL;
+ flags |= RTCF_TPROXY;
+ }
+#else
+ if (dev_out == NULL)
+ return -EINVAL;
+#endif
+
+ /* I removed check for oif == dev_out->oif here.
+ It was wrong by three reasons:
+ 1. ip_dev_find(saddr) can return wrong iface, if saddr is
+ assigned to multiple interfaces.
+ 2. Moreover, we are allowed to send packets with saddr
+ of another iface. --ANK
+ */
+
+ if (oif == 0 &&
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ dev_out &&
+#endif
+ (MULTICAST(daddr) || daddr == 0xFFFFFFFF)) {
+ /* Special hack: user can direct multicasts
+ and limited broadcast via necessary interface
+ without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
+ This hack is not just for fun, it allows
+ vic,vat and friends to work.
+ They bind socket to loopback, set ttl to zero
+ and expect that it will work.
+ From the viewpoint of routing cache they are broken,
+ because we are not allowed to build multicast path
+ with loopback source addr (look, routing cache
+ cannot know, that ttl is zero, so that packet
+ will not leave this host and route is valid).
+ Luckily, this hack is good workaround.
+ */
+
+ key.oif = dev_out->ifindex;
+ goto make_route;
+ }
+ dev_out = NULL;
+ }
+ if (oif) {
+ dev_out = dev_get_by_index(oif);
+ if (dev_out == NULL)
+ return -ENODEV;
+ if (dev_out->ip_ptr == NULL)
+ return -ENODEV; /* Wrong error code */
+
+ if (LOCAL_MCAST(daddr) || daddr == 0xFFFFFFFF) {
+ if (!key.src)
+ key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
+ goto make_route;
+ }
+ if (!key.src) {
+ if (MULTICAST(daddr))
+ key.src = inet_select_addr(dev_out, 0, key.scope);
+ else if (!daddr)
+ key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST);
+ }
+ }
+
+ if (!key.dst) {
+ key.dst = key.src;
+ if (!key.dst)
+ key.dst = key.src = htonl(INADDR_LOOPBACK);
+ dev_out = &loopback_dev;
+ key.oif = loopback_dev.ifindex;
+ res.type = RTN_LOCAL;
+ flags |= RTCF_LOCAL;
+ goto make_route;
+ }
+
+ if (fib_lookup(&key, &res)) {
+ res.fi = NULL;
+ if (oif) {
+ /* Apparently, routing tables are wrong. Assume,
+ that the destination is on link.
+
+ WHY? DW.
+ Because we are allowed to send to iface
+ even if it has NO routes and NO assigned
+ addresses. When oif is specified, routing
+ tables are looked up with only one purpose:
+ to catch if destination is gatewayed, rather than
+ direct. Moreover, if MSG_DONTROUTE is set,
+ we send packet, ignoring both routing tables
+ and ifaddr state. --ANK
+
+
+ We could make it even if oif is unknown,
+ likely IPv6, but we do not.
+ */
+
+ if (key.src == 0)
+ key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
+ res.type = RTN_UNICAST;
+ goto make_route;
+ }
+ return -ENETUNREACH;
+ }
+
+ if (res.type == RTN_NAT)
+ return -EINVAL;
+
+ if (res.type == RTN_LOCAL) {
+ if (!key.src)
+ key.src = key.dst;
+ dev_out = &loopback_dev;
+ key.oif = dev_out->ifindex;
+ res.fi = NULL;
+ flags |= RTCF_LOCAL;
+ goto make_route;
+ }
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (res.fi->fib_nhs > 1 && key.oif == 0)
+ fib_select_multipath(&key, &res);
+ else
+#endif
+ if (res.prefixlen==0 && res.type == RTN_UNICAST && key.oif == 0)
+ fib_select_default(&key, &res);
+
+ if (!key.src)
+ key.src = FIB_RES_PREFSRC(res);
+
+ dev_out = FIB_RES_DEV(res);
+ key.oif = dev_out->ifindex;
+
+make_route:
+ if (LOOPBACK(key.src) && !(dev_out->flags&IFF_LOOPBACK))
+ return -EINVAL;
+
+ if (key.dst == 0xFFFFFFFF)
+ res.type = RTN_BROADCAST;
+ else if (MULTICAST(key.dst))
+ res.type = RTN_MULTICAST;
+ else if (BADCLASS(key.dst) || ZERONET(key.dst))
+ return -EINVAL;
+
+ if (dev_out->flags&IFF_LOOPBACK)
+ flags |= RTCF_LOCAL;
+
+ if (res.type == RTN_BROADCAST) {
+ flags |= RTCF_BROADCAST|RTCF_LOCAL;
+ res.fi = NULL;
+ } else if (res.type == RTN_MULTICAST) {
+ flags |= RTCF_MULTICAST|RTCF_LOCAL;
+ if (!ip_check_mc(dev_out, daddr))
+ flags &= ~RTCF_LOCAL;
+ /* If multicast route do not exist use
+ default one, but do not gateway in this case.
+ Yes, it is hack.
+ */
+ if (res.fi && res.prefixlen < 4)
+ res.fi = NULL;
+ }
+
+ rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops);
+ if (!rth)
+ return -ENOBUFS;
+
+ atomic_set(&rth->u.dst.use, 1);
+ rth->key.dst = daddr;
+ rth->key.tos = tos;
+ rth->key.src = saddr;
+ rth->key.iif = 0;
+ rth->key.oif = oif;
+ rth->rt_dst = key.dst;
+ rth->rt_src = key.src;
+#ifdef CONFIG_IP_ROUTE_NAT
+ rth->rt_dst_map = key.dst;
+ rth->rt_src_map = key.src;
+#endif
+ rth->rt_iif = oif ? : dev_out->ifindex;
+ rth->u.dst.dev = dev_out;
+ rth->rt_gateway = key.dst;
+ rth->rt_spec_dst= key.src;
+
+ rth->u.dst.output=ip_output;
+
+ if (flags&RTCF_LOCAL) {
+ rth->u.dst.input = ip_local_deliver;
+ rth->rt_spec_dst = key.dst;
+ }
+ if (flags&(RTCF_BROADCAST|RTCF_MULTICAST)) {
+ rth->rt_spec_dst = key.src;
+ if (flags&RTCF_LOCAL && !(dev_out->flags&IFF_LOOPBACK))
+ rth->u.dst.output = ip_mc_output;
+#ifdef CONFIG_IP_MROUTE
+ if (res.type == RTN_MULTICAST && dev_out->ip_ptr) {
+ struct in_device *in_dev = dev_out->ip_ptr;
+ if (IN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(daddr)) {
+ rth->u.dst.input = ip_mr_input;
+ rth->u.dst.output = ip_mc_output;
+ }
+ }
+#endif
+ }
+
+ rt_set_nexthop(rth, &res, 0);
+
+ rth->rt_flags = flags;
+
+ hash = rt_hash_code(daddr, saddr^(oif<<5), tos);
+ return rt_intern_hash(hash, rth, rp);
+}
+
+int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif)
+{
+ unsigned hash;
+ struct rtable *rth;
+
+ hash = rt_hash_code(daddr, saddr^(oif<<5), tos);
+
+ start_bh_atomic();
+ for (rth=rt_hash_table[hash]; rth; rth=rth->u.rt_next) {
+ if (rth->key.dst == daddr &&
+ rth->key.src == saddr &&
+ rth->key.iif == 0 &&
+ rth->key.oif == oif &&
+#ifndef CONFIG_IP_TRANSPARENT_PROXY
+ rth->key.tos == tos
+#else
+ !((rth->key.tos^tos)&(IPTOS_TOS_MASK|RTO_ONLINK)) &&
+ ((tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY))
+#endif
+ ) {
+ rth->u.dst.lastuse = jiffies;
+ atomic_inc(&rth->u.dst.use);
+ atomic_inc(&rth->u.dst.refcnt);
+ end_bh_atomic();
+ *rp = rth;
+ return 0;
+ }
+ }
+ end_bh_atomic();
+
+ return ip_route_output_slow(rp, daddr, saddr, tos, oif);
+}
+
+#ifdef CONFIG_RTNETLINK
+
+static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait)
+{
+ struct rtable *rt = (struct rtable*)skb->dst;
+ struct rtmsg *r;
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
+ struct rta_cacheinfo ci;
+#ifdef CONFIG_IP_MROUTE
+ struct rtattr *eptr;
+#endif
+ struct rtattr *mx;
+
+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
+ r = NLMSG_DATA(nlh);
+ nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
+ r->rtm_family = AF_INET;
+ r->rtm_dst_len = 32;
+ r->rtm_src_len = 0;
+ r->rtm_tos = rt->key.tos;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = rt->rt_type;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+ r->rtm_protocol = RTPROT_UNSPEC;
+ r->rtm_flags = (rt->rt_flags&~0xFFFF) | RTM_F_CLONED;
+ if (rt->rt_flags & RTCF_NOTIFY)
+ r->rtm_flags |= RTM_F_NOTIFY;
+ RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst);
+ if (rt->key.src) {
+ r->rtm_src_len = 32;
+ RTA_PUT(skb, RTA_SRC, 4, &rt->key.src);
+ }
+ if (rt->u.dst.dev)
+ RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex);
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (rt->u.dst.tclassid)
+ RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid);
+#endif
+ if (rt->key.iif)
+ RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst);
+ else if (rt->rt_src != rt->key.src)
+ RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src);
+ if (rt->rt_dst != rt->rt_gateway)
+ RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway);
+ mx = (struct rtattr*)skb->tail;
+ RTA_PUT(skb, RTA_METRICS, 0, NULL);
+ if (rt->u.dst.mxlock)
+ RTA_PUT(skb, RTAX_LOCK, sizeof(unsigned), &rt->u.dst.mxlock);
+ if (rt->u.dst.pmtu)
+ RTA_PUT(skb, RTAX_MTU, sizeof(unsigned), &rt->u.dst.pmtu);
+ if (rt->u.dst.window)
+ RTA_PUT(skb, RTAX_WINDOW, sizeof(unsigned), &rt->u.dst.window);
+ if (rt->u.dst.rtt)
+ RTA_PUT(skb, RTAX_RTT, sizeof(unsigned), &rt->u.dst.rtt);
+ mx->rta_len = skb->tail - (u8*)mx;
+ if (mx->rta_len == RTA_LENGTH(0))
+ skb_trim(skb, (u8*)mx - skb->data);
+ ci.rta_lastuse = jiffies - rt->u.dst.lastuse;
+ ci.rta_used = atomic_read(&rt->u.dst.refcnt);
+ ci.rta_clntref = atomic_read(&rt->u.dst.use);
+ if (rt->u.dst.expires)
+ ci.rta_expires = rt->u.dst.expires - jiffies;
+ else
+ ci.rta_expires = 0;
+ ci.rta_error = rt->u.dst.error;
+#ifdef CONFIG_IP_MROUTE
+ eptr = (struct rtattr*)skb->tail;
+#endif
+ RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+ if (rt->key.iif) {
+#ifdef CONFIG_IP_MROUTE
+ u32 dst = rt->rt_dst;
+
+ if (MULTICAST(dst) && !LOCAL_MCAST(dst) && ipv4_devconf.mc_forwarding) {
+ int err = ipmr_get_route(skb, r, nowait);
+ if (err <= 0) {
+ if (!nowait) {
+ if (err == 0)
+ return 0;
+ goto nlmsg_failure;
+ } else {
+ if (err == -EMSGSIZE)
+ goto nlmsg_failure;
+ ((struct rta_cacheinfo*)RTA_DATA(eptr))->rta_error = err;
+ }
+ }
+ } else
+#endif
+ {
+ RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->key.iif);
+ }
+ }
+
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+{
+ struct rtattr **rta = arg;
+ struct rtmsg *rtm = NLMSG_DATA(nlh);
+ struct rtable *rt = NULL;
+ u32 dst = 0;
+ u32 src = 0;
+ int iif = 0;
+ int err;
+ struct sk_buff *skb;
+
+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (skb == NULL)
+ return -ENOBUFS;
+
+ /* Reserve room for dummy headers, this skb can pass
+ through good chunk of routing engine.
+ */
+ skb->mac.raw = skb->data;
+ skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
+
+ if (rta[RTA_SRC-1])
+ memcpy(&src, RTA_DATA(rta[RTA_SRC-1]), 4);
+ if (rta[RTA_DST-1])
+ memcpy(&dst, RTA_DATA(rta[RTA_DST-1]), 4);
+ if (rta[RTA_IIF-1])
+ memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
+
+ if (iif) {
+ struct device *dev;
+ dev = dev_get_by_index(iif);
+ if (!dev)
+ return -ENODEV;
+ skb->protocol = __constant_htons(ETH_P_IP);
+ skb->dev = dev;
+ start_bh_atomic();
+ err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
+ end_bh_atomic();
+ rt = (struct rtable*)skb->dst;
+ if (!err && rt->u.dst.error)
+ err = -rt->u.dst.error;
+ } else {
+ int oif = 0;
+ if (rta[RTA_OIF-1])
+ memcpy(&oif, RTA_DATA(rta[RTA_OIF-1]), sizeof(int));
+ err = ip_route_output(&rt, dst, src, rtm->rtm_tos, oif);
+ }
+ if (err) {
+ kfree_skb(skb);
+ return err;
+ }
+
+ skb->dst = &rt->u.dst;
+ if (rtm->rtm_flags & RTM_F_NOTIFY)
+ rt->rt_flags |= RTCF_NOTIFY;
+
+ NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
+
+ err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
+ if (err == 0)
+ return 0;
+ if (err < 0)
+ return -EMSGSIZE;
+
+ err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+
+int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct rtable *rt;
+ int h, s_h;
+ int idx, s_idx;
+
+ s_h = cb->args[0];
+ s_idx = idx = cb->args[1];
+ for (h=0; h < RT_HASH_DIVISOR; h++) {
+ if (h < s_h) continue;
+ if (h > s_h)
+ s_idx = 0;
+ start_bh_atomic();
+ for (rt = rt_hash_table[h], idx = 0; rt; rt = rt->u.rt_next, idx++) {
+ if (idx < s_idx)
+ continue;
+ skb->dst = dst_clone(&rt->u.dst);
+ if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
+ dst_release(xchg(&skb->dst, NULL));
+ end_bh_atomic();
+ goto done;
+ }
+ dst_release(xchg(&skb->dst, NULL));
+ }
+ end_bh_atomic();
+ }
+
+done:
+ cb->args[0] = h;
+ cb->args[1] = idx;
+ return skb->len;
+}
+
+#endif /* CONFIG_RTNETLINK */
+
+void ip_rt_multicast_event(struct in_device *in_dev)
+{
+ rt_cache_flush(0);
+}
+
+
+
+#ifdef CONFIG_SYSCTL
+
+static int flush_delay;
+
+static
+int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
+ void *buffer, size_t *lenp)
+{
+ if (write) {
+ proc_dointvec(ctl, write, filp, buffer, lenp);
+ rt_cache_flush(flush_delay);
+ return 0;
+ } else
+ return -EINVAL;
+}
+
+static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen,
+ void **context)
+{
+ int delay;
+ if (newlen != sizeof(int))
+ return -EINVAL;
+ if (get_user(delay,(int *)newval))
+ return -EFAULT;
+ rt_cache_flush(delay);
+ return 0;
+}
+
+ctl_table ipv4_route_table[] = {
+ {NET_IPV4_ROUTE_FLUSH, "flush",
+ &flush_delay, sizeof(int), 0644, NULL,
+ &ipv4_sysctl_rtcache_flush, &ipv4_sysctl_rtcache_flush_strategy },
+ {NET_IPV4_ROUTE_MIN_DELAY, "min_delay",
+ &ip_rt_min_delay, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies, &sysctl_jiffies},
+ {NET_IPV4_ROUTE_MAX_DELAY, "max_delay",
+ &ip_rt_max_delay, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies, &sysctl_jiffies},
+ {NET_IPV4_ROUTE_GC_THRESH, "gc_thresh",
+ &ipv4_dst_ops.gc_thresh, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ROUTE_MAX_SIZE, "max_size",
+ &ip_rt_max_size, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ROUTE_GC_MIN_INTERVAL, "gc_min_interval",
+ &ip_rt_gc_min_interval, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies, &sysctl_jiffies},
+ {NET_IPV4_ROUTE_GC_TIMEOUT, "gc_timeout",
+ &ip_rt_gc_timeout, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies, &sysctl_jiffies},
+ {NET_IPV4_ROUTE_GC_INTERVAL, "gc_interval",
+ &ip_rt_gc_interval, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies, &sysctl_jiffies},
+ {NET_IPV4_ROUTE_REDIRECT_LOAD, "redirect_load",
+ &ip_rt_redirect_load, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ROUTE_REDIRECT_NUMBER, "redirect_number",
+ &ip_rt_redirect_number, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ROUTE_REDIRECT_SILENCE, "redirect_silence",
+ &ip_rt_redirect_silence, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ROUTE_ERROR_COST, "error_cost",
+ &ip_rt_error_cost, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ROUTE_ERROR_BURST, "error_burst",
+ &ip_rt_error_burst, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ROUTE_GC_ELASTICITY, "gc_elasticity",
+ &ip_rt_gc_elasticity, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ROUTE_MTU_EXPIRES, "mtu_expires",
+ &ip_rt_mtu_expires, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies, &sysctl_jiffies},
+ {0}
+};
+#endif
+
+#ifdef CONFIG_NET_CLS_ROUTE
+struct ip_rt_acct ip_rt_acct[256];
+
+#ifdef CONFIG_PROC_FS
+static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+{
+ *start=buffer;
+
+ if (offset + length > sizeof(ip_rt_acct)) {
+ length = sizeof(ip_rt_acct) - offset;
+ *eof = 1;
+ }
+ if (length > 0) {
+ start_bh_atomic();
+ memcpy(buffer, ((u8*)&ip_rt_acct)+offset, length);
+ end_bh_atomic();
+ return length;
+ }
+ return 0;
+}
+#endif
+#endif
+
+
+__initfunc(void ip_rt_init(void))
+{
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_NET_CLS_ROUTE
+ struct proc_dir_entry *ent;
+#endif
+#endif
+ devinet_init();
+ ip_fib_init();
+ rt_periodic_timer.function = rt_check_expire;
+ /* All the timers, started at system startup tend
+ to synchronize. Perturb it a bit.
+ */
+ rt_periodic_timer.expires = jiffies + net_random()%ip_rt_gc_interval
+ + ip_rt_gc_interval;
+ add_timer(&rt_periodic_timer);
+
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&(struct proc_dir_entry) {
+ PROC_NET_RTCACHE, 8, "rt_cache",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ rt_cache_get_info
+ });
+#ifdef CONFIG_NET_CLS_ROUTE
+ ent = create_proc_entry("net/rt_acct", 0, 0);
+ ent->read_proc = ip_rt_acct_read;
+#endif
+#endif
+}
diff --git a/pfinet/linux-src/net/ipv4/syncookies.c b/pfinet/linux-src/net/ipv4/syncookies.c
new file mode 100644
index 00000000..fb4e8f80
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/syncookies.c
@@ -0,0 +1,201 @@
+/*
+ * Syncookies implementation for the Linux kernel
+ *
+ * Copyright (C) 1997 Andi Kleen
+ * Based on ideas by D.J.Bernstein and Eric Schenk.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * $Id: syncookies.c,v 1.7.2.1 1999/08/08 08:43:13 davem Exp $
+ *
+ * Missing: IPv6 support.
+ */
+
+#include <linux/config.h>
+#if defined(CONFIG_SYN_COOKIES)
+#include <linux/tcp.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <net/tcp.h>
+
+extern int sysctl_tcp_syncookies;
+
+static unsigned long tcp_lastsynq_overflow;
+
+/*
+ * This table has to be sorted and terminated with (__u16)-1.
+ * XXX generate a better table.
+ * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
+ */
+static __u16 const msstab[] = {
+ 64-1,
+ 256-1,
+ 512-1,
+ 536-1,
+ 1024-1,
+ 1440-1,
+ 1460-1,
+ 4312-1,
+ (__u16)-1
+};
+/* The number doesn't include the -1 terminator */
+#define NUM_MSS (sizeof(msstab)/sizeof(msstab[0]) - 1)
+
+/*
+ * Generate a syncookie. mssp points to the mss, which is returned
+ * rounded down to the value encoded in the cookie.
+ */
+__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
+ __u16 *mssp)
+{
+ int mssind;
+ const __u16 mss = *mssp;
+
+ tcp_lastsynq_overflow = jiffies;
+ /* XXX sort msstab[] by probability? Binary search? */
+ for (mssind = 0; mss > msstab[mssind+1]; mssind++)
+ ;
+ *mssp = msstab[mssind]+1;
+
+ net_statistics.SyncookiesSent++;
+
+ return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
+ skb->h.th->source, skb->h.th->dest,
+ ntohl(skb->h.th->seq),
+ jiffies / (HZ*60), mssind);
+}
+
+/*
+ * This (misnamed) value is the age of syncookie which is permitted.
+ * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
+ * sysctl_tcp_retries1. It's a rather complicated formula (exponential
+ * backoff) to compute at runtime so it's currently hardcoded here.
+ */
+#define COUNTER_TRIES 4
+/*
+ * Check if a ack sequence number is a valid syncookie.
+ * Return the decoded mss if it is, or 0 if not.
+ */
+static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
+{
+ __u32 seq;
+ __u32 mssind;
+
+ if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT)
+ return 0;
+
+ seq = ntohl(skb->h.th->seq)-1;
+ mssind = check_tcp_syn_cookie(cookie,
+ skb->nh.iph->saddr, skb->nh.iph->daddr,
+ skb->h.th->source, skb->h.th->dest,
+ seq, jiffies/(HZ*60), COUNTER_TRIES);
+
+ return mssind < NUM_MSS ? msstab[mssind]+1 : 0;
+}
+
+extern struct or_calltable or_ipv4;
+
+static inline struct sock *
+get_cookie_sock(struct sock *sk, struct sk_buff *skb, struct open_request *req,
+ struct dst_entry *dst)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ sk = tp->af_specific->syn_recv_sock(sk, skb, req, dst);
+ req->sk = sk;
+
+ /* Queue up for accept() */
+ tcp_synq_queue(tp, req);
+
+ return sk;
+}
+
+struct sock *
+cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
+{
+ __u32 cookie = ntohl(skb->h.th->ack_seq)-1;
+ struct open_request *req;
+ int mss;
+ struct rtable *rt;
+ __u8 rcv_wscale;
+
+ if (!sysctl_tcp_syncookies)
+ return sk;
+ if (!skb->h.th->ack)
+ return sk;
+
+ mss = cookie_check(skb, cookie);
+ if (mss == 0) {
+ net_statistics.SyncookiesFailed++;
+ return sk;
+ }
+
+ net_statistics.SyncookiesRecv++;
+
+ req = tcp_openreq_alloc();
+ if (req == NULL)
+ return NULL;
+
+ req->rcv_isn = htonl(skb->h.th->seq)-1;
+ req->snt_isn = cookie;
+ req->mss = mss;
+ req->rmt_port = skb->h.th->source;
+ req->af.v4_req.loc_addr = skb->nh.iph->daddr;
+ req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
+ req->class = &or_ipv4; /* for safety */
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ req->lcl_port = skb->h.th->dest;
+#endif
+
+ req->af.v4_req.opt = NULL;
+
+ /* We throwed the options of the initial SYN away, so we hope
+ * the ACK carries the same options again (see RFC1122 4.2.3.8)
+ */
+ if (opt && opt->optlen) {
+ int opt_size = sizeof(struct ip_options) + opt->optlen;
+
+ req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC);
+ if (req->af.v4_req.opt) {
+ if (ip_options_echo(req->af.v4_req.opt, skb)) {
+ kfree_s(req->af.v4_req.opt, opt_size);
+ req->af.v4_req.opt = NULL;
+ }
+ }
+ }
+
+ req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
+ req->wscale_ok = 0;
+ req->expires = 0UL;
+ req->retrans = 0;
+
+ /*
+ * We need to lookup the route here to get at the correct
+ * window size. We should better make sure that the window size
+ * hasn't changed since we received the original syn, but I see
+ * no easy way to do this.
+ */
+ if (ip_route_output(&rt,
+ opt &&
+ opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
+ req->af.v4_req.loc_addr,
+ sk->ip_tos | RTO_CONN,
+ 0)) {
+ tcp_openreq_free(req);
+ return NULL;
+ }
+
+ /* Try to redo what tcp_v4_send_synack did. */
+ req->window_clamp = rt->u.dst.window;
+ tcp_select_initial_window(sock_rspace(sk)/2,req->mss,
+ &req->rcv_wnd, &req->window_clamp,
+ 0, &rcv_wscale);
+ req->rcv_wscale = rcv_wscale;
+
+ return get_cookie_sock(sk, skb, req, &rt->u.dst);
+}
+
+#endif
diff --git a/pfinet/linux-src/net/ipv4/sysctl_net_ipv4.c b/pfinet/linux-src/net/ipv4/sysctl_net_ipv4.c
new file mode 100644
index 00000000..e578e4e7
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/sysctl_net_ipv4.c
@@ -0,0 +1,205 @@
+/*
+ * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
+ *
+ * $Id: sysctl_net_ipv4.c,v 1.38.2.1 1999/08/08 08:43:14 davem Exp $
+ *
+ * Begun April 1, 1996, Mike Shaver.
+ * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
+ */
+
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <linux/config.h>
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/tcp.h>
+
+/*
+ * TCP configuration parameters
+ */
+
+#define TCP_PMTU_DISC 0x00000001 /* perform PMTU discovery */
+#define TCP_CONG_AVOID 0x00000002 /* congestion avoidance algorithm */
+#define TCP_DELAY_ACKS 0x00000003 /* delayed ack stategy */
+
+#if 0
+static int boolean_min = 0;
+static int boolean_max = 1;
+#endif
+
+/* From icmp.c */
+extern int sysctl_icmp_echo_ignore_all;
+extern int sysctl_icmp_echo_ignore_broadcasts;
+extern int sysctl_icmp_ignore_bogus_error_responses;
+
+/* From ip_fragment.c */
+extern int sysctl_ipfrag_low_thresh;
+extern int sysctl_ipfrag_high_thresh;
+extern int sysctl_ipfrag_time;
+
+/* From ip_output.c */
+extern int sysctl_ip_dynaddr;
+
+/* From ip_masq.c */
+extern int sysctl_ip_masq_debug;
+
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_retrans_collapse;
+extern int sysctl_tcp_keepalive_time;
+extern int sysctl_tcp_keepalive_probes;
+extern int sysctl_tcp_max_ka_probes;
+extern int sysctl_tcp_retries1;
+extern int sysctl_tcp_retries2;
+extern int sysctl_tcp_fin_timeout;
+extern int sysctl_tcp_syncookies;
+extern int sysctl_tcp_syn_retries;
+extern int sysctl_tcp_stdurg;
+extern int sysctl_tcp_rfc1337;
+extern int sysctl_tcp_syn_taildrop;
+extern int sysctl_max_syn_backlog;
+
+/* From icmp.c */
+extern int sysctl_icmp_destunreach_time;
+extern int sysctl_icmp_timeexceed_time;
+extern int sysctl_icmp_paramprob_time;
+extern int sysctl_icmp_echoreply_time;
+
+/* From igmp.c */
+extern int sysctl_igmp_max_memberships;
+
+int tcp_retr1_max = 255;
+
+struct ipv4_config ipv4_config;
+
+extern ctl_table ipv4_route_table[];
+
+#ifdef CONFIG_SYSCTL
+
+static
+int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
+ void *buffer, size_t *lenp)
+{
+ int val = ipv4_devconf.forwarding;
+ int ret;
+
+ ret = proc_dointvec(ctl, write, filp, buffer, lenp);
+
+ if (write && ipv4_devconf.forwarding != val)
+ inet_forward_change();
+
+ return ret;
+}
+
+static int ipv4_sysctl_forward_strategy(ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen,
+ void **context)
+{
+ int new;
+ if (newlen != sizeof(int))
+ return -EINVAL;
+ if (get_user(new,(int *)newval))
+ return -EFAULT;
+ if (new != ipv4_devconf.forwarding)
+ inet_forward_change();
+ return 0; /* caller does change again and handles handles oldval */
+}
+
+ctl_table ipv4_table[] = {
+ {NET_IPV4_TCP_TIMESTAMPS, "tcp_timestamps",
+ &sysctl_tcp_timestamps, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_TCP_WINDOW_SCALING, "tcp_window_scaling",
+ &sysctl_tcp_window_scaling, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_TCP_SACK, "tcp_sack",
+ &sysctl_tcp_sack, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_TCP_RETRANS_COLLAPSE, "tcp_retrans_collapse",
+ &sysctl_tcp_retrans_collapse, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_FORWARD, "ip_forward",
+ &ipv4_devconf.forwarding, sizeof(int), 0644, NULL,
+ &ipv4_sysctl_forward,&ipv4_sysctl_forward_strategy},
+ {NET_IPV4_DEFAULT_TTL, "ip_default_ttl",
+ &ip_statistics.IpDefaultTTL, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_AUTOCONFIG, "ip_autoconfig",
+ &ipv4_config.autoconfig, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_NO_PMTU_DISC, "ip_no_pmtu_disc",
+ &ipv4_config.no_pmtu_disc, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_TCP_SYN_RETRIES, "tcp_syn_retries",
+ &sysctl_tcp_syn_retries, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_IPFRAG_HIGH_THRESH, "ipfrag_high_thresh",
+ &sysctl_ipfrag_high_thresh, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_IPFRAG_LOW_THRESH, "ipfrag_low_thresh",
+ &sysctl_ipfrag_low_thresh, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_DYNADDR, "ip_dynaddr",
+ &sysctl_ip_dynaddr, sizeof(int), 0644, NULL, &proc_dointvec},
+#ifdef CONFIG_IP_MASQUERADE
+ {NET_IPV4_IP_MASQ_DEBUG, "ip_masq_debug",
+ &sysctl_ip_masq_debug, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
+ {NET_IPV4_IPFRAG_TIME, "ipfrag_time",
+ &sysctl_ipfrag_time, sizeof(int), 0644, NULL, &proc_dointvec_jiffies,
+ &sysctl_jiffies},
+ {NET_IPV4_TCP_MAX_KA_PROBES, "tcp_max_ka_probes",
+ &sysctl_tcp_max_ka_probes, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_TCP_KEEPALIVE_TIME, "tcp_keepalive_time",
+ &sysctl_tcp_keepalive_time, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies, &sysctl_jiffies},
+ {NET_IPV4_TCP_KEEPALIVE_PROBES, "tcp_keepalive_probes",
+ &sysctl_tcp_keepalive_probes, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_TCP_RETRIES1, "tcp_retries1",
+ &sysctl_tcp_retries1, sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+ &sysctl_intvec, NULL, NULL, &tcp_retr1_max},
+ {NET_IPV4_TCP_RETRIES2, "tcp_retries2",
+ &sysctl_tcp_retries2, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_TCP_FIN_TIMEOUT, "tcp_fin_timeout",
+ &sysctl_tcp_fin_timeout, sizeof(int), 0644, NULL,
+ &proc_dointvec_jiffies, &sysctl_jiffies},
+#ifdef CONFIG_SYN_COOKIES
+ {NET_TCP_SYNCOOKIES, "tcp_syncookies",
+ &sysctl_tcp_syncookies, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
+ {NET_TCP_STDURG, "tcp_stdurg", &sysctl_tcp_stdurg,
+ sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_TCP_RFC1337, "tcp_rfc1337", &sysctl_tcp_rfc1337,
+ sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_TCP_MAX_SYN_BACKLOG, "tcp_max_syn_backlog", &sysctl_max_syn_backlog,
+ sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_LOCAL_PORT_RANGE, "ip_local_port_range",
+ &sysctl_local_port_range, sizeof(sysctl_local_port_range), 0644,
+ NULL, &proc_dointvec},
+ {NET_IPV4_ICMP_ECHO_IGNORE_ALL, "icmp_echo_ignore_all",
+ &sysctl_icmp_echo_ignore_all, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS, "icmp_echo_ignore_broadcasts",
+ &sysctl_icmp_echo_ignore_broadcasts, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES, "icmp_ignore_bogus_error_responses",
+ &sysctl_icmp_ignore_bogus_error_responses, sizeof(int), 0644, NULL,
+ &proc_dointvec},
+ {NET_IPV4_ICMP_DESTUNREACH_RATE, "icmp_destunreach_rate",
+ &sysctl_icmp_destunreach_time, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_ICMP_TIMEEXCEED_RATE, "icmp_timeexceed_rate",
+ &sysctl_icmp_timeexceed_time, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_ICMP_PARAMPROB_RATE, "icmp_paramprob_rate",
+ &sysctl_icmp_paramprob_time, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_ICMP_ECHOREPLY_RATE, "icmp_echoreply_rate",
+ &sysctl_icmp_echoreply_time, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_IPV4_ROUTE, "route", NULL, 0, 0555, ipv4_route_table},
+#ifdef CONFIG_IP_MULTICAST
+ {NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships",
+ &sysctl_igmp_max_memberships, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
+ {0}
+};
+
+#endif /* CONFIG_SYSCTL */
diff --git a/pfinet/linux-src/net/ipv4/tcp.c b/pfinet/linux-src/net/ipv4/tcp.c
new file mode 100644
index 00000000..65763215
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/tcp.c
@@ -0,0 +1,1826 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id: tcp.c,v 1.140.2.4 1999/08/09 03:13:12 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ * Linus Torvalds, <torvalds@cs.helsinki.fi>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Matthew Dillon, <dillon@apollo.west.oic.com>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ *
+ * Fixes:
+ * Alan Cox : Numerous verify_area() calls
+ * Alan Cox : Set the ACK bit on a reset
+ * Alan Cox : Stopped it crashing if it closed while
+ * sk->inuse=1 and was trying to connect
+ * (tcp_err()).
+ * Alan Cox : All icmp error handling was broken
+ * pointers passed where wrong and the
+ * socket was looked up backwards. Nobody
+ * tested any icmp error code obviously.
+ * Alan Cox : tcp_err() now handled properly. It
+ * wakes people on errors. poll
+ * behaves and the icmp error race
+ * has gone by moving it into sock.c
+ * Alan Cox : tcp_send_reset() fixed to work for
+ * everything not just packets for
+ * unknown sockets.
+ * Alan Cox : tcp option processing.
+ * Alan Cox : Reset tweaked (still not 100%) [Had
+ * syn rule wrong]
+ * Herp Rosmanith : More reset fixes
+ * Alan Cox : No longer acks invalid rst frames.
+ * Acking any kind of RST is right out.
+ * Alan Cox : Sets an ignore me flag on an rst
+ * receive otherwise odd bits of prattle
+ * escape still
+ * Alan Cox : Fixed another acking RST frame bug.
+ * Should stop LAN workplace lockups.
+ * Alan Cox : Some tidyups using the new skb list
+ * facilities
+ * Alan Cox : sk->keepopen now seems to work
+ * Alan Cox : Pulls options out correctly on accepts
+ * Alan Cox : Fixed assorted sk->rqueue->next errors
+ * Alan Cox : PSH doesn't end a TCP read. Switched a
+ * bit to skb ops.
+ * Alan Cox : Tidied tcp_data to avoid a potential
+ * nasty.
+ * Alan Cox : Added some better commenting, as the
+ * tcp is hard to follow
+ * Alan Cox : Removed incorrect check for 20 * psh
+ * Michael O'Reilly : ack < copied bug fix.
+ * Johannes Stille : Misc tcp fixes (not all in yet).
+ * Alan Cox : FIN with no memory -> CRASH
+ * Alan Cox : Added socket option proto entries.
+ * Also added awareness of them to accept.
+ * Alan Cox : Added TCP options (SOL_TCP)
+ * Alan Cox : Switched wakeup calls to callbacks,
+ * so the kernel can layer network
+ * sockets.
+ * Alan Cox : Use ip_tos/ip_ttl settings.
+ * Alan Cox : Handle FIN (more) properly (we hope).
+ * Alan Cox : RST frames sent on unsynchronised
+ * state ack error.
+ * Alan Cox : Put in missing check for SYN bit.
+ * Alan Cox : Added tcp_select_window() aka NET2E
+ * window non shrink trick.
+ * Alan Cox : Added a couple of small NET2E timer
+ * fixes
+ * Charles Hedrick : TCP fixes
+ * Toomas Tamm : TCP window fixes
+ * Alan Cox : Small URG fix to rlogin ^C ack fight
+ * Charles Hedrick : Rewrote most of it to actually work
+ * Linus : Rewrote tcp_read() and URG handling
+ * completely
+ * Gerhard Koerting: Fixed some missing timer handling
+ * Matthew Dillon : Reworked TCP machine states as per RFC
+ * Gerhard Koerting: PC/TCP workarounds
+ * Adam Caldwell : Assorted timer/timing errors
+ * Matthew Dillon : Fixed another RST bug
+ * Alan Cox : Move to kernel side addressing changes.
+ * Alan Cox : Beginning work on TCP fastpathing
+ * (not yet usable)
+ * Arnt Gulbrandsen: Turbocharged tcp_check() routine.
+ * Alan Cox : TCP fast path debugging
+ * Alan Cox : Window clamping
+ * Michael Riepe : Bug in tcp_check()
+ * Matt Dillon : More TCP improvements and RST bug fixes
+ * Matt Dillon : Yet more small nasties remove from the
+ * TCP code (Be very nice to this man if
+ * tcp finally works 100%) 8)
+ * Alan Cox : BSD accept semantics.
+ * Alan Cox : Reset on closedown bug.
+ * Peter De Schrijver : ENOTCONN check missing in tcp_sendto().
+ * Michael Pall : Handle poll() after URG properly in
+ * all cases.
+ * Michael Pall : Undo the last fix in tcp_read_urg()
+ * (multi URG PUSH broke rlogin).
+ * Michael Pall : Fix the multi URG PUSH problem in
+ * tcp_readable(), poll() after URG
+ * works now.
+ * Michael Pall : recv(...,MSG_OOB) never blocks in the
+ * BSD api.
+ * Alan Cox : Changed the semantics of sk->socket to
+ * fix a race and a signal problem with
+ * accept() and async I/O.
+ * Alan Cox : Relaxed the rules on tcp_sendto().
+ * Yury Shevchuk : Really fixed accept() blocking problem.
+ * Craig I. Hagan : Allow for BSD compatible TIME_WAIT for
+ * clients/servers which listen in on
+ * fixed ports.
+ * Alan Cox : Cleaned the above up and shrank it to
+ * a sensible code size.
+ * Alan Cox : Self connect lockup fix.
+ * Alan Cox : No connect to multicast.
+ * Ross Biro : Close unaccepted children on master
+ * socket close.
+ * Alan Cox : Reset tracing code.
+ * Alan Cox : Spurious resets on shutdown.
+ * Alan Cox : Giant 15 minute/60 second timer error
+ * Alan Cox : Small whoops in polling before an
+ * accept.
+ * Alan Cox : Kept the state trace facility since
+ * it's handy for debugging.
+ * Alan Cox : More reset handler fixes.
+ * Alan Cox : Started rewriting the code based on
+ * the RFC's for other useful protocol
+ * references see: Comer, KA9Q NOS, and
+ * for a reference on the difference
+ * between specifications and how BSD
+ * works see the 4.4lite source.
+ * A.N.Kuznetsov : Don't time wait on completion of tidy
+ * close.
+ * Linus Torvalds : Fin/Shutdown & copied_seq changes.
+ * Linus Torvalds : Fixed BSD port reuse to work first syn
+ * Alan Cox : Reimplemented timers as per the RFC
+ * and using multiple timers for sanity.
+ * Alan Cox : Small bug fixes, and a lot of new
+ * comments.
+ * Alan Cox : Fixed dual reader crash by locking
+ * the buffers (much like datagram.c)
+ * Alan Cox : Fixed stuck sockets in probe. A probe
+ * now gets fed up of retrying without
+ * (even a no space) answer.
+ * Alan Cox : Extracted closing code better
+ * Alan Cox : Fixed the closing state machine to
+ * resemble the RFC.
+ * Alan Cox : More 'per spec' fixes.
+ * Jorge Cwik : Even faster checksumming.
+ * Alan Cox : tcp_data() doesn't ack illegal PSH
+ * only frames. At least one pc tcp stack
+ * generates them.
+ * Alan Cox : Cache last socket.
+ * Alan Cox : Per route irtt.
+ * Matt Day : poll()->select() match BSD precisely on error
+ * Alan Cox : New buffers
+ * Marc Tamsky : Various sk->prot->retransmits and
+ * sk->retransmits misupdating fixed.
+ * Fixed tcp_write_timeout: stuck close,
+ * and TCP syn retries gets used now.
+ * Mark Yarvis : In tcp_read_wakeup(), don't send an
+ * ack if state is TCP_CLOSED.
+ * Alan Cox : Look up device on a retransmit - routes may
+ * change. Doesn't yet cope with MSS shrink right
+ * but its a start!
+ * Marc Tamsky : Closing in closing fixes.
+ * Mike Shaver : RFC1122 verifications.
+ * Alan Cox : rcv_saddr errors.
+ * Alan Cox : Block double connect().
+ * Alan Cox : Small hooks for enSKIP.
+ * Alexey Kuznetsov: Path MTU discovery.
+ * Alan Cox : Support soft errors.
+ * Alan Cox : Fix MTU discovery pathological case
+ * when the remote claims no mtu!
+ * Marc Tamsky : TCP_CLOSE fix.
+ * Colin (G3TNE) : Send a reset on syn ack replies in
+ * window but wrong (fixes NT lpd problems)
+ * Pedro Roque : Better TCP window handling, delayed ack.
+ * Joerg Reuter : No modification of locked buffers in
+ * tcp_do_retransmit()
+ * Eric Schenk : Changed receiver side silly window
+ * avoidance algorithm to BSD style
+ * algorithm. This doubles throughput
+ * against machines running Solaris,
+ * and seems to result in general
+ * improvement.
+ * Stefan Magdalinski : adjusted tcp_readable() to fix FIONREAD
+ * Willy Konynenberg : Transparent proxying support.
+ * Mike McLagan : Routing by source
+ * Keith Owens : Do proper merging with partial SKB's in
+ * tcp_do_sendmsg to avoid burstiness.
+ * Eric Schenk : Fix fast close down bug with
+ * shutdown() followed by close().
+ * Andi Kleen : Make poll agree with SIGIO
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or(at your option) any later version.
+ *
+ * Description of States:
+ *
+ * TCP_SYN_SENT sent a connection request, waiting for ack
+ *
+ * TCP_SYN_RECV received a connection request, sent ack,
+ * waiting for final ack in three-way handshake.
+ *
+ * TCP_ESTABLISHED connection established
+ *
+ * TCP_FIN_WAIT1 our side has shutdown, waiting to complete
+ * transmission of remaining buffered data
+ *
+ * TCP_FIN_WAIT2 all buffered data sent, waiting for remote
+ * to shutdown
+ *
+ * TCP_CLOSING both sides have shutdown but we still have
+ * data we have to finish sending
+ *
+ * TCP_TIME_WAIT timeout to catch resent junk before entering
+ * closed, can only be entered from FIN_WAIT2
+ * or CLOSING. Required because the other end
+ * may not have gotten our last ACK causing it
+ * to retransmit the data packet (which we ignore)
+ *
+ * TCP_CLOSE_WAIT remote side has shutdown and is waiting for
+ * us to finish writing our data and to shutdown
+ * (we have to close() to move on to LAST_ACK)
+ *
+ * TCP_LAST_ACK out side has shutdown after remote has
+ * shutdown. There may still be data in our
+ * buffer that we have to finish sending
+ *
+ * TCP_CLOSE socket is finished
+ */
+
+/*
+ * RFC1122 status:
+ * NOTE: I'm not going to be doing comments in the code for this one except
+ * for violations and the like. tcp.c is just too big... If I say something
+ * "does?" or "doesn't?", it means I'm not sure, and will have to hash it out
+ * with Alan. -- MS 950903
+ * [Note: Most of the TCP code has been rewriten/redesigned since this
+ * RFC1122 check. It is probably not correct anymore. It should be redone
+ * before 2.2. -AK]
+ *
+ * Use of PSH (4.2.2.2)
+ * MAY aggregate data sent without the PSH flag. (does)
+ * MAY queue data received without the PSH flag. (does)
+ * SHOULD collapse successive PSH flags when it packetizes data. (doesn't)
+ * MAY implement PSH on send calls. (doesn't, thus:)
+ * MUST NOT buffer data indefinitely (doesn't [1 second])
+ * MUST set PSH on last segment (does)
+ * MAY pass received PSH to application layer (doesn't)
+ * SHOULD send maximum-sized segment whenever possible. (almost always does)
+ *
+ * Window Size (4.2.2.3, 4.2.2.16)
+ * MUST treat window size as an unsigned number (does)
+ * SHOULD treat window size as a 32-bit number (does not)
+ * MUST NOT shrink window once it is offered (does not normally)
+ *
+ * Urgent Pointer (4.2.2.4)
+ * **MUST point urgent pointer to last byte of urgent data (not right
+ * after). (doesn't, to be like BSD. That's configurable, but defaults
+ * to off)
+ * MUST inform application layer asynchronously of incoming urgent
+ * data. (does)
+ * MUST provide application with means of determining the amount of
+ * urgent data pending. (does)
+ * **MUST support urgent data sequence of arbitrary length. (doesn't, but
+ * it's sort of tricky to fix, as urg_ptr is a 16-bit quantity)
+ * [Follows BSD 1 byte of urgent data]
+ *
+ * TCP Options (4.2.2.5)
+ * MUST be able to receive TCP options in any segment. (does)
+ * MUST ignore unsupported options (does)
+ *
+ * Maximum Segment Size Option (4.2.2.6)
+ * MUST implement both sending and receiving MSS. (does, but currently
+ * only uses the smaller of both of them)
+ * SHOULD send an MSS with every SYN where receive MSS != 536 (MAY send
+ * it always). (does, even when MSS == 536, which is legal)
+ * MUST assume MSS == 536 if no MSS received at connection setup (does)
+ * MUST calculate "effective send MSS" correctly:
+ * min(physical_MTU, remote_MSS+20) - sizeof(tcphdr) - sizeof(ipopts)
+ * (does - but allows operator override)
+ *
+ * TCP Checksum (4.2.2.7)
+ * MUST generate and check TCP checksum. (does)
+ *
+ * Initial Sequence Number Selection (4.2.2.8)
+ * MUST use the RFC 793 clock selection mechanism. (doesn't, but it's
+ * OK: RFC 793 specifies a 250KHz clock, while we use 1MHz, which is
+ * necessary for 10Mbps networks - and harder than BSD to spoof!
+ * With syncookies we don't)
+ *
+ * Simultaneous Open Attempts (4.2.2.10)
+ * MUST support simultaneous open attempts (does)
+ *
+ * Recovery from Old Duplicate SYN (4.2.2.11)
+ * MUST keep track of active vs. passive open (does)
+ *
+ * RST segment (4.2.2.12)
+ * SHOULD allow an RST segment to contain data (does, but doesn't do
+ * anything with it, which is standard)
+ *
+ * Closing a Connection (4.2.2.13)
+ * MUST inform application of whether connection was closed by RST or
+ * normal close. (does)
+ * MAY allow "half-duplex" close (treat connection as closed for the
+ * local app, even before handshake is done). (does)
+ * MUST linger in TIME_WAIT for 2 * MSL (does)
+ *
+ * Retransmission Timeout (4.2.2.15)
+ * MUST implement Jacobson's slow start and congestion avoidance
+ * stuff. (does)
+ *
+ * Probing Zero Windows (4.2.2.17)
+ * MUST support probing of zero windows. (does)
+ * MAY keep offered window closed indefinitely. (does)
+ * MUST allow remote window to stay closed indefinitely. (does)
+ *
+ * Passive Open Calls (4.2.2.18)
+ * MUST NOT let new passive open affect other connections. (doesn't)
+ * MUST support passive opens (LISTENs) concurrently. (does)
+ *
+ * Time to Live (4.2.2.19)
+ * MUST make TCP TTL configurable. (does - IP_TTL option)
+ *
+ * Event Processing (4.2.2.20)
+ * SHOULD queue out-of-order segments. (does)
+ * MUST aggregate ACK segments whenever possible. (does but badly)
+ *
+ * Retransmission Timeout Calculation (4.2.3.1)
+ * MUST implement Karn's algorithm and Jacobson's algorithm for RTO
+ * calculation. (does, or at least explains them in the comments 8*b)
+ * SHOULD initialize RTO to 0 and RTT to 3. (does)
+ *
+ * When to Send an ACK Segment (4.2.3.2)
+ * SHOULD implement delayed ACK. (does)
+ * MUST keep ACK delay < 0.5 sec. (does)
+ *
+ * When to Send a Window Update (4.2.3.3)
+ * MUST implement receiver-side SWS. (does)
+ *
+ * When to Send Data (4.2.3.4)
+ * MUST implement sender-side SWS. (does)
+ * SHOULD implement Nagle algorithm. (does)
+ *
+ * TCP Connection Failures (4.2.3.5)
+ * MUST handle excessive retransmissions "properly" (see the RFC). (does)
+ * SHOULD inform application layer of soft errors. (does)
+ *
+ * TCP Keep-Alives (4.2.3.6)
+ * MAY provide keep-alives. (does)
+ * MUST make keep-alives configurable on a per-connection basis. (does)
+ * MUST default to no keep-alives. (does)
+ * MUST make keep-alive interval configurable. (does)
+ * MUST make default keep-alive interval > 2 hours. (does)
+ * MUST NOT interpret failure to ACK keep-alive packet as dead
+ * connection. (doesn't)
+ * SHOULD send keep-alive with no data. (does)
+ *
+ * TCP Multihoming (4.2.3.7)
+ * MUST get source address from IP layer before sending first
+ * SYN. (does)
+ * MUST use same local address for all segments of a connection. (does)
+ *
+ * IP Options (4.2.3.8)
+ * MUST ignore unsupported IP options. (does)
+ * MAY support Time Stamp and Record Route. (does)
+ * MUST allow application to specify a source route. (does)
+ * MUST allow received Source Route option to set route for all future
+ * segments on this connection. (does not (security issues))
+ *
+ * ICMP messages (4.2.3.9)
+ * MUST act on ICMP errors. (does)
+ * MUST slow transmission upon receipt of a Source Quench. (doesn't anymore
+ * because that is deprecated now by the IETF, can be turned on)
+ * MUST NOT abort connection upon receipt of soft Destination
+ * Unreachables (0, 1, 5), Time Exceededs and Parameter
+ * Problems. (doesn't)
+ * SHOULD report soft Destination Unreachables etc. to the
+ * application. (does, except during SYN_RECV and may drop messages
+ * in some rare cases before accept() - ICMP is unreliable)
+ * SHOULD abort connection upon receipt of hard Destination Unreachable
+ * messages (2, 3, 4). (does, but see above)
+ *
+ * Remote Address Validation (4.2.3.10)
+ * MUST reject as an error OPEN for invalid remote IP address. (does)
+ * MUST ignore SYN with invalid source address. (does)
+ * MUST silently discard incoming SYN for broadcast/multicast
+ * address. (does)
+ *
+ * Asynchronous Reports (4.2.4.1)
+ * MUST provide mechanism for reporting soft errors to application
+ * layer. (does)
+ *
+ * Type of Service (4.2.4.2)
+ * MUST allow application layer to set Type of Service. (does IP_TOS)
+ *
+ * (Whew. -- MS 950903)
+ * (Updated by AK, but not complete yet.)
+ **/
+
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+
+#include <net/icmp.h>
+#include <net/tcp.h>
+
+#include <asm/uaccess.h>
+
+int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
+
+struct tcp_mib tcp_statistics;
+
+kmem_cache_t *tcp_openreq_cachep;
+kmem_cache_t *tcp_bucket_cachep;
+kmem_cache_t *tcp_timewait_cachep;
+
+/*
+ * Find someone to 'accept'. Must be called with
+ * the socket locked or with interrupts disabled
+ */
+
+static struct open_request *tcp_find_established(struct tcp_opt *tp,
+ struct open_request **prevp)
+{
+ struct open_request *req = tp->syn_wait_queue;
+ struct open_request *prev = (struct open_request *)&tp->syn_wait_queue;
+ while(req) {
+ if (req->sk &&
+ ((1 << req->sk->state) &
+ ~(TCPF_SYN_SENT|TCPF_SYN_RECV)))
+ break;
+ prev = req;
+ req = req->dl_next;
+ }
+ *prevp = prev;
+ return req;
+}
+
+/*
+ * Walk down the receive queue counting readable data.
+ *
+ * Must be called with the socket lock held.
+ */
+
+static int tcp_readable(struct sock *sk)
+{
+ unsigned long counted;
+ unsigned long amount;
+ struct sk_buff *skb;
+ int sum;
+
+ SOCK_DEBUG(sk, "tcp_readable: %p - ",sk);
+
+ skb = skb_peek(&sk->receive_queue);
+ if (skb == NULL) {
+ SOCK_DEBUG(sk, "empty\n");
+ return(0);
+ }
+
+ counted = sk->tp_pinfo.af_tcp.copied_seq; /* Where we are at the moment */
+ amount = 0;
+
+ /* Do until a push or until we are out of data. */
+ do {
+ /* Found a hole so stops here. */
+ if (before(counted, TCP_SKB_CB(skb)->seq)) /* should not happen */
+ break;
+
+ /* Length - header but start from where we are up to
+ * avoid overlaps.
+ */
+ sum = skb->len - (counted - TCP_SKB_CB(skb)->seq);
+ if (sum >= 0) {
+ /* Add it up, move on. */
+ amount += sum;
+ counted += sum;
+ if (skb->h.th->syn)
+ counted++;
+ }
+
+ /* Don't count urg data ... but do it in the right place!
+ * Consider: "old_data (ptr is here) URG PUSH data"
+ * The old code would stop at the first push because
+ * it counted the urg (amount==1) and then does amount--
+ * *after* the loop. This means tcp_readable() always
+ * returned zero if any URG PUSH was in the queue, even
+ * though there was normal data available. If we subtract
+ * the urg data right here, we even get it to work for more
+ * than one URG PUSH skb without normal data.
+ * This means that poll() finally works now with urg data
+ * in the queue. Note that rlogin was never affected
+ * because it doesn't use poll(); it uses two processes
+ * and a blocking read(). And the queue scan in tcp_read()
+ * was correct. Mike <pall@rz.uni-karlsruhe.de>
+ */
+
+ /* Don't count urg data. */
+ if (skb->h.th->urg)
+ amount--;
+#if 0
+ if (amount && skb->h.th->psh) break;
+#endif
+ skb = skb->next;
+ } while(skb != (struct sk_buff *)&sk->receive_queue);
+
+ SOCK_DEBUG(sk, "got %lu bytes.\n",amount);
+ return(amount);
+}
+
+/*
+ * LISTEN is a special case for poll..
+ */
+static unsigned int tcp_listen_poll(struct sock *sk, poll_table *wait)
+{
+ struct open_request *req, *dummy;
+
+ lock_sock(sk);
+ req = tcp_find_established(&sk->tp_pinfo.af_tcp, &dummy);
+ release_sock(sk);
+ if (req)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+/*
+ * Compute minimal free write space needed to queue new packets.
+ */
+#define tcp_min_write_space(__sk) \
+ (atomic_read(&(__sk)->wmem_alloc) / 2)
+
+/*
+ * Wait for a TCP event.
+ *
+ * Note that we don't need to lock the socket, as the upper poll layers
+ * take care of normal races (between the test and the event) and we don't
+ * go look at any of the socket buffers directly.
+ */
+unsigned int tcp_poll(struct file * file, struct socket *sock, poll_table *wait)
+{
+ unsigned int mask;
+ struct sock *sk = sock->sk;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ poll_wait(file, sk->sleep, wait);
+ if (sk->state == TCP_LISTEN)
+ return tcp_listen_poll(sk, wait);
+
+ mask = 0;
+ if (sk->err)
+ mask = POLLERR;
+
+ /*
+ * POLLHUP is certainly not done right. But poll() doesn't
+ * have a notion of HUP in just one direction, and for a
+ * socket the read side is more interesting.
+ *
+ * Some poll() documentation says that POLLHUP is incompatible
+ * with the POLLOUT/POLLWR flags, so somebody should check this
+ * all. But careful, it tends to be safer to return too many
+ * bits than too few, and you can easily break real applications
+ * if you don't tell them that something has hung up!
+ *
+ * Check-me.
+ */
+ if (sk->shutdown & RCV_SHUTDOWN)
+ mask |= POLLHUP;
+
+ /* Connected? */
+ if ((1 << sk->state) & ~(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
+ if ((tp->rcv_nxt != tp->copied_seq) &&
+ (tp->urg_seq != tp->copied_seq ||
+ tp->rcv_nxt != tp->copied_seq+1 ||
+ sk->urginline || !tp->urg_data))
+ mask |= POLLIN | POLLRDNORM;
+
+ if (!(sk->shutdown & SEND_SHUTDOWN)) {
+ if (sock_wspace(sk) >= tcp_min_write_space(sk)) {
+ mask |= POLLOUT | POLLWRNORM;
+ } else { /* send SIGIO later */
+ sk->socket->flags |= SO_NOSPACE;
+ }
+ }
+
+ if (tp->urg_data & URG_VALID)
+ mask |= POLLPRI;
+ }
+ return mask;
+}
+
+/*
+ * Socket write_space callback.
+ * This (or rather the sock_wake_async) should agree with poll.
+ */
+void tcp_write_space(struct sock *sk)
+{
+ if (sk->dead)
+ return;
+
+ wake_up_interruptible(sk->sleep);
+ if (sock_wspace(sk) >=
+ tcp_min_write_space(sk))
+ sock_wake_async(sk->socket, 2);
+}
+
+
+int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+ int answ;
+
+ switch(cmd) {
+ case TIOCINQ:
+#ifdef FIXME /* FIXME: */
+ case FIONREAD:
+#endif
+ if (sk->state == TCP_LISTEN)
+ return(-EINVAL);
+ lock_sock(sk);
+ answ = tcp_readable(sk);
+ release_sock(sk);
+ break;
+ case SIOCATMARK:
+ {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ answ = tp->urg_data && tp->urg_seq == tp->copied_seq;
+ break;
+ }
+ case TIOCOUTQ:
+ if (sk->state == TCP_LISTEN)
+ return(-EINVAL);
+ answ = sock_wspace(sk);
+ break;
+ default:
+ return(-ENOIOCTLCMD);
+ };
+
+ return put_user(answ, (int *)arg);
+}
+
+/*
+ * Wait for a socket to get into the connected state
+ *
+ * Note: must be called with the socket locked.
+ */
+static int wait_for_tcp_connect(struct sock * sk, int flags)
+{
+ struct task_struct *tsk = current;
+ struct wait_queue wait = { tsk, NULL };
+
+ while((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
+ if(sk->err)
+ return sock_error(sk);
+ if((1 << sk->state) &
+ ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) {
+ if(sk->keepopen && !(flags&MSG_NOSIGNAL))
+ send_sig(SIGPIPE, tsk, 0);
+ return -EPIPE;
+ }
+ if(flags & MSG_DONTWAIT)
+ return -EAGAIN;
+ if(signal_pending(tsk))
+ return -ERESTARTSYS;
+
+ tsk->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(sk->sleep, &wait);
+ release_sock(sk);
+
+ if (((1 << sk->state) & ~(TCPF_ESTABLISHED|TCPF_CLOSE_WAIT)) &&
+ sk->err == 0)
+ schedule();
+
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+ lock_sock(sk);
+ }
+ return 0;
+}
+
+static inline int tcp_memory_free(struct sock *sk)
+{
+ return atomic_read(&sk->wmem_alloc) < sk->sndbuf;
+}
+
+/*
+ * Wait for more memory for a socket
+ */
+static void wait_for_tcp_memory(struct sock * sk)
+{
+ release_sock(sk);
+ if (!tcp_memory_free(sk)) {
+ struct wait_queue wait = { current, NULL };
+
+ sk->socket->flags &= ~SO_NOSPACE;
+ add_wait_queue(sk->sleep, &wait);
+ for (;;) {
+ if (signal_pending(current))
+ break;
+ current->state = TASK_INTERRUPTIBLE;
+ if (tcp_memory_free(sk))
+ break;
+ if (sk->shutdown & SEND_SHUTDOWN)
+ break;
+ if (sk->err)
+ break;
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+ }
+ lock_sock(sk);
+}
+
+/*
+ * Wait for a buffer.
+ */
+static int wait_for_buffer(struct sock *sk)
+{
+ struct wait_queue wait = { current, NULL };
+
+ release_sock(sk);
+ add_wait_queue(sk->sleep, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+ lock_sock(sk);
+ return 0;
+}
+
+/* When all user supplied data has been queued set the PSH bit */
+#define PSH_NEEDED (seglen == 0 && iovlen == 0)
+
+/*
+ * This routine copies from a user buffer into a socket,
+ * and starts the transmit system.
+ *
+ * Note: must be called with the socket locked.
+ */
+
+int tcp_do_sendmsg(struct sock *sk, struct msghdr *msg)
+{
+ struct iovec *iov;
+ struct tcp_opt *tp;
+ struct sk_buff *skb;
+ int iovlen, flags;
+ int mss_now;
+ int err, copied;
+
+ lock_sock(sk);
+
+ err = 0;
+ tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Wait for a connection to finish. */
+ flags = msg->msg_flags;
+ if ((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
+ if((err = wait_for_tcp_connect(sk, flags)) != 0)
+ goto out;
+
+ /* This should be in poll */
+ sk->socket->flags &= ~SO_NOSPACE; /* clear SIGIO XXX */
+
+ mss_now = tcp_current_mss(sk);
+
+ /* Ok commence sending. */
+ iovlen = msg->msg_iovlen;
+ iov = msg->msg_iov;
+ copied = 0;
+
+ while(--iovlen >= 0) {
+ int seglen=iov->iov_len;
+ unsigned char * from=iov->iov_base;
+
+ iov++;
+
+ while(seglen > 0) {
+ int copy, tmp, queue_it, psh;
+
+ if (err)
+ goto do_fault2;
+
+ /* Stop on errors. */
+ if (sk->err)
+ goto do_sock_err;
+
+ /* Make sure that we are established. */
+ if (sk->shutdown & SEND_SHUTDOWN)
+ goto do_shutdown;
+
+ /* Now we need to check if we have a half
+ * built packet we can tack some data onto.
+ */
+ if (tp->send_head && !(flags & MSG_OOB)) {
+ skb = sk->write_queue.prev;
+ copy = skb->len;
+ /* If the remote does SWS avoidance we should
+ * queue the best we can if not we should in
+ * fact send multiple packets...
+ * A method for detecting this would be most
+ * welcome.
+ */
+ if (skb_tailroom(skb) > 0 &&
+ (mss_now - copy) > 0 &&
+ tp->snd_nxt < TCP_SKB_CB(skb)->end_seq) {
+ int last_byte_was_odd = (copy % 4);
+
+ /*
+ * Check for parallel writers sleeping in user access.
+ */
+ if (tp->partial_writers++ > 0) {
+ wait_for_buffer(sk);
+ tp->partial_writers--;
+ continue;
+ }
+
+ copy = mss_now - copy;
+ if(copy > skb_tailroom(skb))
+ copy = skb_tailroom(skb);
+ if(copy > seglen)
+ copy = seglen;
+
+ if(last_byte_was_odd) {
+ if(copy_from_user(skb_put(skb, copy),
+ from, copy))
+ err = -EFAULT;
+ skb->csum = csum_partial(skb->data,
+ skb->len, 0);
+ } else {
+ skb->csum =
+ csum_and_copy_from_user(
+ from, skb_put(skb, copy),
+ copy, skb->csum, &err);
+ }
+
+ /*
+ * FIXME: the *_user functions should
+ * return how much data was
+ * copied before the fault
+ * occurred and then a partial
+ * packet with this data should
+ * be sent. Unfortunately
+ * csum_and_copy_from_user doesn't
+ * return this information.
+ * ATM it might send partly zeroed
+ * data in this case.
+ */
+ tp->write_seq += copy;
+ TCP_SKB_CB(skb)->end_seq += copy;
+ from += copy;
+ copied += copy;
+ seglen -= copy;
+ if (PSH_NEEDED)
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+
+ if (--tp->partial_writers > 0)
+ wake_up_interruptible(sk->sleep);
+
+ continue;
+ }
+ }
+
+ /* We also need to worry about the window. If
+ * window < 1/2 the maximum window we've seen
+ * from this host, don't use it. This is
+ * sender side silly window prevention, as
+ * specified in RFC1122. (Note that this is
+ * different than earlier versions of SWS
+ * prevention, e.g. RFC813.). What we
+ * actually do is use the whole MSS. Since
+ * the results in the right edge of the packet
+ * being outside the window, it will be queued
+ * for later rather than sent.
+ */
+ psh = 0;
+ copy = tp->snd_wnd - (tp->snd_nxt - tp->snd_una);
+ if(copy > (tp->max_window >> 1)) {
+ copy = min(copy, mss_now);
+ psh = 1;
+ } else {
+ copy = mss_now;
+ }
+ if(copy > seglen)
+ copy = seglen;
+
+ /* Determine how large of a buffer to allocate. */
+ tmp = MAX_HEADER + sk->prot->max_header;
+ if (copy < min(mss_now, tp->max_window >> 1) &&
+ !(flags & MSG_OOB)) {
+ tmp += min(mss_now, tp->max_window);
+
+ /* What is happening here is that we want to
+ * tack on later members of the users iovec
+ * if possible into a single frame. When we
+ * leave this loop our caller checks to see if
+ * we can send queued frames onto the wire.
+ * See tcp_v[46]_sendmsg() for this.
+ */
+ queue_it = 1;
+ } else {
+ tmp += copy;
+ queue_it = 0;
+ }
+ skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
+
+ /* If we didn't get any memory, we need to sleep. */
+ if (skb == NULL) {
+ sk->socket->flags |= SO_NOSPACE;
+ if (flags&MSG_DONTWAIT) {
+ err = -EAGAIN;
+ goto do_interrupted;
+ }
+ if (signal_pending(current)) {
+ err = -ERESTARTSYS;
+ goto do_interrupted;
+ }
+ tcp_push_pending_frames(sk, tp);
+ wait_for_tcp_memory(sk);
+
+ /* If SACK's were formed or PMTU events happened,
+ * we must find out about it.
+ */
+ mss_now = tcp_current_mss(sk);
+ continue;
+ }
+
+ seglen -= copy;
+
+ /* Prepare control bits for TCP header creation engine. */
+ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK |
+ ((PSH_NEEDED || psh) ?
+ TCPCB_FLAG_PSH : 0));
+ TCP_SKB_CB(skb)->sacked = 0;
+ if (flags & MSG_OOB) {
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_URG;
+ TCP_SKB_CB(skb)->urg_ptr = copy;
+ } else
+ TCP_SKB_CB(skb)->urg_ptr = 0;
+
+ /* TCP data bytes are SKB_PUT() on top, later
+ * TCP+IP+DEV headers are SKB_PUSH()'d beneath.
+ * Reserve header space and checksum the data.
+ */
+ skb_reserve(skb, MAX_HEADER + sk->prot->max_header);
+ skb->csum = csum_and_copy_from_user(from,
+ skb_put(skb, copy), copy, 0, &err);
+
+ if (err)
+ goto do_fault;
+
+ from += copy;
+ copied += copy;
+
+ TCP_SKB_CB(skb)->seq = tp->write_seq;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + copy;
+
+ /* This advances tp->write_seq for us. */
+ tcp_send_skb(sk, skb, queue_it);
+ }
+ }
+ sk->err = 0;
+ err = copied;
+ goto out;
+
+do_sock_err:
+ if(copied)
+ err = copied;
+ else
+ err = sock_error(sk);
+ goto out;
+do_shutdown:
+ if(copied)
+ err = copied;
+ else {
+ if (!(flags&MSG_NOSIGNAL))
+ send_sig(SIGPIPE, current, 0);
+ err = -EPIPE;
+ }
+ goto out;
+do_interrupted:
+ if(copied)
+ err = copied;
+ goto out;
+do_fault:
+ kfree_skb(skb);
+do_fault2:
+ err = -EFAULT;
+out:
+ tcp_push_pending_frames(sk, tp);
+ release_sock(sk);
+ return err;
+}
+
+#undef PSH_NEEDED
+
+/*
+ * Send an ack if one is backlogged at this point. Ought to merge
+ * this with tcp_send_ack().
+ * This is called for delayed acks also.
+ */
+
+void tcp_read_wakeup(struct sock *sk)
+{
+ /* If we're closed, don't send an ack, or we'll get a RST
+ * from the closed destination.
+ */
+ if (sk->state != TCP_CLOSE)
+ tcp_send_ack(sk);
+}
+
+/*
+ * Handle reading urgent data. BSD has very simple semantics for
+ * this, no blocking and very strange errors 8)
+ */
+
+static int tcp_recv_urg(struct sock * sk, int nonblock,
+ struct msghdr *msg, int len, int flags,
+ int *addr_len)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* No URG data to read. */
+ if (sk->urginline || !tp->urg_data || tp->urg_data == URG_READ)
+ return -EINVAL; /* Yes this is right ! */
+
+ if (sk->err)
+ return sock_error(sk);
+
+ if (sk->done)
+ return -ENOTCONN;
+
+ if (sk->state == TCP_CLOSE || (sk->shutdown & RCV_SHUTDOWN)) {
+ sk->done = 1;
+ return 0;
+ }
+
+ lock_sock(sk);
+ if (tp->urg_data & URG_VALID) {
+ int err = 0;
+ char c = tp->urg_data;
+
+ if (!(flags & MSG_PEEK))
+ tp->urg_data = URG_READ;
+
+ if(msg->msg_name)
+ tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
+ msg->msg_name);
+
+ if(addr_len)
+ *addr_len = tp->af_specific->sockaddr_len;
+
+ /* Read urgent data. */
+ msg->msg_flags|=MSG_OOB;
+ release_sock(sk);
+
+ if(len>0)
+ {
+ err = memcpy_toiovec(msg->msg_iov, &c, 1);
+ /* N.B. already set above ... */
+ msg->msg_flags|=MSG_OOB;
+ }
+ else
+ msg->msg_flags|=MSG_TRUNC;
+
+ /* N.B. Is this right?? If len == 0 we didn't read any data */
+ return err ? -EFAULT : 1;
+ }
+ release_sock(sk);
+
+ /* Fixed the recv(..., MSG_OOB) behaviour. BSD docs and
+ * the available implementations agree in this case:
+ * this call should never block, independent of the
+ * blocking state of the socket.
+ * Mike <pall@rz.uni-karlsruhe.de>
+ */
+ return -EAGAIN;
+}
+
+/*
+ * Release a skb if it is no longer needed. This routine
+ * must be called with interrupts disabled or with the
+ * socket locked so that the sk_buff queue operation is ok.
+ */
+
+static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
+{
+ __skb_unlink(skb, &sk->receive_queue);
+ kfree_skb(skb);
+}
+
+/* Clean up the receive buffer for full frames taken by the user,
+ * then send an ACK if necessary. COPIED is the number of bytes
+ * tcp_recvmsg has given to the user so far, it speeds up the
+ * calculation of whether or not we must ACK for the sake of
+ * a window update.
+ */
+static void cleanup_rbuf(struct sock *sk, int copied)
+{
+ struct sk_buff *skb;
+
+ /* NOTE! The socket must be locked, so that we don't get
+ * a messed-up receive queue.
+ */
+ while ((skb=skb_peek(&sk->receive_queue)) != NULL) {
+ if (!skb->used || atomic_read(&skb->users) > 1)
+ break;
+ tcp_eat_skb(sk, skb);
+ }
+
+ /* We send an ACK if we can now advertise a non-zero window
+ * which has been raised "significantly".
+ */
+ if(copied > 0) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ __u32 rcv_window_now = tcp_receive_window(tp);
+ __u32 new_window = __tcp_select_window(sk);
+
+ /* We won't be raising the window any further than
+ * the window-clamp allows. Our window selection
+ * also keeps things a nice multiple of MSS. These
+ * checks are necessary to prevent spurious ACKs
+ * which don't advertize a larger window.
+ */
+ if((new_window && (new_window >= rcv_window_now * 2)) &&
+ ((rcv_window_now + tp->mss_cache) <= tp->window_clamp))
+ tcp_read_wakeup(sk);
+ }
+}
+
+
+/*
+ * This routine copies from a sock struct into the user buffer.
+ */
+
+int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
+ int len, int nonblock, int flags, int *addr_len)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct wait_queue wait = { current, NULL };
+ int copied = 0;
+ u32 peek_seq;
+ volatile u32 *seq; /* So gcc doesn't overoptimise */
+ unsigned long used;
+ int err = 0;
+ int target = 1; /* Read at least this many bytes */
+
+ if (sk->err)
+ return sock_error(sk);
+
+ if (sk->state == TCP_LISTEN)
+ return -ENOTCONN;
+
+ /* Urgent data needs to be handled specially. */
+ if (flags & MSG_OOB)
+ return tcp_recv_urg(sk, nonblock, msg, len, flags, addr_len);
+
+ /* Copying sequence to update. This is volatile to handle
+ * the multi-reader case neatly (memcpy_to/fromfs might be
+ * inline and thus not flush cached variables otherwise).
+ */
+ peek_seq = tp->copied_seq;
+ seq = &tp->copied_seq;
+ if (flags & MSG_PEEK)
+ seq = &peek_seq;
+
+ /* Handle the POSIX bogosity MSG_WAITALL. */
+ if (flags & MSG_WAITALL)
+ target=len;
+
+ add_wait_queue(sk->sleep, &wait);
+ lock_sock(sk);
+
+ /*
+ * BUG BUG BUG
+ * This violates 1003.1g compliance. We must wait for
+ * data to exist even if we read none!
+ */
+
+ while (len > 0) {
+ struct sk_buff * skb;
+ u32 offset;
+
+ /* Are we at urgent data? Stop if we have read anything. */
+ if (copied && tp->urg_data && tp->urg_seq == *seq)
+ break;
+
+ /* We need to check signals first, to get correct SIGURG
+ * handling. FIXME: Need to check this doesnt impact 1003.1g
+ * and move it down to the bottom of the loop
+ */
+ if (signal_pending(current)) {
+ if (copied)
+ break;
+ copied = -ERESTARTSYS;
+ if (nonblock)
+ copied = -EAGAIN;
+ break;
+ }
+
+ /* Next get a buffer. */
+ current->state = TASK_INTERRUPTIBLE;
+
+ skb = skb_peek(&sk->receive_queue);
+ do {
+ if (!skb)
+ break;
+
+ /* Now that we have two receive queues this
+ * shouldn't happen.
+ */
+ if (before(*seq, TCP_SKB_CB(skb)->seq)) {
+ printk(KERN_INFO "recvmsg bug: copied %X seq %X\n",
+ *seq, TCP_SKB_CB(skb)->seq);
+ break;
+ }
+ offset = *seq - TCP_SKB_CB(skb)->seq;
+ if (skb->h.th->syn)
+ offset--;
+ if (offset < skb->len)
+ goto found_ok_skb;
+ if (skb->h.th->fin)
+ goto found_fin_ok;
+ if (!(flags & MSG_PEEK))
+ skb->used = 1;
+ skb = skb->next;
+ } while (skb != (struct sk_buff *)&sk->receive_queue);
+
+ if (copied >= target)
+ break;
+
+ /*
+ These three lines and clause if (sk->state == TCP_CLOSE)
+ are unlikely to be correct, if target > 1.
+ I DO NOT FIX IT, because I have no idea, what
+ POSIX prescribes to make here. Probably, it really
+ wants to lose data 8), if not all target is received.
+ --ANK
+ */
+ if (sk->err && !(flags&MSG_PEEK)) {
+ copied = sock_error(sk);
+ break;
+ }
+
+ if (sk->shutdown & RCV_SHUTDOWN) {
+ sk->done = 1;
+ break;
+ }
+
+ if (sk->state == TCP_CLOSE) {
+ if (!sk->done) {
+ sk->done = 1;
+ break;
+ }
+ copied = -ENOTCONN;
+ break;
+ }
+
+ if (nonblock) {
+ copied = -EAGAIN;
+ break;
+ }
+
+ cleanup_rbuf(sk, copied);
+ release_sock(sk);
+ sk->socket->flags |= SO_WAITDATA;
+ schedule();
+ sk->socket->flags &= ~SO_WAITDATA;
+ lock_sock(sk);
+ continue;
+
+ found_ok_skb:
+ /* Lock the buffer. We can be fairly relaxed as
+ * an interrupt will never steal a buffer we are
+ * using unless I've missed something serious in
+ * tcp_data.
+ */
+ atomic_inc(&skb->users);
+
+ /* Ok so how much can we use? */
+ used = skb->len - offset;
+ if (len < used)
+ used = len;
+
+ /* Do we have urgent data here? */
+ if (tp->urg_data) {
+ u32 urg_offset = tp->urg_seq - *seq;
+ if (urg_offset < used) {
+ if (!urg_offset) {
+ if (!sk->urginline) {
+ ++*seq;
+ offset++;
+ used--;
+ }
+ } else
+ used = urg_offset;
+ }
+ }
+
+ /* Copy it - We _MUST_ update *seq first so that we
+ * don't ever double read when we have dual readers
+ */
+ *seq += used;
+
+ /* This memcpy_toiovec can sleep. If it sleeps and we
+ * do a second read it relies on the skb->users to avoid
+ * a crash when cleanup_rbuf() gets called.
+ */
+ err = memcpy_toiovec(msg->msg_iov, ((unsigned char *)skb->h.th) + skb->h.th->doff*4 + offset, used);
+ if (err) {
+ /* Exception. Bailout! */
+ atomic_dec(&skb->users);
+ copied = -EFAULT;
+ break;
+ }
+
+ copied += used;
+ len -= used;
+
+ /* We now will not sleep again until we are finished
+ * with skb. Sorry if you are doing the SMP port
+ * but you'll just have to fix it neatly ;)
+ */
+ atomic_dec(&skb->users);
+
+ if (after(tp->copied_seq,tp->urg_seq))
+ tp->urg_data = 0;
+ if (used + offset < skb->len)
+ continue;
+
+ /* Process the FIN. We may also need to handle PSH
+ * here and make it break out of MSG_WAITALL.
+ */
+ if (skb->h.th->fin)
+ goto found_fin_ok;
+ if (flags & MSG_PEEK)
+ continue;
+ skb->used = 1;
+ if (atomic_read(&skb->users) == 1)
+ tcp_eat_skb(sk, skb);
+ continue;
+
+ found_fin_ok:
+ ++*seq;
+ if (flags & MSG_PEEK)
+ break;
+
+ /* All is done. */
+ skb->used = 1;
+ sk->shutdown |= RCV_SHUTDOWN;
+ break;
+ }
+
+ if(copied >= 0 && msg->msg_name) {
+ tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
+ msg->msg_name);
+ if(addr_len)
+ *addr_len = tp->af_specific->sockaddr_len;
+ }
+
+ remove_wait_queue(sk->sleep, &wait);
+ current->state = TASK_RUNNING;
+
+ /* Clean up data we have read: This will do ACK frames. */
+ cleanup_rbuf(sk, copied);
+ release_sock(sk);
+ return copied;
+}
+
+/*
+ * Check whether to renew the timer.
+ */
+static inline void tcp_check_fin_timer(struct sock *sk)
+{
+ if (sk->state == TCP_FIN_WAIT2 && !sk->timer.prev)
+ tcp_reset_msl_timer(sk, TIME_CLOSE, sysctl_tcp_fin_timeout);
+}
+
+/*
+ * State processing on a close. This implements the state shift for
+ * sending our FIN frame. Note that we only send a FIN for some
+ * states. A shutdown() may have already sent the FIN, or we may be
+ * closed.
+ */
+
+static unsigned char new_state[16] = {
+ /* current state: new state: action: */
+ /* (Invalid) */ TCP_CLOSE,
+ /* TCP_ESTABLISHED */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,
+ /* TCP_SYN_SENT */ TCP_CLOSE,
+ /* TCP_SYN_RECV */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,
+ /* TCP_FIN_WAIT1 */ TCP_FIN_WAIT1,
+ /* TCP_FIN_WAIT2 */ TCP_FIN_WAIT2,
+ /* TCP_TIME_WAIT */ TCP_CLOSE,
+ /* TCP_CLOSE */ TCP_CLOSE,
+ /* TCP_CLOSE_WAIT */ TCP_LAST_ACK | TCP_ACTION_FIN,
+ /* TCP_LAST_ACK */ TCP_LAST_ACK,
+ /* TCP_LISTEN */ TCP_CLOSE,
+ /* TCP_CLOSING */ TCP_CLOSING,
+};
+
+static int tcp_close_state(struct sock *sk, int dead)
+{
+ int next = (int) new_state[sk->state];
+ int ns = (next & TCP_STATE_MASK);
+
+ tcp_set_state(sk, ns);
+
+ /* This is a (useful) BSD violating of the RFC. There is a
+ * problem with TCP as specified in that the other end could
+ * keep a socket open forever with no application left this end.
+ * We use a 3 minute timeout (about the same as BSD) then kill
+ * our end. If they send after that then tough - BUT: long enough
+ * that we won't make the old 4*rto = almost no time - whoops
+ * reset mistake.
+ */
+ if (dead)
+ tcp_check_fin_timer(sk);
+
+ return (next & TCP_ACTION_FIN);
+}
+
+/*
+ * Shutdown the sending side of a connection. Much like close except
+ * that we don't receive shut down or set sk->dead.
+ */
+
+void tcp_shutdown(struct sock *sk, int how)
+{
+ /* We need to grab some memory, and put together a FIN,
+ * and then put it into the queue to be sent.
+ * Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
+ */
+ if (!(how & SEND_SHUTDOWN))
+ return;
+
+ /* If we've already sent a FIN, or it's a closed state, skip this. */
+ if ((1 << sk->state) &
+ (TCPF_ESTABLISHED|TCPF_SYN_SENT|TCPF_SYN_RECV|TCPF_CLOSE_WAIT)) {
+ lock_sock(sk);
+
+ /* Clear out any half completed packets. FIN if needed. */
+ if (tcp_close_state(sk,0))
+ tcp_send_fin(sk);
+
+ release_sock(sk);
+ }
+}
+
+
+/*
+ * Return 1 if we still have things to send in our buffers.
+ */
+
+static inline int closing(struct sock * sk)
+{
+ return ((1 << sk->state) & (TCPF_FIN_WAIT1|TCPF_CLOSING|TCPF_LAST_ACK));
+}
+
+/*
+ * This routine closes sockets which have been at least partially
+ * opened, but not yet accepted. Currently it is only called by
+ * tcp_close, and timeout mirrors the value there.
+ */
+
+static void tcp_close_pending (struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct open_request *req = tp->syn_wait_queue;
+
+ while(req) {
+ struct open_request *iter;
+
+ if (req->sk)
+ tcp_close(req->sk, 0);
+
+ iter = req;
+ req = req->dl_next;
+
+ (*iter->class->destructor)(iter);
+ tcp_dec_slow_timer(TCP_SLT_SYNACK);
+ sk->ack_backlog--;
+ tcp_openreq_free(iter);
+ }
+
+ tcp_synq_init(tp);
+}
+
+void tcp_close(struct sock *sk, long timeout)
+{
+ struct sk_buff *skb;
+ int data_was_unread = 0;
+
+ /*
+ * Check whether the socket is locked ... supposedly
+ * it's impossible to tcp_close() a locked socket.
+ */
+ if (atomic_read(&sk->sock_readers))
+ printk("tcp_close: socket already locked!\n");
+
+ /* We need to grab some memory, and put together a FIN,
+ * and then put it into the queue to be sent.
+ */
+ lock_sock(sk);
+ if(sk->state == TCP_LISTEN) {
+ /* Special case. */
+ tcp_set_state(sk, TCP_CLOSE);
+ tcp_close_pending(sk);
+ release_sock(sk);
+ sk->dead = 1;
+ return;
+ }
+
+ /* It is questionable, what the role of this is now.
+ * In any event either it should be removed, or
+ * increment of SLT_KEEPALIVE be done, this is causing
+ * big problems. For now I comment it out. -DaveM
+ */
+ /* sk->keepopen = 1; */
+ sk->shutdown = SHUTDOWN_MASK;
+
+ if (!sk->dead)
+ sk->state_change(sk);
+
+ /* We need to flush the recv. buffs. We do this only on the
+ * descriptor close, not protocol-sourced closes, because the
+ * reader process may not have drained the data yet!
+ */
+ while((skb=__skb_dequeue(&sk->receive_queue))!=NULL) {
+ u32 len = TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq - skb->h.th->fin;
+ data_was_unread += len;
+ kfree_skb(skb);
+ }
+
+ /* As outlined in draft-ietf-tcpimpl-prob-03.txt, section
+ * 3.10, we send a RST here because data was lost. To
+ * witness the awful effects of the old behavior of always
+ * doing a FIN, run an older 2.1.x kernel or 2.0.x, start
+ * a bulk GET in an FTP client, suspend the process, wait
+ * for the client to advertise a zero window, then kill -9
+ * the FTP client, wheee... Note: timeout is always zero
+ * in such a case.
+ */
+ if(data_was_unread != 0) {
+ /* Unread data was tossed, zap the connection. */
+ tcp_set_state(sk, TCP_CLOSE);
+ tcp_send_active_reset(sk);
+ } else if (tcp_close_state(sk,1)) {
+ /* We FIN if the application ate all the data before
+ * zapping the connection.
+ */
+ tcp_send_fin(sk);
+ }
+
+ if (timeout) {
+ struct task_struct *tsk = current;
+ struct wait_queue wait = { tsk, NULL };
+
+ add_wait_queue(sk->sleep, &wait);
+ release_sock(sk);
+
+ while (1) {
+ tsk->state = TASK_INTERRUPTIBLE;
+ if (!closing(sk))
+ break;
+ timeout = schedule_timeout(timeout);
+ if (signal_pending(tsk) || !timeout)
+ break;
+ }
+
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+
+ lock_sock(sk);
+ }
+
+ /* Now that the socket is dead, if we are in the FIN_WAIT2 state
+ * we may need to set up a timer.
+ */
+ tcp_check_fin_timer(sk);
+
+ release_sock(sk);
+ sk->dead = 1;
+}
+
+/*
+ * Wait for an incoming connection, avoid race
+ * conditions. This must be called with the socket locked.
+ */
+static struct open_request * wait_for_connect(struct sock * sk,
+ struct open_request **pprev)
+{
+ struct wait_queue wait = { current, NULL };
+ struct open_request *req;
+
+ add_wait_queue(sk->sleep, &wait);
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ release_sock(sk);
+ schedule();
+ lock_sock(sk);
+ req = tcp_find_established(&(sk->tp_pinfo.af_tcp), pprev);
+ if (req)
+ break;
+ if (signal_pending(current))
+ break;
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+ return req;
+}
+
+/*
+ * This will accept the next outstanding connection.
+ *
+ * Be careful about race conditions here - this is subtle.
+ */
+
+struct sock *tcp_accept(struct sock *sk, int flags)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct open_request *req, *prev;
+ struct sock *newsk = NULL;
+ int error;
+
+ lock_sock(sk);
+
+ /* We need to make sure that this socket is listening,
+ * and that it has something pending.
+ */
+ error = EINVAL;
+ if (sk->state != TCP_LISTEN)
+ goto out;
+
+ /* Find already established connection */
+ req = tcp_find_established(tp, &prev);
+ if (!req) {
+ /* If this is a non blocking socket don't sleep */
+ error = EAGAIN;
+ if (flags & O_NONBLOCK)
+ goto out;
+
+ error = ERESTARTSYS;
+ req = wait_for_connect(sk, &prev);
+ if (!req)
+ goto out;
+ }
+
+ tcp_synq_unlink(tp, req, prev);
+ newsk = req->sk;
+ req->class->destructor(req);
+ tcp_openreq_free(req);
+ sk->ack_backlog--;
+ if(sk->keepopen)
+ tcp_inc_slow_timer(TCP_SLT_KEEPALIVE);
+
+ release_sock(sk);
+ return newsk;
+
+out:
+ /* sk should be in LISTEN state, thus accept can use sk->err for
+ * internal purposes without stomping one anyone's feed.
+ */
+ sk->err = error;
+ release_sock(sk);
+ return newsk;
+}
+
+/*
+ * Socket option code for TCP.
+ */
+
+int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval,
+ int optlen)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int val;
+
+ if (level != SOL_TCP)
+ return tp->af_specific->setsockopt(sk, level, optname,
+ optval, optlen);
+
+ if(optlen<sizeof(int))
+ return -EINVAL;
+
+ if (get_user(val, (int *)optval))
+ return -EFAULT;
+
+ switch(optname) {
+ case TCP_MAXSEG:
+ /* values greater than interface MTU won't take effect. however at
+ * the point when this call is done we typically don't yet know
+ * which interface is going to be used
+ */
+ if(val < 1 || val > MAX_WINDOW)
+ return -EINVAL;
+ tp->user_mss = val;
+ return 0;
+
+ case TCP_NODELAY:
+ /* You cannot try to use this and TCP_CORK in
+ * tandem, so let the user know.
+ */
+ if (sk->nonagle == 2)
+ return -EINVAL;
+ sk->nonagle = (val == 0) ? 0 : 1;
+ return 0;
+
+ case TCP_CORK:
+ /* When set indicates to always queue non-full frames.
+ * Later the user clears this option and we transmit
+ * any pending partial frames in the queue. This is
+ * meant to be used alongside sendfile() to get properly
+ * filled frames when the user (for example) must write
+ * out headers with a write() call first and then use
+ * sendfile to send out the data parts.
+ *
+ * You cannot try to use TCP_NODELAY and this mechanism
+ * at the same time, so let the user know.
+ */
+ if (sk->nonagle == 1)
+ return -EINVAL;
+ if (val != 0) {
+ sk->nonagle = 2;
+ } else {
+ sk->nonagle = 0;
+
+ lock_sock(sk);
+ tcp_push_pending_frames(sk, tp);
+ release_sock(sk);
+ }
+ return 0;
+
+ default:
+ return -ENOPROTOOPT;
+ };
+}
+
+int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval,
+ int *optlen)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int val, len;
+
+ if(level != SOL_TCP)
+ return tp->af_specific->getsockopt(sk, level, optname,
+ optval, optlen);
+
+ if(get_user(len,optlen))
+ return -EFAULT;
+
+ len = min(len, sizeof(int));
+
+ switch(optname) {
+ case TCP_MAXSEG:
+ val = tp->user_mss;
+ break;
+ case TCP_NODELAY:
+ val = (sk->nonagle == 1);
+ break;
+ case TCP_CORK:
+ val = (sk->nonagle == 2);
+ break;
+ default:
+ return -ENOPROTOOPT;
+ };
+
+ if(put_user(len, optlen))
+ return -EFAULT;
+ if(copy_to_user(optval, &val,len))
+ return -EFAULT;
+ return 0;
+}
+
+void tcp_set_keepalive(struct sock *sk, int val)
+{
+ if (!sk->keepopen && val)
+ tcp_inc_slow_timer(TCP_SLT_KEEPALIVE);
+ else if (sk->keepopen && !val)
+ tcp_dec_slow_timer(TCP_SLT_KEEPALIVE);
+}
+
+extern void __skb_cb_too_small_for_tcp(int, int);
+
+void __init tcp_init(void)
+{
+ struct sk_buff *skb = NULL;
+
+ if(sizeof(struct tcp_skb_cb) > sizeof(skb->cb))
+ __skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
+ sizeof(skb->cb));
+
+ tcp_openreq_cachep = kmem_cache_create("tcp_open_request",
+ sizeof(struct open_request),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if(!tcp_openreq_cachep)
+ panic("tcp_init: Cannot alloc open_request cache.");
+
+ tcp_bucket_cachep = kmem_cache_create("tcp_bind_bucket",
+ sizeof(struct tcp_bind_bucket),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if(!tcp_bucket_cachep)
+ panic("tcp_init: Cannot alloc tcp_bind_bucket cache.");
+
+ tcp_timewait_cachep = kmem_cache_create("tcp_tw_bucket",
+ sizeof(struct tcp_tw_bucket),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if(!tcp_timewait_cachep)
+ panic("tcp_init: Cannot alloc tcp_tw_bucket cache.");
+}
diff --git a/pfinet/linux-src/net/ipv4/tcp_input.c b/pfinet/linux-src/net/ipv4/tcp_input.c
new file mode 100644
index 00000000..a753b128
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/tcp_input.c
@@ -0,0 +1,2432 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id: tcp_input.c,v 1.164.2.7 1999/08/13 16:14:27 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ * Linus Torvalds, <torvalds@cs.helsinki.fi>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Matthew Dillon, <dillon@apollo.west.oic.com>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+/*
+ * Changes:
+ * Pedro Roque : Fast Retransmit/Recovery.
+ * Two receive queues.
+ * Retransmit queue handled by TCP.
+ * Better retransmit timer handling.
+ * New congestion avoidance.
+ * Header prediction.
+ * Variable renaming.
+ *
+ * Eric : Fast Retransmit.
+ * Randy Scott : MSS option defines.
+ * Eric Schenk : Fixes to slow start algorithm.
+ * Eric Schenk : Yet another double ACK bug.
+ * Eric Schenk : Delayed ACK bug fixes.
+ * Eric Schenk : Floyd style fast retrans war avoidance.
+ * David S. Miller : Don't allow zero congestion window.
+ * Eric Schenk : Fix retransmitter so that it sends
+ * next packet on ack of previous packet.
+ * Andi Kleen : Moved open_request checking here
+ * and process RSTs for open_requests.
+ * Andi Kleen : Better prune_queue, and other fixes.
+ * Andrey Savochkin: Fix RTT measurements in the presnce of
+ * timestamps.
+ * Andrey Savochkin: Check sequence numbers correctly when
+ * removing SACKs due to in sequence incoming
+ * data segments.
+ * Andi Kleen: Make sure we never ack data there is not
+ * enough room for. Also make this condition
+ * a fatal error if it might still happen.
+ * Andi Kleen: Add tcp_measure_rcv_mss to make
+ * connections with MSS<min(MTU,ann. MSS)
+ * work without delayed acks.
+ * Andi Kleen: Process packets with PSH set in the
+ * fast path.
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <net/tcp.h>
+#include <linux/ipsec.h>
+
+#ifdef CONFIG_SYSCTL
+#define SYNC_INIT 0 /* let the user enable it */
+#else
+#define SYNC_INIT 1
+#endif
+
+extern int sysctl_tcp_fin_timeout;
+
+/* These are on by default so the code paths get tested.
+ * For the final 2.2 this may be undone at our discretion. -DaveM
+ */
+int sysctl_tcp_timestamps = 1;
+int sysctl_tcp_window_scaling = 1;
+int sysctl_tcp_sack = 1;
+
+int sysctl_tcp_syncookies = SYNC_INIT;
+int sysctl_tcp_stdurg;
+int sysctl_tcp_rfc1337;
+
+static int prune_queue(struct sock *sk);
+
+/* There is something which you must keep in mind when you analyze the
+ * behavior of the tp->ato delayed ack timeout interval. When a
+ * connection starts up, we want to ack as quickly as possible. The
+ * problem is that "good" TCP's do slow start at the beginning of data
+ * transmission. The means that until we send the first few ACK's the
+ * sender will sit on his end and only queue most of his data, because
+ * he can only send snd_cwnd unacked packets at any given time. For
+ * each ACK we send, he increments snd_cwnd and transmits more of his
+ * queue. -DaveM
+ */
+static void tcp_delack_estimator(struct tcp_opt *tp)
+{
+ if(tp->ato == 0) {
+ tp->lrcvtime = tcp_time_stamp;
+
+ /* Help sender leave slow start quickly,
+ * and also makes sure we do not take this
+ * branch ever again for this connection.
+ */
+ tp->ato = 1;
+ tcp_enter_quickack_mode(tp);
+ } else {
+ int m = tcp_time_stamp - tp->lrcvtime;
+
+ tp->lrcvtime = tcp_time_stamp;
+ if(m <= 0)
+ m = 1;
+ if(m > tp->rto)
+ tp->ato = tp->rto;
+ else {
+ /* This funny shift makes sure we
+ * clear the "quick ack mode" bit.
+ */
+ tp->ato = ((tp->ato << 1) >> 2) + m;
+ }
+ }
+}
+
+/*
+ * Remember to send an ACK later.
+ */
+static __inline__ void tcp_remember_ack(struct tcp_opt *tp, struct tcphdr *th,
+ struct sk_buff *skb)
+{
+ tp->delayed_acks++;
+
+ /* Tiny-grams with PSH set artifically deflate our
+ * ato measurement, but with a lower bound.
+ */
+ if(th->psh && (skb->len < (tp->mss_cache >> 1))) {
+ /* Preserve the quickack state. */
+ if((tp->ato & 0x7fffffff) > HZ/50)
+ tp->ato = ((tp->ato & 0x80000000) |
+ (HZ/50));
+ }
+}
+
+/* Called to compute a smoothed rtt estimate. The data fed to this
+ * routine either comes from timestamps, or from segments that were
+ * known _not_ to have been retransmitted [see Karn/Partridge
+ * Proceedings SIGCOMM 87]. The algorithm is from the SIGCOMM 88
+ * piece by Van Jacobson.
+ * NOTE: the next three routines used to be one big routine.
+ * To save cycles in the RFC 1323 implementation it was better to break
+ * it up into three procedures. -- erics
+ */
+
+static __inline__ void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt)
+{
+ long m = mrtt; /* RTT */
+
+ /* The following amusing code comes from Jacobson's
+ * article in SIGCOMM '88. Note that rtt and mdev
+ * are scaled versions of rtt and mean deviation.
+ * This is designed to be as fast as possible
+ * m stands for "measurement".
+ *
+ * On a 1990 paper the rto value is changed to:
+ * RTO = rtt + 4 * mdev
+ */
+ if(m == 0)
+ m = 1;
+ if (tp->srtt != 0) {
+ m -= (tp->srtt >> 3); /* m is now error in rtt est */
+ tp->srtt += m; /* rtt = 7/8 rtt + 1/8 new */
+ if (m < 0)
+ m = -m; /* m is now abs(error) */
+ m -= (tp->mdev >> 2); /* similar update on mdev */
+ tp->mdev += m; /* mdev = 3/4 mdev + 1/4 new */
+ } else {
+ /* no previous measure. */
+ tp->srtt = m<<3; /* take the measured time to be rtt */
+ tp->mdev = m<<2; /* make sure rto = 3*rtt */
+ }
+}
+
+/* Calculate rto without backoff. This is the second half of Van Jacobson's
+ * routine referred to above.
+ */
+
+static __inline__ void tcp_set_rto(struct tcp_opt *tp)
+{
+ tp->rto = (tp->srtt >> 3) + tp->mdev;
+ tp->rto += (tp->rto >> 2) + (tp->rto >> (tp->snd_cwnd-1));
+}
+
+
+/* Keep the rto between HZ/5 and 120*HZ. 120*HZ is the upper bound
+ * on packet lifetime in the internet. We need the HZ/5 lower
+ * bound to behave correctly against BSD stacks with a fixed
+ * delayed ack.
+ * FIXME: It's not entirely clear this lower bound is the best
+ * way to avoid the problem. Is it possible to drop the lower
+ * bound and still avoid trouble with BSD stacks? Perhaps
+ * some modification to the RTO calculation that takes delayed
+ * ack bias into account? This needs serious thought. -- erics
+ */
+static __inline__ void tcp_bound_rto(struct tcp_opt *tp)
+{
+ if (tp->rto > 120*HZ)
+ tp->rto = 120*HZ;
+ if (tp->rto < HZ/5)
+ tp->rto = HZ/5;
+}
+
+/* WARNING: this must not be called if tp->saw_timestamp was false. */
+extern __inline__ void tcp_replace_ts_recent(struct sock *sk, struct tcp_opt *tp,
+ __u32 start_seq, __u32 end_seq)
+{
+ /* It is start_seq <= last_ack_seq combined
+ with in window check. If start_seq<=last_ack_seq<=rcv_nxt,
+ then segment is in window if end_seq>=rcv_nxt.
+ */
+ if (!after(start_seq, tp->last_ack_sent) &&
+ !before(end_seq, tp->rcv_nxt)) {
+ /* PAWS bug workaround wrt. ACK frames, the PAWS discard
+ * extra check below makes sure this can only happen
+ * for pure ACK frames. -DaveM
+ *
+ * Plus: expired timestamps.
+ *
+ * Plus: resets failing PAWS.
+ */
+ if((s32)(tp->rcv_tsval - tp->ts_recent) >= 0) {
+ tp->ts_recent = tp->rcv_tsval;
+ tp->ts_recent_stamp = tcp_time_stamp;
+ }
+ }
+}
+
+#define PAWS_24DAYS (HZ * 60 * 60 * 24 * 24)
+
+extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct tcphdr *th, unsigned len)
+{
+ return ((s32)(tp->rcv_tsval - tp->ts_recent) < 0 &&
+ (s32)(tcp_time_stamp - tp->ts_recent_stamp) < PAWS_24DAYS &&
+ /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM */
+ len != (th->doff * 4));
+}
+
+
+static int __tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+ u32 end_window = tp->rcv_wup + tp->rcv_wnd;
+
+ if (tp->rcv_wnd &&
+ after(end_seq, tp->rcv_nxt) &&
+ before(seq, end_window))
+ return 1;
+ if (seq != end_window)
+ return 0;
+ return (seq == end_seq);
+}
+
+/* This functions checks to see if the tcp header is actually acceptable. */
+extern __inline__ int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+ if (seq == tp->rcv_nxt)
+ return (tp->rcv_wnd || (end_seq == seq));
+
+ return __tcp_sequence(tp, seq, end_seq);
+}
+
+/* When we get a reset we do this. */
+static void tcp_reset(struct sock *sk)
+{
+ sk->zapped = 1;
+
+ /* We want the right error as BSD sees it (and indeed as we do). */
+ switch (sk->state) {
+ case TCP_SYN_SENT:
+ sk->err = ECONNREFUSED;
+ break;
+ case TCP_CLOSE_WAIT:
+ sk->err = EPIPE;
+ break;
+ default:
+ sk->err = ECONNRESET;
+ };
+ tcp_set_state(sk, TCP_CLOSE);
+ sk->shutdown = SHUTDOWN_MASK;
+ if (!sk->dead)
+ sk->state_change(sk);
+}
+
+/* This tags the retransmission queue when SACKs arrive. */
+static void tcp_sacktag_write_queue(struct sock *sk, struct tcp_sack_block *sp, int nsacks)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int i = nsacks;
+
+ while(i--) {
+ struct sk_buff *skb = skb_peek(&sk->write_queue);
+ __u32 start_seq = ntohl(sp->start_seq);
+ __u32 end_seq = ntohl(sp->end_seq);
+ int fack_count = 0;
+
+ while((skb != NULL) &&
+ (skb != tp->send_head) &&
+ (skb != (struct sk_buff *)&sk->write_queue)) {
+ /* The retransmission queue is always in order, so
+ * we can short-circuit the walk early.
+ */
+ if(after(TCP_SKB_CB(skb)->seq, end_seq))
+ break;
+
+ /* We play conservative, we don't allow SACKS to partially
+ * tag a sequence space.
+ */
+ fack_count++;
+ if(!after(start_seq, TCP_SKB_CB(skb)->seq) &&
+ !before(end_seq, TCP_SKB_CB(skb)->end_seq)) {
+ /* If this was a retransmitted frame, account for it. */
+ if((TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) &&
+ tp->retrans_out)
+ tp->retrans_out--;
+ TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED;
+
+ /* RULE: All new SACKs will either decrease retrans_out
+ * or advance fackets_out.
+ */
+ if(fack_count > tp->fackets_out)
+ tp->fackets_out = fack_count;
+ }
+ skb = skb->next;
+ }
+ sp++; /* Move on to the next SACK block. */
+ }
+}
+
+/* Look for tcp options. Normally only called on SYN and SYNACK packets.
+ * But, this can also be called on packets in the established flow when
+ * the fast version below fails.
+ */
+void tcp_parse_options(struct sock *sk, struct tcphdr *th, struct tcp_opt *tp, int no_fancy)
+{
+ unsigned char *ptr;
+ int length=(th->doff*4)-sizeof(struct tcphdr);
+ int saw_mss = 0;
+
+ ptr = (unsigned char *)(th + 1);
+ tp->saw_tstamp = 0;
+
+ while(length>0) {
+ int opcode=*ptr++;
+ int opsize;
+
+ switch (opcode) {
+ case TCPOPT_EOL:
+ return;
+ case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */
+ length--;
+ continue;
+ default:
+ opsize=*ptr++;
+ if (opsize < 2) /* "silly options" */
+ return;
+ if (opsize > length)
+ break; /* don't parse partial options */
+ switch(opcode) {
+ case TCPOPT_MSS:
+ if(opsize==TCPOLEN_MSS && th->syn) {
+ u16 in_mss = ntohs(*(__u16 *)ptr);
+ if (in_mss == 0)
+ in_mss = 536;
+ if (tp->mss_clamp > in_mss)
+ tp->mss_clamp = in_mss;
+ saw_mss = 1;
+ }
+ break;
+ case TCPOPT_WINDOW:
+ if(opsize==TCPOLEN_WINDOW && th->syn)
+ if (!no_fancy && sysctl_tcp_window_scaling) {
+ tp->wscale_ok = 1;
+ tp->snd_wscale = *(__u8 *)ptr;
+ if(tp->snd_wscale > 14) {
+ if(net_ratelimit())
+ printk("tcp_parse_options: Illegal window "
+ "scaling value %d >14 received.",
+ tp->snd_wscale);
+ tp->snd_wscale = 14;
+ }
+ }
+ break;
+ case TCPOPT_TIMESTAMP:
+ if(opsize==TCPOLEN_TIMESTAMP) {
+ if (sysctl_tcp_timestamps && !no_fancy) {
+ tp->tstamp_ok = 1;
+ tp->saw_tstamp = 1;
+ tp->rcv_tsval = ntohl(*(__u32 *)ptr);
+ tp->rcv_tsecr = ntohl(*(__u32 *)(ptr+4));
+ }
+ }
+ break;
+ case TCPOPT_SACK_PERM:
+ if(opsize==TCPOLEN_SACK_PERM && th->syn) {
+ if (sysctl_tcp_sack && !no_fancy) {
+ tp->sack_ok = 1;
+ tp->num_sacks = 0;
+ }
+ }
+ break;
+
+ case TCPOPT_SACK:
+ if((opsize >= (TCPOLEN_SACK_BASE + TCPOLEN_SACK_PERBLOCK)) &&
+ sysctl_tcp_sack && (sk != NULL) && !th->syn) {
+ int sack_bytes = opsize - TCPOLEN_SACK_BASE;
+
+ if(!(sack_bytes % TCPOLEN_SACK_PERBLOCK)) {
+ int num_sacks = sack_bytes >> 3;
+ struct tcp_sack_block *sackp;
+
+ sackp = (struct tcp_sack_block *)ptr;
+ tcp_sacktag_write_queue(sk, sackp, num_sacks);
+ }
+ }
+ };
+ ptr+=opsize-2;
+ length-=opsize;
+ };
+ }
+ if(th->syn && saw_mss == 0)
+ tp->mss_clamp = 536;
+}
+
+/* Fast parse options. This hopes to only see timestamps.
+ * If it is wrong it falls back on tcp_parse_options().
+ */
+static __inline__ int tcp_fast_parse_options(struct sock *sk, struct tcphdr *th, struct tcp_opt *tp)
+{
+ /* If we didn't send out any options ignore them all. */
+ if (tp->tcp_header_len == sizeof(struct tcphdr))
+ return 0;
+ if (th->doff == sizeof(struct tcphdr)>>2) {
+ tp->saw_tstamp = 0;
+ return 0;
+ } else if (th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
+ __u32 *ptr = (__u32 *)(th + 1);
+ if (*ptr == __constant_ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+ | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
+ tp->saw_tstamp = 1;
+ tp->rcv_tsval = ntohl(*++ptr);
+ tp->rcv_tsecr = ntohl(*++ptr);
+ return 1;
+ }
+ }
+ tcp_parse_options(sk, th, tp, 0);
+ return 1;
+}
+
+#define FLAG_DATA 0x01 /* Incoming frame contained data. */
+#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
+#define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */
+#define FLAG_RETRANS_DATA_ACKED 0x08 /* "" "" some of which was retransmitted. */
+
+static __inline__ void clear_fast_retransmit(struct tcp_opt *tp)
+{
+ if (tp->dup_acks > 3)
+ tp->snd_cwnd = (tp->snd_ssthresh);
+
+ tp->dup_acks = 0;
+}
+
+/* NOTE: This code assumes that tp->dup_acks gets cleared when a
+ * retransmit timer fires.
+ */
+static void tcp_fast_retrans(struct sock *sk, u32 ack, int not_dup)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Note: If not_dup is set this implies we got a
+ * data carrying packet or a window update.
+ * This carries no new information about possible
+ * lost packets, so we have to ignore it for the purposes
+ * of counting duplicate acks. Ideally this does not imply we
+ * should stop our fast retransmit phase, more acks may come
+ * later without data to help us. Unfortunately this would make
+ * the code below much more complex. For now if I see such
+ * a packet I clear the fast retransmit phase.
+ */
+ if (ack == tp->snd_una && tp->packets_out && (not_dup == 0)) {
+ /* This is the standard reno style fast retransmit branch. */
+
+ /* 1. When the third duplicate ack is received, set ssthresh
+ * to one half the current congestion window, but no less
+ * than two segments. Retransmit the missing segment.
+ */
+ if (tp->high_seq == 0 || after(ack, tp->high_seq)) {
+ tp->dup_acks++;
+ if ((tp->fackets_out > 3) || (tp->dup_acks == 3)) {
+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ tp->snd_cwnd = (tp->snd_ssthresh + 3);
+ tp->high_seq = tp->snd_nxt;
+ if(!tp->fackets_out)
+ tcp_retransmit_skb(sk,
+ skb_peek(&sk->write_queue));
+ else
+ tcp_fack_retransmit(sk);
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+ }
+ } else if (++tp->dup_acks > 3) {
+ /* 2. Each time another duplicate ACK arrives, increment
+ * cwnd by the segment size. [...] Transmit a packet...
+ *
+ * Packet transmission will be done on normal flow processing
+ * since we're not in "retransmit mode". We do not use
+ * duplicate ACKs to artificially inflate the congestion
+ * window when doing FACK.
+ */
+ if(!tp->fackets_out) {
+ tp->snd_cwnd++;
+ } else {
+ /* Fill any further holes which may have
+ * appeared.
+ *
+ * We may want to change this to run every
+ * further multiple-of-3 dup ack increments,
+ * to be more robust against out-of-order
+ * packet delivery. -DaveM
+ */
+ tcp_fack_retransmit(sk);
+ }
+ }
+ } else if (tp->high_seq != 0) {
+ /* In this branch we deal with clearing the Floyd style
+ * block on duplicate fast retransmits, and if requested
+ * we do Hoe style secondary fast retransmits.
+ */
+ if (!before(ack, tp->high_seq) || (not_dup & FLAG_DATA) != 0) {
+ /* Once we have acked all the packets up to high_seq
+ * we are done this fast retransmit phase.
+ * Alternatively data arrived. In this case we
+ * Have to abort the fast retransmit attempt.
+ * Note that we do want to accept a window
+ * update since this is expected with Hoe's algorithm.
+ */
+ clear_fast_retransmit(tp);
+
+ /* After we have cleared up to high_seq we can
+ * clear the Floyd style block.
+ */
+ if (!before(ack, tp->high_seq)) {
+ tp->high_seq = 0;
+ tp->fackets_out = 0;
+ }
+ } else if (tp->dup_acks >= 3) {
+ if (!tp->fackets_out) {
+ /* Hoe Style. We didn't ack the whole
+ * window. Take this as a cue that
+ * another packet was lost and retransmit it.
+ * Don't muck with the congestion window here.
+ * Note that we have to be careful not to
+ * act if this was a window update and it
+ * didn't ack new data, since this does
+ * not indicate a packet left the system.
+ * We can test this by just checking
+ * if ack changed from snd_una, since
+ * the only way to get here without advancing
+ * from snd_una is if this was a window update.
+ */
+ if (ack != tp->snd_una && before(ack, tp->high_seq)) {
+ tcp_retransmit_skb(sk,
+ skb_peek(&sk->write_queue));
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+ }
+ } else {
+ /* FACK style, fill any remaining holes in
+ * receiver's queue.
+ */
+ tcp_fack_retransmit(sk);
+ }
+ }
+ }
+}
+
+/* This is Jacobson's slow start and congestion avoidance.
+ * SIGCOMM '88, p. 328.
+ */
+static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
+{
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ /* In "safe" area, increase. */
+ tp->snd_cwnd++;
+ } else {
+ /* In dangerous area, increase slowly.
+ * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
+ */
+ if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt=0;
+ } else
+ tp->snd_cwnd_cnt++;
+ }
+}
+
+/* Remove acknowledged frames from the retransmission queue. */
+static int tcp_clean_rtx_queue(struct sock *sk, __u32 ack,
+ __u32 *seq, __u32 *seq_rtt)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+ __u32 now = tcp_time_stamp;
+ int acked = 0;
+
+ /* If we are retransmitting, and this ACK clears up to
+ * the retransmit head, or further, then clear our state.
+ */
+ if (tp->retrans_head != NULL &&
+ !before(ack, TCP_SKB_CB(tp->retrans_head)->end_seq))
+ tp->retrans_head = NULL;
+
+ while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head)) {
+ struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
+ __u8 sacked = scb->sacked;
+
+ /* If our packet is before the ack sequence we can
+ * discard it as it's confirmed to have arrived at
+ * the other end.
+ */
+ if (after(scb->end_seq, ack))
+ break;
+
+ /* Initial outgoing SYN's get put onto the write_queue
+ * just like anything else we transmit. It is not
+ * true data, and if we misinform our callers that
+ * this ACK acks real data, we will erroneously exit
+ * connection startup slow start one packet too
+ * quickly. This is severely frowned upon behavior.
+ */
+ if((sacked & TCPCB_SACKED_RETRANS) && tp->retrans_out)
+ tp->retrans_out--;
+ if(!(scb->flags & TCPCB_FLAG_SYN)) {
+ acked |= FLAG_DATA_ACKED;
+ if(sacked & TCPCB_SACKED_RETRANS)
+ acked |= FLAG_RETRANS_DATA_ACKED;
+ if(tp->fackets_out)
+ tp->fackets_out--;
+ } else {
+ /* This is pure paranoia. */
+ tp->retrans_head = NULL;
+ }
+ tp->packets_out--;
+ *seq = scb->seq;
+ *seq_rtt = now - scb->when;
+ __skb_unlink(skb, skb->list);
+ kfree_skb(skb);
+ }
+ return acked;
+}
+
+static void tcp_ack_probe(struct sock *sk, __u32 ack)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Our probe was answered. */
+ tp->probes_out = 0;
+
+ /* Was it a usable window open? */
+
+ /* should always be non-null */
+ if (tp->send_head != NULL &&
+ !before (ack + tp->snd_wnd, TCP_SKB_CB(tp->send_head)->end_seq)) {
+ tp->backoff = 0;
+ tp->pending = 0;
+ tcp_clear_xmit_timer(sk, TIME_PROBE0);
+ } else {
+ tcp_reset_xmit_timer(sk, TIME_PROBE0,
+ min(tp->rto << tp->backoff, 120*HZ));
+ }
+}
+
+/* Should we open up the congestion window? */
+static __inline__ int should_advance_cwnd(struct tcp_opt *tp, int flag)
+{
+ /* Data must have been acked. */
+ if ((flag & FLAG_DATA_ACKED) == 0)
+ return 0;
+
+ /* Some of the data acked was retransmitted somehow? */
+ if ((flag & FLAG_RETRANS_DATA_ACKED) != 0) {
+ /* We advance in all cases except during
+ * non-FACK fast retransmit/recovery.
+ */
+ if (tp->fackets_out != 0 ||
+ tp->retransmits != 0)
+ return 1;
+
+ /* Non-FACK fast retransmit does it's own
+ * congestion window management, don't get
+ * in the way.
+ */
+ return 0;
+ }
+
+ /* New non-retransmitted data acked, always advance. */
+ return 1;
+}
+
+/* Read draft-ietf-tcplw-high-performance before mucking
+ * with this code. (Superceeds RFC1323)
+ */
+static void tcp_ack_saw_tstamp(struct sock *sk, struct tcp_opt *tp,
+ u32 seq, u32 ack, int flag)
+{
+ __u32 seq_rtt;
+
+ /* RTTM Rule: A TSecr value received in a segment is used to
+ * update the averaged RTT measurement only if the segment
+ * acknowledges some new data, i.e., only if it advances the
+ * left edge of the send window.
+ *
+ * See draft-ietf-tcplw-high-performance-00, section 3.3.
+ * 1998/04/10 Andrey V. Savochkin <saw@msu.ru>
+ */
+ if (!(flag & FLAG_DATA_ACKED))
+ return;
+
+ seq_rtt = tcp_time_stamp - tp->rcv_tsecr;
+ tcp_rtt_estimator(tp, seq_rtt);
+ if (tp->retransmits) {
+ if (tp->packets_out == 0) {
+ tp->retransmits = 0;
+ tp->fackets_out = 0;
+ tp->retrans_out = 0;
+ tp->backoff = 0;
+ tcp_set_rto(tp);
+ } else {
+ /* Still retransmitting, use backoff */
+ tcp_set_rto(tp);
+ tp->rto = tp->rto << tp->backoff;
+ }
+ } else {
+ tcp_set_rto(tp);
+ }
+
+ tcp_bound_rto(tp);
+}
+
+static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
+{
+ struct sk_buff *skb = skb_peek(&sk->write_queue);
+
+ /* Some data was ACK'd, if still retransmitting (due to a
+ * timeout), resend more of the retransmit queue. The
+ * congestion window is handled properly by that code.
+ */
+ if (tp->retransmits) {
+ tcp_xmit_retransmit_queue(sk);
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+ } else {
+ __u32 when = tp->rto - (tcp_time_stamp - TCP_SKB_CB(skb)->when);
+ if ((__s32)when < 0)
+ when = 1;
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, when);
+ }
+}
+
+/* This routine deals with incoming acks, but not outgoing ones. */
+static int tcp_ack(struct sock *sk, struct tcphdr *th,
+ u32 ack_seq, u32 ack, int len)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int flag = 0;
+ u32 seq = 0;
+ u32 seq_rtt = 0;
+
+ if(sk->zapped)
+ return(1); /* Dead, can't ack any more so why bother */
+
+ if (tp->pending == TIME_KEEPOPEN)
+ tp->probes_out = 0;
+
+ tp->rcv_tstamp = tcp_time_stamp;
+
+ /* If the ack is newer than sent or older than previous acks
+ * then we can probably ignore it.
+ */
+ if (after(ack, tp->snd_nxt) || before(ack, tp->snd_una))
+ goto uninteresting_ack;
+
+ /* If there is data set flag 1 */
+ if (len != th->doff*4) {
+ flag |= FLAG_DATA;
+ tcp_delack_estimator(tp);
+ }
+
+ /* Update our send window. */
+
+ /* This is the window update code as per RFC 793
+ * snd_wl{1,2} are used to prevent unordered
+ * segments from shrinking the window
+ */
+ if (before(tp->snd_wl1, ack_seq) ||
+ (tp->snd_wl1 == ack_seq && !after(tp->snd_wl2, ack))) {
+ u32 nwin = ntohs(th->window) << tp->snd_wscale;
+
+ if ((tp->snd_wl2 != ack) || (nwin > tp->snd_wnd)) {
+ flag |= FLAG_WIN_UPDATE;
+ tp->snd_wnd = nwin;
+
+ tp->snd_wl1 = ack_seq;
+ tp->snd_wl2 = ack;
+
+ if (nwin > tp->max_window)
+ tp->max_window = nwin;
+ }
+ }
+
+ /* We passed data and got it acked, remove any soft error
+ * log. Something worked...
+ */
+ sk->err_soft = 0;
+
+ /* If this ack opens up a zero window, clear backoff. It was
+ * being used to time the probes, and is probably far higher than
+ * it needs to be for normal retransmission.
+ */
+ if (tp->pending == TIME_PROBE0)
+ tcp_ack_probe(sk, ack);
+
+ /* See if we can take anything off of the retransmit queue. */
+ flag |= tcp_clean_rtx_queue(sk, ack, &seq, &seq_rtt);
+
+ /* We must do this here, before code below clears out important
+ * state contained in tp->fackets_out and tp->retransmits. -DaveM
+ */
+ if (should_advance_cwnd(tp, flag))
+ tcp_cong_avoid(tp);
+
+ /* If we have a timestamp, we always do rtt estimates. */
+ if (tp->saw_tstamp) {
+ tcp_ack_saw_tstamp(sk, tp, seq, ack, flag);
+ } else {
+ /* If we were retransmiting don't count rtt estimate. */
+ if (tp->retransmits) {
+ if (tp->packets_out == 0) {
+ tp->retransmits = 0;
+ tp->fackets_out = 0;
+ tp->retrans_out = 0;
+ }
+ } else {
+ /* We don't have a timestamp. Can only use
+ * packets that are not retransmitted to determine
+ * rtt estimates. Also, we must not reset the
+ * backoff for rto until we get a non-retransmitted
+ * packet. This allows us to deal with a situation
+ * where the network delay has increased suddenly.
+ * I.e. Karn's algorithm. (SIGCOMM '87, p5.)
+ */
+ if (flag & FLAG_DATA_ACKED) {
+ if(!(flag & FLAG_RETRANS_DATA_ACKED)) {
+ tp->backoff = 0;
+ tcp_rtt_estimator(tp, seq_rtt);
+ tcp_set_rto(tp);
+ tcp_bound_rto(tp);
+ }
+ }
+ }
+ }
+
+ if (tp->packets_out) {
+ if (flag & FLAG_DATA_ACKED)
+ tcp_ack_packets_out(sk, tp);
+ } else {
+ tcp_clear_xmit_timer(sk, TIME_RETRANS);
+ }
+
+ flag &= (FLAG_DATA | FLAG_WIN_UPDATE);
+ if ((ack == tp->snd_una && tp->packets_out && flag == 0) ||
+ (tp->high_seq != 0)) {
+ tcp_fast_retrans(sk, ack, flag);
+ } else {
+ /* Clear any aborted fast retransmit starts. */
+ tp->dup_acks = 0;
+ }
+ /* It is not a brain fart, I thought a bit now. 8)
+ *
+ * Forward progress is indicated, if:
+ * 1. the ack acknowledges new data.
+ * 2. or the ack is duplicate, but it is caused by new segment
+ * arrival. This case is filtered by:
+ * - it contains no data, syn or fin.
+ * - it does not update window.
+ * 3. or new SACK. It is difficult to check, so that we ignore it.
+ *
+ * Forward progress is also indicated by arrival new data,
+ * which was caused by window open from our side. This case is more
+ * difficult and it is made (alas, incorrectly) in tcp_data_queue().
+ * --ANK (990513)
+ */
+ if (ack != tp->snd_una || (flag == 0 && !th->fin))
+ dst_confirm(sk->dst_cache);
+
+ /* Remember the highest ack received. */
+ tp->snd_una = ack;
+ return 1;
+
+uninteresting_ack:
+ SOCK_DEBUG(sk, "Ack ignored %u %u\n", ack, tp->snd_nxt);
+ return 0;
+}
+
+/* New-style handling of TIME_WAIT sockets. */
+extern void tcp_tw_schedule(struct tcp_tw_bucket *tw);
+extern void tcp_tw_reschedule(struct tcp_tw_bucket *tw);
+extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
+
+void tcp_timewait_kill(struct tcp_tw_bucket *tw)
+{
+ struct tcp_bind_bucket *tb = tw->tb;
+
+ /* Disassociate with bind bucket. */
+ if(tw->bind_next)
+ tw->bind_next->bind_pprev = tw->bind_pprev;
+ *(tw->bind_pprev) = tw->bind_next;
+ if (tb->owners == NULL) {
+ if (tb->next)
+ tb->next->pprev = tb->pprev;
+ *(tb->pprev) = tb->next;
+ kmem_cache_free(tcp_bucket_cachep, tb);
+ }
+
+ /* Unlink from established hashes. */
+ if(tw->next)
+ tw->next->pprev = tw->pprev;
+ *tw->pprev = tw->next;
+
+ /* We decremented the prot->inuse count when we entered TIME_WAIT
+ * and the sock from which this came was destroyed.
+ */
+ tw->sklist_next->sklist_prev = tw->sklist_prev;
+ tw->sklist_prev->sklist_next = tw->sklist_next;
+
+ /* Ok, now free it up. */
+ kmem_cache_free(tcp_timewait_cachep, tw);
+}
+
+/* We come here as a special case from the AF specific TCP input processing,
+ * and the SKB has no owner. Essentially handling this is very simple,
+ * we just keep silently eating rx'd packets, acking them if necessary,
+ * until none show up for the entire timeout period.
+ *
+ * Return 0, TCP_TW_ACK, TCP_TW_RST
+ */
+enum tcp_tw_status
+tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
+ struct tcphdr *th, unsigned len)
+{
+ /* RFC 1122:
+ * "When a connection is [...] on TIME-WAIT state [...]
+ * [a TCP] MAY accept a new SYN from the remote TCP to
+ * reopen the connection directly, if it:
+ *
+ * (1) assigns its initial sequence number for the new
+ * connection to be larger than the largest sequence
+ * number it used on the previous connection incarnation,
+ * and
+ *
+ * (2) returns to TIME-WAIT state if the SYN turns out
+ * to be an old duplicate".
+ */
+ if(th->syn && !th->rst && after(TCP_SKB_CB(skb)->seq, tw->rcv_nxt)) {
+ struct sock *sk;
+ struct tcp_func *af_specific = tw->af_specific;
+ __u32 isn;
+
+ isn = tw->snd_nxt + 128000;
+ if(isn == 0)
+ isn++;
+ tcp_tw_deschedule(tw);
+ tcp_timewait_kill(tw);
+ sk = af_specific->get_sock(skb, th);
+ if(sk == NULL ||
+ !ipsec_sk_policy(sk,skb) ||
+ atomic_read(&sk->sock_readers) != 0)
+ return 0;
+ skb_set_owner_r(skb, sk);
+ af_specific = sk->tp_pinfo.af_tcp.af_specific;
+ if(af_specific->conn_request(sk, skb, isn) < 0)
+ return TCP_TW_RST; /* Toss a reset back. */
+ return 0; /* Discard the frame. */
+ }
+
+ /* Check RST or SYN */
+ if(th->rst || th->syn) {
+ /* This is TIME_WAIT assasination, in two flavors.
+ * Oh well... nobody has a sufficient solution to this
+ * protocol bug yet.
+ */
+ if(sysctl_tcp_rfc1337 == 0) {
+ tcp_tw_deschedule(tw);
+ tcp_timewait_kill(tw);
+ }
+ if(!th->rst)
+ return TCP_TW_RST; /* toss a reset back */
+ return 0;
+ } else {
+ /* In this case we must reset the TIMEWAIT timer. */
+ if(th->ack)
+ tcp_tw_reschedule(tw);
+ }
+ /* Ack old packets if necessary */
+ if (!after(TCP_SKB_CB(skb)->end_seq, tw->rcv_nxt) &&
+ (th->doff * 4) > len)
+ return TCP_TW_ACK;
+ return 0;
+}
+
+/* Enter the time wait state. This is always called from BH
+ * context. Essentially we whip up a timewait bucket, copy the
+ * relevant info into it from the SK, and mess with hash chains
+ * and list linkage.
+ */
+static __inline__ void tcp_tw_hashdance(struct sock *sk, struct tcp_tw_bucket *tw)
+{
+ struct sock **head, *sktw;
+
+ /* Step 1: Remove SK from established hash. */
+ if(sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ tcp_reg_zap(sk);
+
+ /* Step 2: Put TW into bind hash where SK was. */
+ tw->tb = (struct tcp_bind_bucket *)sk->prev;
+ if((tw->bind_next = sk->bind_next) != NULL)
+ sk->bind_next->bind_pprev = &tw->bind_next;
+ tw->bind_pprev = sk->bind_pprev;
+ *sk->bind_pprev = (struct sock *)tw;
+ sk->prev = NULL;
+
+ /* Step 3: Same for the protocol sklist. */
+ (tw->sklist_next = sk->sklist_next)->sklist_prev = (struct sock *)tw;
+ (tw->sklist_prev = sk->sklist_prev)->sklist_next = (struct sock *)tw;
+ sk->sklist_next = NULL;
+ sk->prot->inuse--;
+
+ /* Step 4: Hash TW into TIMEWAIT half of established hash table. */
+ head = &tcp_established_hash[sk->hashent + (TCP_HTABLE_SIZE/2)];
+ sktw = (struct sock *)tw;
+ if((sktw->next = *head) != NULL)
+ (*head)->pprev = &sktw->next;
+ *head = sktw;
+ sktw->pprev = head;
+}
+
+void tcp_time_wait(struct sock *sk)
+{
+ struct tcp_tw_bucket *tw;
+
+ tw = kmem_cache_alloc(tcp_timewait_cachep, SLAB_ATOMIC);
+ if(tw != NULL) {
+ /* Give us an identity. */
+ tw->daddr = sk->daddr;
+ tw->rcv_saddr = sk->rcv_saddr;
+ tw->bound_dev_if= sk->bound_dev_if;
+ tw->num = sk->num;
+ tw->state = TCP_TIME_WAIT;
+ tw->sport = sk->sport;
+ tw->dport = sk->dport;
+ tw->family = sk->family;
+ tw->reuse = sk->reuse;
+ tw->rcv_nxt = sk->tp_pinfo.af_tcp.rcv_nxt;
+ tw->snd_nxt = sk->tp_pinfo.af_tcp.snd_nxt;
+ tw->window = tcp_select_window(sk);
+ tw->af_specific = sk->tp_pinfo.af_tcp.af_specific;
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ if(tw->family == PF_INET6) {
+ memcpy(&tw->v6_daddr,
+ &sk->net_pinfo.af_inet6.daddr,
+ sizeof(struct in6_addr));
+ memcpy(&tw->v6_rcv_saddr,
+ &sk->net_pinfo.af_inet6.rcv_saddr,
+ sizeof(struct in6_addr));
+ }
+#endif
+ /* Linkage updates. */
+ tcp_tw_hashdance(sk, tw);
+
+ /* Get the TIME_WAIT timeout firing. */
+ tcp_tw_schedule(tw);
+
+ /* CLOSE the SK. */
+ if(sk->state == TCP_ESTABLISHED)
+ tcp_statistics.TcpCurrEstab--;
+ sk->state = TCP_CLOSE;
+ net_reset_timer(sk, TIME_DONE,
+ min(sk->tp_pinfo.af_tcp.srtt * 2, TCP_DONE_TIME));
+ } else {
+ /* Sorry, we're out of memory, just CLOSE this
+ * socket up. We've got bigger problems than
+ * non-graceful socket closings.
+ */
+ tcp_set_state(sk, TCP_CLOSE);
+ }
+
+ /* Prevent rcvmsg/sndmsg calls, and wake people up. */
+ sk->shutdown = SHUTDOWN_MASK;
+ if(!sk->dead)
+ sk->state_change(sk);
+}
+
+/*
+ * Process the FIN bit. This now behaves as it is supposed to work
+ * and the FIN takes effect when it is validly part of sequence
+ * space. Not before when we get holes.
+ *
+ * If we are ESTABLISHED, a received fin moves us to CLOSE-WAIT
+ * (and thence onto LAST-ACK and finally, CLOSE, we never enter
+ * TIME-WAIT)
+ *
+ * If we are in FINWAIT-1, a received FIN indicates simultaneous
+ * close and we go into CLOSING (and later onto TIME-WAIT)
+ *
+ * If we are in FINWAIT-2, a received FIN moves us to TIME-WAIT.
+ */
+
+static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
+{
+ sk->tp_pinfo.af_tcp.fin_seq = TCP_SKB_CB(skb)->end_seq;
+
+ tcp_send_ack(sk);
+
+ if (!sk->dead) {
+ sk->state_change(sk);
+ sock_wake_async(sk->socket, 1);
+ }
+
+ switch(sk->state) {
+ case TCP_SYN_RECV:
+ case TCP_ESTABLISHED:
+ /* Move to CLOSE_WAIT */
+ tcp_set_state(sk, TCP_CLOSE_WAIT);
+ if (th->rst)
+ sk->shutdown = SHUTDOWN_MASK;
+ break;
+
+ case TCP_CLOSE_WAIT:
+ case TCP_CLOSING:
+ /* Received a retransmission of the FIN, do
+ * nothing.
+ */
+ break;
+ case TCP_LAST_ACK:
+ /* RFC793: Remain in the LAST-ACK state. */
+ break;
+
+ case TCP_FIN_WAIT1:
+ /* This case occurs when a simultaneous close
+ * happens, we must ack the received FIN and
+ * enter the CLOSING state.
+ *
+ * This causes a WRITE timeout, which will either
+ * move on to TIME_WAIT when we timeout, or resend
+ * the FIN properly (maybe we get rid of that annoying
+ * FIN lost hang). The TIME_WRITE code is already
+ * correct for handling this timeout.
+ */
+ tcp_set_state(sk, TCP_CLOSING);
+ break;
+ case TCP_FIN_WAIT2:
+ /* Received a FIN -- send ACK and enter TIME_WAIT. */
+ tcp_time_wait(sk);
+ break;
+ default:
+ /* Only TCP_LISTEN and TCP_CLOSE are left, in these
+ * cases we should never reach this piece of code.
+ */
+ printk("tcp_fin: Impossible, sk->state=%d\n", sk->state);
+ break;
+ };
+}
+
+/* These routines update the SACK block as out-of-order packets arrive or
+ * in-order packets close up the sequence space.
+ */
+static void tcp_sack_maybe_coalesce(struct tcp_opt *tp, struct tcp_sack_block *sp)
+{
+ int this_sack, num_sacks = tp->num_sacks;
+ struct tcp_sack_block *swalk = &tp->selective_acks[0];
+
+ /* If more than one SACK block, see if the recent change to SP eats into
+ * or hits the sequence space of other SACK blocks, if so coalesce.
+ */
+ if(num_sacks != 1) {
+ for(this_sack = 0; this_sack < num_sacks; this_sack++, swalk++) {
+ if(swalk == sp)
+ continue;
+
+ /* First case, bottom of SP moves into top of the
+ * sequence space of SWALK.
+ */
+ if(between(sp->start_seq, swalk->start_seq, swalk->end_seq)) {
+ sp->start_seq = swalk->start_seq;
+ goto coalesce;
+ }
+ /* Second case, top of SP moves into bottom of the
+ * sequence space of SWALK.
+ */
+ if(between(sp->end_seq, swalk->start_seq, swalk->end_seq)) {
+ sp->end_seq = swalk->end_seq;
+ goto coalesce;
+ }
+ }
+ }
+ /* SP is the only SACK, or no coalescing cases found. */
+ return;
+
+coalesce:
+ /* Zap SWALK, by moving every further SACK up by one slot.
+ * Decrease num_sacks.
+ */
+ for(; this_sack < num_sacks-1; this_sack++, swalk++) {
+ struct tcp_sack_block *next = (swalk + 1);
+ swalk->start_seq = next->start_seq;
+ swalk->end_seq = next->end_seq;
+ }
+ tp->num_sacks--;
+}
+
+static __inline__ void tcp_sack_swap(struct tcp_sack_block *sack1, struct tcp_sack_block *sack2)
+{
+ __u32 tmp;
+
+ tmp = sack1->start_seq;
+ sack1->start_seq = sack2->start_seq;
+ sack2->start_seq = tmp;
+
+ tmp = sack1->end_seq;
+ sack1->end_seq = sack2->end_seq;
+ sack2->end_seq = tmp;
+}
+
+static void tcp_sack_new_ofo_skb(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct tcp_sack_block *sp = &tp->selective_acks[0];
+ int cur_sacks = tp->num_sacks;
+
+ if (!cur_sacks)
+ goto new_sack;
+
+ /* Optimize for the common case, new ofo frames arrive
+ * "in order". ;-) This also satisfies the requirements
+ * of RFC2018 about ordering of SACKs.
+ */
+ if(sp->end_seq == TCP_SKB_CB(skb)->seq) {
+ sp->end_seq = TCP_SKB_CB(skb)->end_seq;
+ tcp_sack_maybe_coalesce(tp, sp);
+ } else if(sp->start_seq == TCP_SKB_CB(skb)->end_seq) {
+ /* Re-ordered arrival, in this case, can be optimized
+ * as well.
+ */
+ sp->start_seq = TCP_SKB_CB(skb)->seq;
+ tcp_sack_maybe_coalesce(tp, sp);
+ } else {
+ struct tcp_sack_block *swap = sp + 1;
+ int this_sack, max_sacks = (tp->tstamp_ok ? 3 : 4);
+
+ /* Oh well, we have to move things around.
+ * Try to find a SACK we can tack this onto.
+ */
+
+ for(this_sack = 1; this_sack < cur_sacks; this_sack++, swap++) {
+ if((swap->end_seq == TCP_SKB_CB(skb)->seq) ||
+ (swap->start_seq == TCP_SKB_CB(skb)->end_seq)) {
+ if(swap->end_seq == TCP_SKB_CB(skb)->seq)
+ swap->end_seq = TCP_SKB_CB(skb)->end_seq;
+ else
+ swap->start_seq = TCP_SKB_CB(skb)->seq;
+ tcp_sack_swap(sp, swap);
+ tcp_sack_maybe_coalesce(tp, sp);
+ return;
+ }
+ }
+
+ /* Could not find an adjacent existing SACK, build a new one,
+ * put it at the front, and shift everyone else down. We
+ * always know there is at least one SACK present already here.
+ *
+ * If the sack array is full, forget about the last one.
+ */
+ if (cur_sacks >= max_sacks) {
+ cur_sacks--;
+ tp->num_sacks--;
+ }
+ while(cur_sacks >= 1) {
+ struct tcp_sack_block *this = &tp->selective_acks[cur_sacks];
+ struct tcp_sack_block *prev = (this - 1);
+ this->start_seq = prev->start_seq;
+ this->end_seq = prev->end_seq;
+ cur_sacks--;
+ }
+
+ new_sack:
+ /* Build the new head SACK, and we're done. */
+ sp->start_seq = TCP_SKB_CB(skb)->seq;
+ sp->end_seq = TCP_SKB_CB(skb)->end_seq;
+ tp->num_sacks++;
+ }
+}
+
+static void tcp_sack_remove_skb(struct tcp_opt *tp, struct sk_buff *skb)
+{
+ struct tcp_sack_block *sp = &tp->selective_acks[0];
+ int num_sacks = tp->num_sacks;
+ int this_sack;
+
+ /* This is an in order data segment _or_ an out-of-order SKB being
+ * moved to the receive queue, so we know this removed SKB will eat
+ * from the front of a SACK.
+ */
+ for(this_sack = 0; this_sack < num_sacks; this_sack++, sp++) {
+ /* Check if the start of the sack is covered by skb. */
+ if(!before(sp->start_seq, TCP_SKB_CB(skb)->seq) &&
+ before(sp->start_seq, TCP_SKB_CB(skb)->end_seq))
+ break;
+ }
+
+ /* This should only happen if so many SACKs get built that some get
+ * pushed out before we get here, or we eat some in sequence packets
+ * which are before the first SACK block.
+ */
+ if(this_sack >= num_sacks)
+ return;
+
+ sp->start_seq = TCP_SKB_CB(skb)->end_seq;
+ if(!before(sp->start_seq, sp->end_seq)) {
+ /* Zap this SACK, by moving forward any other SACKS. */
+ for(this_sack += 1; this_sack < num_sacks; this_sack++, sp++) {
+ struct tcp_sack_block *next = (sp + 1);
+ sp->start_seq = next->start_seq;
+ sp->end_seq = next->end_seq;
+ }
+ tp->num_sacks--;
+ }
+}
+
+static void tcp_sack_extend(struct tcp_opt *tp, struct sk_buff *old_skb, struct sk_buff *new_skb)
+{
+ struct tcp_sack_block *sp = &tp->selective_acks[0];
+ int num_sacks = tp->num_sacks;
+ int this_sack;
+
+ for(this_sack = 0; this_sack < num_sacks; this_sack++, sp++) {
+ if(sp->end_seq == TCP_SKB_CB(old_skb)->end_seq)
+ break;
+ }
+ if(this_sack >= num_sacks)
+ return;
+ sp->end_seq = TCP_SKB_CB(new_skb)->end_seq;
+}
+
+/* This one checks to see if we can put data from the
+ * out_of_order queue into the receive_queue.
+ */
+static void tcp_ofo_queue(struct sock *sk)
+{
+ struct sk_buff *skb;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ while ((skb = skb_peek(&tp->out_of_order_queue))) {
+ if (after(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
+ break;
+
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
+ SOCK_DEBUG(sk, "ofo packet was already received \n");
+ __skb_unlink(skb, skb->list);
+ kfree_skb(skb);
+ continue;
+ }
+ SOCK_DEBUG(sk, "ofo requeuing : rcv_next %X seq %X - %X\n",
+ tp->rcv_nxt, TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->end_seq);
+
+ if(tp->sack_ok)
+ tcp_sack_remove_skb(tp, skb);
+ __skb_unlink(skb, skb->list);
+ __skb_queue_tail(&sk->receive_queue, skb);
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ if(skb->h.th->fin)
+ tcp_fin(skb, sk, skb->h.th);
+ }
+}
+
+static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
+{
+ struct sk_buff *skb1;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Queue data for delivery to the user.
+ * Packets in sequence go to the receive queue.
+ * Out of sequence packets to the out_of_order_queue.
+ */
+ if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+ /* Ok. In sequence. */
+ queue_and_out:
+ dst_confirm(sk->dst_cache);
+ __skb_queue_tail(&sk->receive_queue, skb);
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ if(skb->h.th->fin) {
+ tcp_fin(skb, sk, skb->h.th);
+ } else {
+ tcp_remember_ack(tp, skb->h.th, skb);
+ }
+ /* This may have eaten into a SACK block. */
+ if(tp->sack_ok && tp->num_sacks)
+ tcp_sack_remove_skb(tp, skb);
+ tcp_ofo_queue(sk);
+
+ /* Turn on fast path. */
+ if (skb_queue_len(&tp->out_of_order_queue) == 0)
+ tp->pred_flags = htonl(((tp->tcp_header_len >> 2) << 28) |
+ (0x10 << 16) |
+ tp->snd_wnd);
+ return;
+ }
+
+ /* An old packet, either a retransmit or some packet got lost. */
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
+ /* A retransmit, 2nd most common case. Force an imediate ack. */
+ SOCK_DEBUG(sk, "retransmit received: seq %X\n", TCP_SKB_CB(skb)->seq);
+ tcp_enter_quickack_mode(tp);
+ kfree_skb(skb);
+ return;
+ }
+
+ if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+ /* Partial packet, seq < rcv_next < end_seq */
+ SOCK_DEBUG(sk, "partial packet: rcv_next %X seq %X - %X\n",
+ tp->rcv_nxt, TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->end_seq);
+
+ goto queue_and_out;
+ }
+
+ /* Ok. This is an out_of_order segment, force an ack. */
+ tp->delayed_acks++;
+ tcp_enter_quickack_mode(tp);
+
+ /* Disable header prediction. */
+ tp->pred_flags = 0;
+
+ SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n",
+ tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
+
+ if (skb_peek(&tp->out_of_order_queue) == NULL) {
+ /* Initial out of order segment, build 1 SACK. */
+ if(tp->sack_ok) {
+ tp->num_sacks = 1;
+ tp->selective_acks[0].start_seq = TCP_SKB_CB(skb)->seq;
+ tp->selective_acks[0].end_seq = TCP_SKB_CB(skb)->end_seq;
+ }
+ __skb_queue_head(&tp->out_of_order_queue,skb);
+ } else {
+ for(skb1=tp->out_of_order_queue.prev; ; skb1 = skb1->prev) {
+ /* Already there. */
+ if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb1)->seq) {
+ if (skb->len >= skb1->len) {
+ if(tp->sack_ok)
+ tcp_sack_extend(tp, skb1, skb);
+ __skb_append(skb1, skb);
+ __skb_unlink(skb1, skb1->list);
+ kfree_skb(skb1);
+ } else {
+ /* A duplicate, smaller than what is in the
+ * out-of-order queue right now, toss it.
+ */
+ kfree_skb(skb);
+ }
+ break;
+ }
+
+ if (after(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb1)->seq)) {
+ __skb_append(skb1, skb);
+ if(tp->sack_ok)
+ tcp_sack_new_ofo_skb(sk, skb);
+ break;
+ }
+
+ /* See if we've hit the start. If so insert. */
+ if (skb1 == skb_peek(&tp->out_of_order_queue)) {
+ __skb_queue_head(&tp->out_of_order_queue,skb);
+ if(tp->sack_ok)
+ tcp_sack_new_ofo_skb(sk, skb);
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+ * This routine handles the data. If there is room in the buffer,
+ * it will be have already been moved into it. If there is no
+ * room, then we will just have to discard the packet.
+ */
+
+static int tcp_data(struct sk_buff *skb, struct sock *sk, unsigned int len)
+{
+ struct tcphdr *th;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ th = skb->h.th;
+ skb_pull(skb, th->doff*4);
+ skb_trim(skb, len - (th->doff*4));
+
+ if (skb->len == 0 && !th->fin)
+ return(0);
+
+ /*
+ * If our receive queue has grown past its limits shrink it.
+ * Make sure to do this before moving snd_nxt, otherwise
+ * data might be acked for that we don't have enough room.
+ */
+ if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf) {
+ if (prune_queue(sk) < 0) {
+ /* Still not enough room. That can happen when
+ * skb->true_size differs significantly from skb->len.
+ */
+ return 0;
+ }
+ }
+
+ tcp_data_queue(sk, skb);
+
+ if (before(tp->rcv_nxt, tp->copied_seq)) {
+ printk(KERN_DEBUG "*** tcp.c:tcp_data bug acked < copied\n");
+ tp->rcv_nxt = tp->copied_seq;
+ }
+
+ /* Above, tcp_data_queue() increments delayed_acks appropriately.
+ * Now tell the user we may have some data.
+ */
+ if (!sk->dead) {
+ sk->data_ready(sk,0);
+ }
+ return(1);
+}
+
+static void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) &&
+ tcp_packets_in_flight(tp) < tp->snd_cwnd) {
+ /* Put more data onto the wire. */
+ tcp_write_xmit(sk);
+ } else if (tp->packets_out == 0 && !tp->pending) {
+ /* Start probing the receivers window. */
+ tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto);
+ }
+}
+
+static __inline__ void tcp_data_snd_check(struct sock *sk)
+{
+ struct sk_buff *skb = sk->tp_pinfo.af_tcp.send_head;
+
+ if (skb != NULL)
+ __tcp_data_snd_check(sk, skb);
+}
+
+/*
+ * Adapt the MSS value used to make delayed ack decision to the
+ * real world.
+ */
+static __inline__ void tcp_measure_rcv_mss(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ unsigned int len = skb->len, lss;
+
+ if (len > tp->rcv_mss)
+ tp->rcv_mss = len;
+ lss = tp->last_seg_size;
+ tp->last_seg_size = 0;
+ if (len >= 536) {
+ if (len == lss)
+ tp->rcv_mss = len;
+ tp->last_seg_size = len;
+ }
+}
+
+/*
+ * Check if sending an ack is needed.
+ */
+static __inline__ void __tcp_ack_snd_check(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* This also takes care of updating the window.
+ * This if statement needs to be simplified.
+ *
+ * Rules for delaying an ack:
+ * - delay time <= 0.5 HZ
+ * - we don't have a window update to send
+ * - must send at least every 2 full sized packets
+ * - must send an ACK if we have any out of order data
+ *
+ * With an extra heuristic to handle loss of packet
+ * situations and also helping the sender leave slow
+ * start in an expediant manner.
+ */
+
+ /* Two full frames received or... */
+ if (((tp->rcv_nxt - tp->rcv_wup) >= tp->rcv_mss * MAX_DELAY_ACK) ||
+ /* We will update the window "significantly" or... */
+ tcp_raise_window(sk) ||
+ /* We entered "quick ACK" mode or... */
+ tcp_in_quickack_mode(tp) ||
+ /* We have out of order data */
+ (skb_peek(&tp->out_of_order_queue) != NULL)) {
+ /* Then ack it now */
+ tcp_send_ack(sk);
+ } else {
+ /* Else, send delayed ack. */
+ tcp_send_delayed_ack(tp, HZ/2);
+ }
+}
+
+static __inline__ void tcp_ack_snd_check(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ if (tp->delayed_acks == 0) {
+ /* We sent a data segment already. */
+ return;
+ }
+ __tcp_ack_snd_check(sk);
+}
+
+
+/*
+ * This routine is only called when we have urgent data
+ * signalled. Its the 'slow' part of tcp_urg. It could be
+ * moved inline now as tcp_urg is only called from one
+ * place. We handle URGent data wrong. We have to - as
+ * BSD still doesn't use the correction from RFC961.
+ * For 1003.1g we should support a new option TCP_STDURG to permit
+ * either form (or just set the sysctl tcp_stdurg).
+ */
+
+static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ u32 ptr = ntohs(th->urg_ptr);
+
+ if (ptr && !sysctl_tcp_stdurg)
+ ptr--;
+ ptr += ntohl(th->seq);
+
+ /* Ignore urgent data that we've already seen and read. */
+ if (after(tp->copied_seq, ptr))
+ return;
+
+ /* Do we already have a newer (or duplicate) urgent pointer? */
+ if (tp->urg_data && !after(ptr, tp->urg_seq))
+ return;
+
+ /* Tell the world about our new urgent pointer. */
+ if (sk->proc != 0) {
+ if (sk->proc > 0)
+ kill_proc(sk->proc, SIGURG, 1);
+ else
+ kill_pg(-sk->proc, SIGURG, 1);
+ }
+
+ /* We may be adding urgent data when the last byte read was
+ * urgent. To do this requires some care. We cannot just ignore
+ * tp->copied_seq since we would read the last urgent byte again
+ * as data, nor can we alter copied_seq until this data arrives
+ * or we break the sematics of SIOCATMARK (and thus sockatmark())
+ */
+ if (tp->urg_seq == tp->copied_seq)
+ tp->copied_seq++; /* Move the copied sequence on correctly */
+ tp->urg_data = URG_NOTYET;
+ tp->urg_seq = ptr;
+
+ /* Disable header prediction. */
+ tp->pred_flags = 0;
+}
+
+/* This is the 'fast' part of urgent handling. */
+static inline void tcp_urg(struct sock *sk, struct tcphdr *th, unsigned long len)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Check if we get a new urgent pointer - normally not. */
+ if (th->urg)
+ tcp_check_urg(sk,th);
+
+ /* Do we wait for any urgent data? - normally not... */
+ if (tp->urg_data == URG_NOTYET) {
+ u32 ptr = tp->urg_seq - ntohl(th->seq) + (th->doff*4);
+
+ /* Is the urgent pointer pointing into this packet? */
+ if (ptr < len) {
+ tp->urg_data = URG_VALID | *(ptr + (unsigned char *) th);
+ if (!sk->dead)
+ sk->data_ready(sk,0);
+ }
+ }
+}
+
+/* Clean the out_of_order queue if we can, trying to get
+ * the socket within its memory limits again.
+ *
+ * Return less than zero if we should start dropping frames
+ * until the socket owning process reads some of the data
+ * to stabilize the situation.
+ */
+static int prune_queue(struct sock *sk)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct sk_buff * skb;
+
+ SOCK_DEBUG(sk, "prune_queue: c=%x\n", tp->copied_seq);
+
+ net_statistics.PruneCalled++;
+
+ /* First, purge the out_of_order queue. */
+ skb = __skb_dequeue_tail(&tp->out_of_order_queue);
+ if(skb != NULL) {
+ /* Free it all. */
+ do { net_statistics.OfoPruned += skb->len;
+ kfree_skb(skb);
+ skb = __skb_dequeue_tail(&tp->out_of_order_queue);
+ } while(skb != NULL);
+
+ /* Reset SACK state. A conforming SACK implementation will
+ * do the same at a timeout based retransmit. When a connection
+ * is in a sad state like this, we care only about integrity
+ * of the connection not performance.
+ */
+ if(tp->sack_ok)
+ tp->num_sacks = 0;
+ }
+
+ /* If we are really being abused, tell the caller to silently
+ * drop receive data on the floor. It will get retransmitted
+ * and hopefully then we'll have sufficient space.
+ *
+ * We used to try to purge the in-order packets too, but that
+ * turns out to be deadly and fraught with races. Consider:
+ *
+ * 1) If we acked the data, we absolutely cannot drop the
+ * packet. This data would then never be retransmitted.
+ * 2) It is possible, with a proper sequence of events involving
+ * delayed acks and backlog queue handling, to have the user
+ * read the data before it gets acked. The previous code
+ * here got this wrong, and it lead to data corruption.
+ * 3) Too much state changes happen when the FIN arrives, so once
+ * we've seen that we can't remove any in-order data safely.
+ *
+ * The net result is that removing in-order receive data is too
+ * complex for anyones sanity. So we don't do it anymore. But
+ * if we are really having our buffer space abused we stop accepting
+ * new receive data.
+ */
+ if(atomic_read(&sk->rmem_alloc) < (sk->rcvbuf << 1))
+ return 0;
+
+ /* Massive buffer overcommit. */
+ return -1;
+}
+
+/*
+ * TCP receive function for the ESTABLISHED state.
+ *
+ * It is split into a fast path and a slow path. The fast path is
+ * disabled when:
+ * - A zero window was announced from us - zero window probing
+ * is only handled properly in the slow path.
+ * - Out of order segments arrived.
+ * - Urgent data is expected.
+ * - There is no buffer space left
+ * - Unexpected TCP flags/window values/header lengths are received
+ * (detected by checking the TCP header against pred_flags)
+ * - Data is sent in both directions. Fast path only supports pure senders
+ * or pure receivers (this means either the sequence number or the ack
+ * value must stay constant)
+ *
+ * When these conditions are not satisfied it drops into a standard
+ * receive procedure patterned after RFC793 to handle all cases.
+ * The first three cases are guaranteed by proper pred_flags setting,
+ * the rest is checked inline. Fast processing is turned on in
+ * tcp_data_queue when everything is OK.
+ */
+int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+ struct tcphdr *th, unsigned len)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int queued;
+ u32 flg;
+
+ /*
+ * Header prediction.
+ * The code follows the one in the famous
+ * "30 instruction TCP receive" Van Jacobson mail.
+ *
+ * Van's trick is to deposit buffers into socket queue
+ * on a device interrupt, to call tcp_recv function
+ * on the receive process context and checksum and copy
+ * the buffer to user space. smart...
+ *
+ * Our current scheme is not silly either but we take the
+ * extra cost of the net_bh soft interrupt processing...
+ * We do checksum and copy also but from device to kernel.
+ */
+
+ /*
+ * RFC1323: H1. Apply PAWS check first.
+ */
+ if (tcp_fast_parse_options(sk, th, tp)) {
+ if (tp->saw_tstamp) {
+ if (tcp_paws_discard(tp, th, len)) {
+ tcp_statistics.TcpInErrs++;
+ if (!th->rst) {
+ tcp_send_ack(sk);
+ goto discard;
+ }
+ }
+ tcp_replace_ts_recent(sk, tp,
+ TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->end_seq);
+ }
+ }
+
+ flg = *(((u32 *)th) + 3) & ~htonl(0xFC8 << 16);
+
+ /* pred_flags is 0xS?10 << 16 + snd_wnd
+ * if header_predition is to be made
+ * 'S' will always be tp->tcp_header_len >> 2
+ * '?' will be 0 else it will be !0
+ * (when there are holes in the receive
+ * space for instance)
+ * PSH flag is ignored.
+ */
+
+ if (flg == tp->pred_flags && TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+ if (len <= th->doff*4) {
+ /* Bulk data transfer: sender */
+ if (len == th->doff*4) {
+ tcp_ack(sk, th, TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->ack_seq, len);
+ kfree_skb(skb);
+ tcp_data_snd_check(sk);
+ return 0;
+ } else { /* Header too small */
+ tcp_statistics.TcpInErrs++;
+ goto discard;
+ }
+ } else if (TCP_SKB_CB(skb)->ack_seq == tp->snd_una &&
+ atomic_read(&sk->rmem_alloc) <= sk->rcvbuf) {
+ /* Bulk data transfer: receiver */
+ __skb_pull(skb,th->doff*4);
+
+ tcp_measure_rcv_mss(sk, skb);
+
+ /* DO NOT notify forward progress here.
+ * It saves dozen of CPU instructions in fast path. --ANK
+ */
+ __skb_queue_tail(&sk->receive_queue, skb);
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+
+ /* FIN bit check is not done since if FIN is set in
+ * this frame, the pred_flags won't match up. -DaveM
+ */
+ sk->data_ready(sk, 0);
+ tcp_delack_estimator(tp);
+
+ tcp_remember_ack(tp, th, skb);
+
+ __tcp_ack_snd_check(sk);
+ return 0;
+ }
+ }
+
+ /*
+ * Standard slow path.
+ */
+
+ if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
+ /* RFC793, page 37: "In all states except SYN-SENT, all reset
+ * (RST) segments are validated by checking their SEQ-fields."
+ * And page 69: "If an incoming segment is not acceptable,
+ * an acknowledgment should be sent in reply (unless the RST bit
+ * is set, if so drop the segment and return)".
+ */
+ if (th->rst)
+ goto discard;
+ if (after(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+ SOCK_DEBUG(sk, "seq:%d end:%d wup:%d wnd:%d\n",
+ TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
+ tp->rcv_wup, tp->rcv_wnd);
+ }
+ tcp_send_ack(sk);
+ goto discard;
+ }
+
+ if(th->syn && TCP_SKB_CB(skb)->seq != tp->syn_seq) {
+ SOCK_DEBUG(sk, "syn in established state\n");
+ tcp_statistics.TcpInErrs++;
+ tcp_reset(sk);
+ return 1;
+ }
+
+ if(th->rst) {
+ tcp_reset(sk);
+ goto discard;
+ }
+
+ if(th->ack)
+ tcp_ack(sk, th, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->ack_seq, len);
+
+ /* Process urgent data. */
+ tcp_urg(sk, th, len);
+
+ /* step 7: process the segment text */
+ queued = tcp_data(skb, sk, len);
+
+ /* This must be after tcp_data() does the skb_pull() to
+ * remove the header size from skb->len.
+ *
+ * Dave!!! Phrase above (and all about rcv_mss) has
+ * nothing to do with reality. rcv_mss must measure TOTAL
+ * size, including sacks, IP options etc. Hence, measure_rcv_mss
+ * must occure before pulling etc, otherwise it will flap
+ * like hell. Even putting it before tcp_data is wrong,
+ * it should use skb->tail - skb->nh.raw instead.
+ * --ANK (980805)
+ *
+ * BTW I broke it. Now all TCP options are handled equally
+ * in mss_clamp calculations (i.e. ignored, rfc1122),
+ * and mss_cache does include all of them (i.e. tstamps)
+ * except for sacks, to calulate effective mss faster.
+ * --ANK (980805)
+ */
+ tcp_measure_rcv_mss(sk, skb);
+
+ /* Be careful, tcp_data() may have put this into TIME_WAIT. */
+ if(sk->state != TCP_CLOSE) {
+ tcp_data_snd_check(sk);
+ tcp_ack_snd_check(sk);
+ }
+
+ if (!queued) {
+ discard:
+ kfree_skb(skb);
+ }
+
+ return 0;
+}
+
+/*
+ * Process an incoming SYN or SYN-ACK for SYN_RECV sockets represented
+ * as an open_request.
+ */
+
+struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
+ struct open_request *req)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ u32 flg;
+
+ /* assumption: the socket is not in use.
+ * as we checked the user count on tcp_rcv and we're
+ * running from a soft interrupt.
+ */
+
+ /* Check for syn retransmission */
+ flg = *(((u32 *)skb->h.th) + 3);
+
+ flg &= __constant_htonl(0x00170000);
+ /* Only SYN set? */
+ if (flg == __constant_htonl(0x00020000)) {
+ if (TCP_SKB_CB(skb)->seq == req->rcv_isn) {
+ /* retransmited syn.
+ */
+ req->class->rtx_syn_ack(sk, req);
+ return NULL;
+ } else {
+ return sk; /* Pass new SYN to the listen socket. */
+ }
+ }
+
+ /* We know it's an ACK here */
+ if (req->sk) {
+ /* socket already created but not
+ * yet accepted()...
+ */
+ sk = req->sk;
+ } else {
+ /* In theory the packet could be for a cookie, but
+ * TIME_WAIT should guard us against this.
+ * XXX: Nevertheless check for cookies?
+ * This sequence number check is done again later,
+ * but we do it here to prevent syn flood attackers
+ * from creating big SYN_RECV sockets.
+ */
+ if (!between(TCP_SKB_CB(skb)->ack_seq, req->snt_isn, req->snt_isn+1) ||
+ !between(TCP_SKB_CB(skb)->seq, req->rcv_isn,
+ req->rcv_isn+1+req->rcv_wnd)) {
+ req->class->send_reset(skb);
+ return NULL;
+ }
+
+ sk = tp->af_specific->syn_recv_sock(sk, skb, req, NULL);
+ tcp_dec_slow_timer(TCP_SLT_SYNACK);
+ if (sk == NULL)
+ return NULL;
+
+ req->expires = 0UL;
+ req->sk = sk;
+ }
+ skb_orphan(skb);
+ skb_set_owner_r(skb, sk);
+ return sk;
+}
+
+/*
+ * This function implements the receiving procedure of RFC 793 for
+ * all states except ESTABLISHED and TIME_WAIT.
+ * It's called from both tcp_v4_rcv and tcp_v6_rcv and should be
+ * address independent.
+ */
+
+int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
+ struct tcphdr *th, unsigned len)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int queued = 0;
+
+ switch (sk->state) {
+ case TCP_CLOSE:
+ /* When state == CLOSED, hash lookup always fails.
+ *
+ * But, there is a back door, the backlog queue.
+ * If we have a sequence of packets in the backlog
+ * during __release_sock() which have a sequence such
+ * that:
+ * packet X causes entry to TCP_CLOSE state
+ * ...
+ * packet X + N has FIN bit set
+ *
+ * We report a (luckily) harmless error in this case.
+ * The issue is that backlog queue processing bypasses
+ * any hash lookups (we know which socket packets are for).
+ * The correct behavior here is what 2.0.x did, since
+ * a TCP_CLOSE socket does not exist. Drop the frame
+ * and send a RST back to the other end.
+ */
+ return 1;
+
+ case TCP_LISTEN:
+ /* These use the socket TOS..
+ * might want to be the received TOS
+ */
+ if(th->ack)
+ return 1;
+
+ if(th->syn) {
+ if(tp->af_specific->conn_request(sk, skb, 0) < 0)
+ return 1;
+
+ /* Now we have several options: In theory there is
+ * nothing else in the frame. KA9Q has an option to
+ * send data with the syn, BSD accepts data with the
+ * syn up to the [to be] advertised window and
+ * Solaris 2.1 gives you a protocol error. For now
+ * we just ignore it, that fits the spec precisely
+ * and avoids incompatibilities. It would be nice in
+ * future to drop through and process the data.
+ *
+ * Now that TTCP is starting to be used we ought to
+ * queue this data.
+ * But, this leaves one open to an easy denial of
+ * service attack, and SYN cookies can't defend
+ * against this problem. So, we drop the data
+ * in the interest of security over speed.
+ */
+ goto discard;
+ }
+
+ goto discard;
+ break;
+
+ case TCP_SYN_SENT:
+ /* SYN sent means we have to look for a suitable ack and
+ * either reset for bad matches or go to connected.
+ * The SYN_SENT case is unusual and should
+ * not be in line code. [AC]
+ */
+ if(th->ack) {
+ /* rfc793:
+ * "If the state is SYN-SENT then
+ * first check the ACK bit
+ * If the ACK bit is set
+ * If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send
+ * a reset (unless the RST bit is set, if so drop
+ * the segment and return)"
+ *
+ * I cite this place to emphasize one essential
+ * detail, this check is different of one
+ * in established state: SND.UNA <= SEG.ACK <= SND.NXT.
+ * SEG_ACK == SND.UNA == ISS is invalid in SYN-SENT,
+ * because we have no previous data sent before SYN.
+ * --ANK(990513)
+ *
+ * We do not send data with SYN, so that RFC-correct
+ * test reduces to:
+ */
+ if (sk->zapped ||
+ TCP_SKB_CB(skb)->ack_seq != tp->snd_nxt)
+ return 1;
+
+ /* Now ACK is acceptable.
+ *
+ * "If the RST bit is set
+ * If the ACK was acceptable then signal the user "error:
+ * connection reset", drop the segment, enter CLOSED state,
+ * delete TCB, and return."
+ */
+
+ if (th->rst) {
+ tcp_reset(sk);
+ goto discard;
+ }
+
+ /* rfc793:
+ * "fifth, if neither of the SYN or RST bits is set then
+ * drop the segment and return."
+ *
+ * See note below!
+ * --ANK(990513)
+ */
+
+ if (!th->syn)
+ goto discard;
+
+ /* rfc793:
+ * "If the SYN bit is on ...
+ * are acceptable then ...
+ * (our SYN has been ACKed), change the connection
+ * state to ESTABLISHED..."
+ *
+ * Do you see? SYN-less ACKs in SYN-SENT state are
+ * completely ignored.
+ *
+ * The bug causing stalled SYN-SENT sockets
+ * was here: tcp_ack advanced snd_una and canceled
+ * retransmit timer, so that bare ACK received
+ * in SYN-SENT state (even with invalid ack==ISS,
+ * because tcp_ack check is too weak for SYN-SENT)
+ * causes moving socket to invalid semi-SYN-SENT,
+ * semi-ESTABLISHED state and connection hangs.
+ *
+ * There exist buggy stacks, which really send
+ * such ACKs: f.e. 202.226.91.94 (okigate.oki.co.jp)
+ * Actually, if this host did not try to get something
+ * from ftp.inr.ac.ru I'd never find this bug 8)
+ *
+ * --ANK (990514)
+ */
+
+ tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+ tcp_ack(sk,th, TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->ack_seq, len);
+
+ /* Ok.. it's good. Set up sequence numbers and
+ * move to established.
+ */
+ tp->rcv_nxt = TCP_SKB_CB(skb)->seq+1;
+ tp->rcv_wup = TCP_SKB_CB(skb)->seq+1;
+
+ /* RFC1323: The window in SYN & SYN/ACK segments is
+ * never scaled.
+ */
+ tp->snd_wnd = htons(th->window);
+ tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+ tp->snd_wl2 = TCP_SKB_CB(skb)->ack_seq;
+ tp->fin_seq = TCP_SKB_CB(skb)->seq;
+
+ tcp_set_state(sk, TCP_ESTABLISHED);
+ tcp_parse_options(sk, th, tp, 0);
+
+ if (tp->wscale_ok == 0) {
+ tp->snd_wscale = tp->rcv_wscale = 0;
+ tp->window_clamp = min(tp->window_clamp,65535);
+ }
+
+ if (tp->tstamp_ok) {
+ tp->tcp_header_len =
+ sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
+ } else
+ tp->tcp_header_len = sizeof(struct tcphdr);
+ if (tp->saw_tstamp) {
+ tp->ts_recent = tp->rcv_tsval;
+ tp->ts_recent_stamp = tcp_time_stamp;
+ }
+
+ /* Can't be earlier, doff would be wrong. */
+ tcp_send_ack(sk);
+
+ sk->dport = th->source;
+ tp->copied_seq = tp->rcv_nxt;
+
+ if(!sk->dead) {
+ sk->state_change(sk);
+ sock_wake_async(sk->socket, 0);
+ }
+ } else {
+ if(th->syn && !th->rst) {
+ /* The previous version of the code
+ * checked for "connecting to self"
+ * here. that check is done now in
+ * tcp_connect.
+ */
+ tcp_set_state(sk, TCP_SYN_RECV);
+ tcp_parse_options(sk, th, tp, 0);
+ if (tp->saw_tstamp) {
+ tp->ts_recent = tp->rcv_tsval;
+ tp->ts_recent_stamp = tcp_time_stamp;
+ }
+
+ tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
+ tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
+
+ /* RFC1323: The window in SYN & SYN/ACK segments is
+ * never scaled.
+ */
+ tp->snd_wnd = htons(th->window);
+ tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+
+ tcp_send_synack(sk);
+ } else
+ break;
+ }
+
+ /* tp->tcp_header_len and tp->mss_clamp
+ probably changed, synchronize mss.
+ */
+ tcp_sync_mss(sk, tp->pmtu_cookie);
+ tp->rcv_mss = tp->mss_cache;
+
+ if (sk->state == TCP_SYN_RECV)
+ goto discard;
+
+ goto step6;
+ }
+
+ /* Parse the tcp_options present on this header.
+ * By this point we really only expect timestamps.
+ * Note that this really has to be here and not later for PAWS
+ * (RFC1323) to work.
+ */
+ if (tcp_fast_parse_options(sk, th, tp)) {
+ /* NOTE: assumes saw_tstamp is never set if we didn't
+ * negotiate the option. tcp_fast_parse_options() must
+ * guarantee this.
+ */
+ if (tp->saw_tstamp) {
+ if (tcp_paws_discard(tp, th, len)) {
+ tcp_statistics.TcpInErrs++;
+ if (!th->rst) {
+ tcp_send_ack(sk);
+ goto discard;
+ }
+ }
+ tcp_replace_ts_recent(sk, tp,
+ TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->end_seq);
+ }
+ }
+
+ /* The silly FIN test here is necessary to see an advancing ACK in
+ * retransmitted FIN frames properly. Consider the following sequence:
+ *
+ * host1 --> host2 FIN XSEQ:XSEQ(0) ack YSEQ
+ * host2 --> host1 FIN YSEQ:YSEQ(0) ack XSEQ
+ * host1 --> host2 XSEQ:XSEQ(0) ack YSEQ+1
+ * host2 --> host1 FIN YSEQ:YSEQ(0) ack XSEQ+1 (fails tcp_sequence test)
+ *
+ * At this point the connection will deadlock with host1 believing
+ * that his FIN is never ACK'd, and thus it will retransmit it's FIN
+ * forever. The following fix is from Taral (taral@taral.net).
+ */
+
+ /* step 1: check sequence number */
+ if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq) &&
+ !(th->fin && TCP_SKB_CB(skb)->end_seq == tp->rcv_nxt)) {
+ if (!th->rst) {
+ tcp_send_ack(sk);
+ }
+ goto discard;
+ }
+
+ /* step 2: check RST bit */
+ if(th->rst) {
+ tcp_reset(sk);
+ goto discard;
+ }
+
+ /* step 3: check security and precedence [ignored] */
+
+ /* step 4:
+ *
+ * Check for a SYN, and ensure it matches the SYN we were
+ * first sent. We have to handle the rather unusual (but valid)
+ * sequence that KA9Q derived products may generate of
+ *
+ * SYN
+ * SYN|ACK Data
+ * ACK (lost)
+ * SYN|ACK Data + More Data
+ * .. we must ACK not RST...
+ *
+ * We keep syn_seq as the sequence space occupied by the
+ * original syn.
+ */
+
+ if (th->syn && TCP_SKB_CB(skb)->seq != tp->syn_seq) {
+ tcp_reset(sk);
+ return 1;
+ }
+
+ /* step 5: check the ACK field */
+ if (th->ack) {
+ int acceptable = tcp_ack(sk, th, TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->ack_seq, len);
+
+ switch(sk->state) {
+ case TCP_SYN_RECV:
+ if (acceptable) {
+ tcp_set_state(sk, TCP_ESTABLISHED);
+ sk->dport = th->source;
+ tp->copied_seq = tp->rcv_nxt;
+
+ if(!sk->dead)
+ sk->state_change(sk);
+
+ tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
+ tp->snd_wnd = htons(th->window) << tp->snd_wscale;
+ tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+ tp->snd_wl2 = TCP_SKB_CB(skb)->ack_seq;
+
+ } else {
+ SOCK_DEBUG(sk, "bad ack\n");
+ return 1;
+ }
+ break;
+
+ case TCP_FIN_WAIT1:
+ if (tp->snd_una == tp->write_seq) {
+ sk->shutdown |= SEND_SHUTDOWN;
+ tcp_set_state(sk, TCP_FIN_WAIT2);
+ if (!sk->dead)
+ sk->state_change(sk);
+ else
+ tcp_reset_msl_timer(sk, TIME_CLOSE, sysctl_tcp_fin_timeout);
+ }
+ break;
+
+ case TCP_CLOSING:
+ if (tp->snd_una == tp->write_seq) {
+ tcp_time_wait(sk);
+ goto discard;
+ }
+ break;
+
+ case TCP_LAST_ACK:
+ if (tp->snd_una == tp->write_seq) {
+ sk->shutdown = SHUTDOWN_MASK;
+ tcp_set_state(sk,TCP_CLOSE);
+ if (!sk->dead)
+ sk->state_change(sk);
+ goto discard;
+ }
+ break;
+ }
+ } else
+ goto discard;
+
+step6:
+ /* step 6: check the URG bit */
+ tcp_urg(sk, th, len);
+
+ /* step 7: process the segment text */
+ switch (sk->state) {
+ case TCP_CLOSE_WAIT:
+ case TCP_CLOSING:
+ if (!before(TCP_SKB_CB(skb)->seq, tp->fin_seq))
+ break;
+
+ case TCP_FIN_WAIT1:
+ case TCP_FIN_WAIT2:
+ /* RFC 793 says to queue data in these states,
+ * RFC 1122 says we MUST send a reset.
+ * BSD 4.4 also does reset.
+ */
+ if ((sk->shutdown & RCV_SHUTDOWN) && sk->dead) {
+ if (after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
+ tcp_reset(sk);
+ return 1;
+ }
+ }
+
+ case TCP_ESTABLISHED:
+ queued = tcp_data(skb, sk, len);
+
+ /* This must be after tcp_data() does the skb_pull() to
+ * remove the header size from skb->len.
+ */
+ tcp_measure_rcv_mss(sk, skb);
+ break;
+ }
+
+ tcp_data_snd_check(sk);
+ tcp_ack_snd_check(sk);
+
+ if (!queued) {
+discard:
+ kfree_skb(skb);
+ }
+ return 0;
+}
diff --git a/pfinet/linux-src/net/ipv4/tcp_ipv4.c b/pfinet/linux-src/net/ipv4/tcp_ipv4.c
new file mode 100644
index 00000000..c2c78365
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/tcp_ipv4.c
@@ -0,0 +1,2044 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id: tcp_ipv4.c,v 1.175.2.10 1999/08/13 16:14:35 davem Exp $
+ *
+ * IPv4 specific functions
+ *
+ *
+ * code split from:
+ * linux/ipv4/tcp.c
+ * linux/ipv4/tcp_input.c
+ * linux/ipv4/tcp_output.c
+ *
+ * See tcp.c for author information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Changes:
+ * David S. Miller : New socket lookup architecture.
+ * This code is dedicated to John Dyson.
+ * David S. Miller : Change semantics of established hash,
+ * half is devoted to TIME_WAIT sockets
+ * and the rest go in the other half.
+ * Andi Kleen : Add support for syncookies and fixed
+ * some bugs: ip options weren't passed to
+ * the TCP layer, missed a check for an ACK bit.
+ * Andi Kleen : Implemented fast path mtu discovery.
+ * Fixed many serious bugs in the
+ * open_request handling and moved
+ * most of it into the af independent code.
+ * Added tail drop and some other bugfixes.
+ * Added new listen sematics.
+ * Mike McLagan : Routing by source
+ * Juan Jose Ciarlante: ip_dynaddr bits
+ * Andi Kleen: various fixes.
+ * Vitaly E. Lavrov : Transparent proxy revived after year coma.
+ * Andi Kleen : Fix new listen.
+ * Andi Kleen : Fix accept error reporting.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/ipsec.h>
+
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <net/ipv6.h>
+
+#include <asm/segment.h>
+
+#include <linux/inet.h>
+#include <linux/stddef.h>
+
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_syncookies;
+extern int sysctl_ip_dynaddr;
+extern __u32 sysctl_wmem_max;
+extern __u32 sysctl_rmem_max;
+
+/* Check TCP sequence numbers in ICMP packets. */
+#define ICMP_MIN_LENGTH 8
+
+/* Socket used for sending RSTs */
+struct inode tcp_inode;
+struct socket *tcp_socket=&tcp_inode.u.socket_i;
+
+static void tcp_v4_send_reset(struct sk_buff *skb);
+
+void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
+ struct sk_buff *skb);
+
+/* This is for sockets with full identity only. Sockets here will always
+ * be without wildcards and will have the following invariant:
+ * TCP_ESTABLISHED <= sk->state < TCP_CLOSE
+ *
+ * First half of the table is for sockets not in TIME_WAIT, second half
+ * is for TIME_WAIT sockets only.
+ */
+struct sock *tcp_established_hash[TCP_HTABLE_SIZE];
+
+/* Ok, let's try this, I give up, we do need a local binding
+ * TCP hash as well as the others for fast bind/connect.
+ */
+struct tcp_bind_bucket *tcp_bound_hash[TCP_BHTABLE_SIZE];
+
+/* All sockets in TCP_LISTEN state will be in here. This is the only table
+ * where wildcard'd TCP sockets can exist. Hash function here is just local
+ * port number.
+ */
+struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE];
+
+/* Register cache. */
+struct sock *tcp_regs[TCP_NUM_REGS];
+
+/*
+ * This array holds the first and last local port number.
+ * For high-usage systems, use sysctl to change this to
+ * 32768-61000
+ */
+int sysctl_local_port_range[2] = { 1024, 4999 };
+int tcp_port_rover = (1024 - 1);
+
+static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport,
+ __u32 faddr, __u16 fport)
+{
+ return ((laddr ^ lport) ^ (faddr ^ fport)) & ((TCP_HTABLE_SIZE/2) - 1);
+}
+
+static __inline__ int tcp_sk_hashfn(struct sock *sk)
+{
+ __u32 laddr = sk->rcv_saddr;
+ __u16 lport = sk->num;
+ __u32 faddr = sk->daddr;
+ __u16 fport = sk->dport;
+
+ return tcp_hashfn(laddr, lport, faddr, fport);
+}
+
+/* Allocate and initialize a new TCP local port bind bucket.
+ * Always runs inside the socket hashing lock.
+ */
+struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum)
+{
+ struct tcp_bind_bucket *tb;
+
+ tb = kmem_cache_alloc(tcp_bucket_cachep, SLAB_ATOMIC);
+ if(tb != NULL) {
+ struct tcp_bind_bucket **head =
+ &tcp_bound_hash[tcp_bhashfn(snum)];
+ tb->port = snum;
+ tb->fastreuse = 0;
+ tb->owners = NULL;
+ if((tb->next = *head) != NULL)
+ tb->next->pprev = &tb->next;
+ *head = tb;
+ tb->pprev = head;
+ }
+ return tb;
+}
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/* Ensure that the bound bucket for the port exists.
+ * Return 0 and bump bucket reference count on success.
+ *
+ * Must run in a BH atomic section.
+ */
+static __inline__ int __tcp_bucket_check(unsigned short snum)
+{
+ struct tcp_bind_bucket *tb;
+
+ tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ for( ; (tb && (tb->port != snum)); tb = tb->next)
+ ;
+ if (tb == NULL) {
+ if ((tb = tcp_bucket_create(snum)) == NULL)
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+ struct tcp_bind_bucket *tb = (struct tcp_bind_bucket *)sk->prev;
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (child->num != sk->num) {
+ unsigned short snum = ntohs(child->num);
+ for(tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ tb && tb->port != snum;
+ tb = tb->next)
+ ;
+ if (tb == NULL)
+ tb = (struct tcp_bind_bucket *)sk->prev;
+ }
+#endif
+ if ((child->bind_next = tb->owners) != NULL)
+ tb->owners->bind_pprev = &child->bind_next;
+ tb->owners = child;
+ child->bind_pprev = &tb->owners;
+ child->prev = (struct sock *) tb;
+}
+
+__inline__ void tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+ SOCKHASH_LOCK();
+ __tcp_inherit_port(sk, child);
+ SOCKHASH_UNLOCK();
+}
+
+/* Obtain a reference to a local port for the given sock,
+ * if snum is zero it means select any available local port.
+ */
+static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
+{
+ struct tcp_bind_bucket *tb;
+
+ SOCKHASH_LOCK();
+ if (snum == 0) {
+ int rover = tcp_port_rover;
+ int low = sysctl_local_port_range[0];
+ int high = sysctl_local_port_range[1];
+ int remaining = (high - low) + 1;
+
+ do { rover++;
+ if ((rover < low) || (rover > high))
+ rover = low;
+ tb = tcp_bound_hash[tcp_bhashfn(rover)];
+ for ( ; tb; tb = tb->next)
+ if (tb->port == rover)
+ goto next;
+ break;
+ next:
+ } while (--remaining > 0);
+ tcp_port_rover = rover;
+
+ /* Exhausted local port range during search? */
+ if (remaining <= 0)
+ goto fail;
+
+ /* OK, here is the one we will use. */
+ snum = rover;
+ tb = NULL;
+ } else {
+ for (tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ tb != NULL;
+ tb = tb->next)
+ if (tb->port == snum)
+ break;
+ }
+ if (tb != NULL && tb->owners != NULL) {
+ if (tb->fastreuse != 0 && sk->reuse != 0) {
+ goto success;
+ } else {
+ struct sock *sk2 = tb->owners;
+ int sk_reuse = sk->reuse;
+
+ for( ; sk2 != NULL; sk2 = sk2->bind_next) {
+ if (sk->bound_dev_if == sk2->bound_dev_if) {
+ if (!sk_reuse ||
+ !sk2->reuse ||
+ sk2->state == TCP_LISTEN) {
+ if (!sk2->rcv_saddr ||
+ !sk->rcv_saddr ||
+ (sk2->rcv_saddr == sk->rcv_saddr))
+ break;
+ }
+ }
+ }
+ /* If we found a conflict, fail. */
+ if (sk2 != NULL)
+ goto fail;
+ }
+ }
+ if (tb == NULL &&
+ (tb = tcp_bucket_create(snum)) == NULL)
+ goto fail;
+ if (tb->owners == NULL) {
+ if (sk->reuse && sk->state != TCP_LISTEN)
+ tb->fastreuse = 1;
+ else
+ tb->fastreuse = 0;
+ } else if (tb->fastreuse &&
+ ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
+ tb->fastreuse = 0;
+success:
+ sk->num = snum;
+ if ((sk->bind_next = tb->owners) != NULL)
+ tb->owners->bind_pprev = &sk->bind_next;
+ tb->owners = sk;
+ sk->bind_pprev = &tb->owners;
+ sk->prev = (struct sock *) tb;
+
+ SOCKHASH_UNLOCK();
+ return 0;
+
+fail:
+ SOCKHASH_UNLOCK();
+ return 1;
+}
+
+/* Get rid of any references to a local port held by the
+ * given sock.
+ */
+__inline__ void __tcp_put_port(struct sock *sk)
+{
+ struct tcp_bind_bucket *tb;
+
+ tb = (struct tcp_bind_bucket *) sk->prev;
+ if (sk->bind_next)
+ sk->bind_next->bind_pprev = sk->bind_pprev;
+ *(sk->bind_pprev) = sk->bind_next;
+ sk->prev = NULL;
+ if (tb->owners == NULL) {
+ if (tb->next)
+ tb->next->pprev = tb->pprev;
+ *(tb->pprev) = tb->next;
+ kmem_cache_free(tcp_bucket_cachep, tb);
+ }
+}
+
+void tcp_put_port(struct sock *sk)
+{
+ SOCKHASH_LOCK();
+ __tcp_put_port(sk);
+ SOCKHASH_UNLOCK();
+}
+
+static __inline__ void __tcp_v4_hash(struct sock *sk)
+{
+ struct sock **skp;
+
+ if(sk->state == TCP_LISTEN)
+ skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
+ else
+ skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
+
+ if((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+ *skp = sk;
+ sk->pprev = skp;
+}
+
+static void tcp_v4_hash(struct sock *sk)
+{
+ if (sk->state != TCP_CLOSE) {
+ SOCKHASH_LOCK();
+ __tcp_v4_hash(sk);
+ SOCKHASH_UNLOCK();
+ }
+}
+
+static void tcp_v4_unhash(struct sock *sk)
+{
+ SOCKHASH_LOCK();
+ if(sk->pprev) {
+ if(sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ tcp_reg_zap(sk);
+ __tcp_put_port(sk);
+ }
+ SOCKHASH_UNLOCK();
+}
+
+/* Don't inline this cruft. Here are some nice properties to
+ * exploit here. The BSD API does not allow a listening TCP
+ * to specify the remote port nor the remote address for the
+ * connection. So always assume those are both wildcarded
+ * during the search since they can never be otherwise.
+ */
+static struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, int dif)
+{
+ struct sock *sk;
+ struct sock *result = NULL;
+ int score, hiscore;
+
+ hiscore=0;
+ for(sk = tcp_listening_hash[tcp_lhashfn(hnum)]; sk; sk = sk->next) {
+ if(sk->num == hnum) {
+ __u32 rcv_saddr = sk->rcv_saddr;
+
+ score = 1;
+ if(rcv_saddr) {
+ if (rcv_saddr != daddr)
+ continue;
+ score++;
+ }
+ if (sk->bound_dev_if) {
+ if (sk->bound_dev_if != dif)
+ continue;
+ score++;
+ }
+ if (score == 3)
+ return sk;
+ if (score > hiscore) {
+ hiscore = score;
+ result = sk;
+ }
+ }
+ }
+ return result;
+}
+
+/* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
+ * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
+ * It is assumed that this code only gets called from within NET_BH.
+ */
+static inline struct sock *__tcp_v4_lookup(struct tcphdr *th,
+ u32 saddr, u16 sport,
+ u32 daddr, u16 dport, int dif)
+{
+ TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
+ __u16 hnum = ntohs(dport);
+ __u32 ports = TCP_COMBINED_PORTS(sport, hnum);
+ struct sock *sk;
+ int hash;
+
+ /* Check TCP register quick cache first. */
+ sk = TCP_RHASH(sport);
+ if(sk && TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
+ goto hit;
+
+ /* Optimize here for direct hit, only listening connections can
+ * have wildcards anyways.
+ */
+ hash = tcp_hashfn(daddr, hnum, saddr, sport);
+ for(sk = tcp_established_hash[hash]; sk; sk = sk->next) {
+ if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif)) {
+ if (sk->state == TCP_ESTABLISHED)
+ TCP_RHASH(sport) = sk;
+ goto hit; /* You sunk my battleship! */
+ }
+ }
+ /* Must check for a TIME_WAIT'er before going to listener hash. */
+ for(sk = tcp_established_hash[hash+(TCP_HTABLE_SIZE/2)]; sk; sk = sk->next)
+ if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
+ goto hit;
+ sk = tcp_v4_lookup_listener(daddr, hnum, dif);
+hit:
+ return sk;
+}
+
+__inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
+{
+ return __tcp_v4_lookup(0, saddr, sport, daddr, dport, dif);
+}
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/* Cleaned up a little and adapted to new bind bucket scheme.
+ * Oddly, this should increase performance here for
+ * transparent proxy, as tests within the inner loop have
+ * been eliminated. -DaveM
+ */
+static struct sock *tcp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
+ unsigned short rnum, unsigned long laddr,
+ struct device *dev, unsigned short pnum,
+ int dif)
+{
+ struct sock *s, *result = NULL;
+ int badness = -1;
+ u32 paddr = 0;
+ unsigned short hnum = ntohs(num);
+ unsigned short hpnum = ntohs(pnum);
+ int firstpass = 1;
+
+ if(dev && dev->ip_ptr) {
+ struct in_device *idev = dev->ip_ptr;
+
+ if(idev->ifa_list)
+ paddr = idev->ifa_list->ifa_local;
+ }
+
+ /* This code must run only from NET_BH. */
+ {
+ struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(hnum)];
+ for( ; (tb && tb->port != hnum); tb = tb->next)
+ ;
+ if(tb == NULL)
+ goto next;
+ s = tb->owners;
+ }
+pass2:
+ for(; s; s = s->bind_next) {
+ int score = 0;
+ if(s->rcv_saddr) {
+ if((s->num != hpnum || s->rcv_saddr != paddr) &&
+ (s->num != hnum || s->rcv_saddr != laddr))
+ continue;
+ score++;
+ }
+ if(s->daddr) {
+ if(s->daddr != raddr)
+ continue;
+ score++;
+ }
+ if(s->dport) {
+ if(s->dport != rnum)
+ continue;
+ score++;
+ }
+ if(s->bound_dev_if) {
+ if(s->bound_dev_if != dif)
+ continue;
+ score++;
+ }
+ if(score == 4 && s->num == hnum) {
+ result = s;
+ goto gotit;
+ } else if(score > badness && (s->num == hpnum || s->rcv_saddr)) {
+ result = s;
+ badness = score;
+ }
+ }
+next:
+ if(firstpass--) {
+ struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(hpnum)];
+ for( ; (tb && tb->port != hpnum); tb = tb->next)
+ ;
+ if(tb) {
+ s = tb->owners;
+ goto pass2;
+ }
+ }
+gotit:
+ return result;
+}
+#endif /* CONFIG_IP_TRANSPARENT_PROXY */
+
+static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
+{
+ return secure_tcp_sequence_number(sk->saddr, sk->daddr,
+ skb->h.th->dest,
+ skb->h.th->source);
+}
+
+/* Check that a TCP address is unique, don't allow multiple
+ * connects to/from the same address. Actually we can optimize
+ * quite a bit, since the socket about to connect is still
+ * in TCP_CLOSE, a tcp_bind_bucket for the local port he will
+ * use will exist, with a NULL owners list. So check for that.
+ * The good_socknum and verify_bind scheme we use makes this
+ * work.
+ */
+static int tcp_v4_unique_address(struct sock *sk)
+{
+ struct tcp_bind_bucket *tb;
+ unsigned short snum = sk->num;
+ int retval = 1;
+
+ /* Freeze the hash while we snoop around. */
+ SOCKHASH_LOCK();
+ tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ for(; tb; tb = tb->next) {
+ if(tb->port == snum && tb->owners != NULL) {
+ /* Almost certainly the re-use port case, search the real hashes
+ * so it actually scales.
+ */
+ sk = __tcp_v4_lookup(NULL, sk->daddr, sk->dport,
+ sk->rcv_saddr, htons(snum),
+ sk->bound_dev_if);
+ if((sk != NULL) && (sk->state != TCP_LISTEN))
+ retval = 0;
+ break;
+ }
+ }
+ SOCKHASH_UNLOCK();
+ return retval;
+}
+
+/* This will initiate an outgoing connection. */
+int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
+ struct sk_buff *buff;
+ struct rtable *rt;
+ u32 daddr, nexthop;
+ int tmp;
+
+ if (sk->state != TCP_CLOSE)
+ return(-EISCONN);
+
+ /* Don't allow a double connect. */
+ if (sk->daddr)
+ return -EINVAL;
+
+ if (addr_len < sizeof(struct sockaddr_in))
+ return(-EINVAL);
+
+ if (usin->sin_family != AF_INET) {
+ static int complained;
+ if (usin->sin_family)
+ return(-EAFNOSUPPORT);
+ if (!complained++)
+ printk(KERN_DEBUG "%s forgot to set AF_INET in " __FUNCTION__ "\n", current->comm);
+ }
+
+ nexthop = daddr = usin->sin_addr.s_addr;
+ if (sk->opt && sk->opt->srr) {
+ if (daddr == 0)
+ return -EINVAL;
+ nexthop = sk->opt->faddr;
+ }
+
+ tmp = ip_route_connect(&rt, nexthop, sk->saddr,
+ RT_TOS(sk->ip_tos)|RTO_CONN|sk->localroute, sk->bound_dev_if);
+ if (tmp < 0)
+ return tmp;
+
+ if (rt->rt_flags&(RTCF_MULTICAST|RTCF_BROADCAST)) {
+ ip_rt_put(rt);
+ return -ENETUNREACH;
+ }
+
+ dst_release(xchg(&sk->dst_cache, rt));
+
+ buff = sock_wmalloc(sk, (MAX_HEADER + sk->prot->max_header),
+ 0, GFP_KERNEL);
+
+ if (buff == NULL)
+ return -ENOBUFS;
+
+ /* Socket has no identity, so lock_sock() is useless. Also
+ * since state==TCP_CLOSE (checked above) the socket cannot
+ * possibly be in the hashes. TCP hash locking is only
+ * needed while checking quickly for a unique address.
+ * However, the socket does need to be (and is) locked
+ * in tcp_connect().
+ * Perhaps this addresses all of ANK's concerns. 8-) -DaveM
+ */
+ sk->dport = usin->sin_port;
+ sk->daddr = rt->rt_dst;
+ if (sk->opt && sk->opt->srr)
+ sk->daddr = daddr;
+ if (!sk->saddr)
+ sk->saddr = rt->rt_src;
+ sk->rcv_saddr = sk->saddr;
+
+ if (!tcp_v4_unique_address(sk)) {
+ kfree_skb(buff);
+ sk->daddr = 0;
+ return -EADDRNOTAVAIL;
+ }
+
+ tp->write_seq = secure_tcp_sequence_number(sk->saddr, sk->daddr,
+ sk->sport, usin->sin_port);
+
+ tp->ext_header_len = 0;
+ if (sk->opt)
+ tp->ext_header_len = sk->opt->optlen;
+
+ /* Reset mss clamp */
+ tp->mss_clamp = ~0;
+
+ if (!ip_dont_fragment(sk, &rt->u.dst) &&
+ rt->u.dst.pmtu > 576 && rt->rt_dst != rt->rt_gateway) {
+ /* Clamp mss at maximum of 536 and user_mss.
+ Probably, user ordered to override tiny segment size
+ in gatewayed case.
+ */
+ tp->mss_clamp = max(tp->user_mss, 536);
+ }
+
+ tcp_connect(sk, buff, rt->u.dst.pmtu);
+ return 0;
+}
+
+static int tcp_v4_sendmsg(struct sock *sk, struct msghdr *msg, int len)
+{
+ int retval = -EINVAL;
+
+ /* Do sanity checking for sendmsg/sendto/send. */
+ if (msg->msg_flags & ~(MSG_OOB|MSG_DONTROUTE|MSG_DONTWAIT|MSG_NOSIGNAL))
+ goto out;
+ if (msg->msg_name) {
+ struct sockaddr_in *addr=(struct sockaddr_in *)msg->msg_name;
+
+ if (msg->msg_namelen < sizeof(*addr))
+ goto out;
+ if (addr->sin_family && addr->sin_family != AF_INET)
+ goto out;
+ retval = -ENOTCONN;
+ if(sk->state == TCP_CLOSE)
+ goto out;
+ retval = -EISCONN;
+ if (addr->sin_port != sk->dport)
+ goto out;
+ if (addr->sin_addr.s_addr != sk->daddr)
+ goto out;
+ }
+ retval = tcp_do_sendmsg(sk, msg);
+
+out:
+ return retval;
+}
+
+
+/*
+ * Do a linear search in the socket open_request list.
+ * This should be replaced with a global hash table.
+ */
+static struct open_request *tcp_v4_search_req(struct tcp_opt *tp,
+ struct iphdr *iph,
+ struct tcphdr *th,
+ struct open_request **prevp)
+{
+ struct open_request *req, *prev;
+ __u16 rport = th->source;
+
+ /* assumption: the socket is not in use.
+ * as we checked the user count on tcp_rcv and we're
+ * running from a soft interrupt.
+ */
+ prev = (struct open_request *) (&tp->syn_wait_queue);
+ for (req = prev->dl_next; req; req = req->dl_next) {
+ if (req->af.v4_req.rmt_addr == iph->saddr &&
+ req->af.v4_req.loc_addr == iph->daddr &&
+ req->rmt_port == rport
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ && req->lcl_port == th->dest
+#endif
+ ) {
+ *prevp = prev;
+ return req;
+ }
+ prev = req;
+ }
+ return NULL;
+}
+
+
+/*
+ * This routine does path mtu discovery as defined in RFC1191.
+ */
+static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *ip, unsigned mtu)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ if (atomic_read(&sk->sock_readers))
+ return;
+
+ /* Don't interested in TCP_LISTEN and open_requests (SYN-ACKs
+ * send out by Linux are always <576bytes so they should go through
+ * unfragmented).
+ */
+ if (sk->state == TCP_LISTEN)
+ return;
+
+ /* We don't check in the destentry if pmtu discovery is forbidden
+ * on this route. We just assume that no packet_to_big packets
+ * are send back when pmtu discovery is not active.
+ * There is a small race when the user changes this flag in the
+ * route, but I think that's acceptable.
+ */
+ if (sk->dst_cache == NULL)
+ return;
+ ip_rt_update_pmtu(sk->dst_cache, mtu);
+ if (sk->ip_pmtudisc != IP_PMTUDISC_DONT &&
+ tp->pmtu_cookie > sk->dst_cache->pmtu) {
+ tcp_sync_mss(sk, sk->dst_cache->pmtu);
+
+ /* Resend the TCP packet because it's
+ * clear that the old packet has been
+ * dropped. This is the new "fast" path mtu
+ * discovery.
+ */
+ tcp_simple_retransmit(sk);
+ } /* else let the usual retransmit timer handle it */
+}
+
+/*
+ * This routine is called by the ICMP module when it gets some
+ * sort of error condition. If err < 0 then the socket should
+ * be closed and the error returned to the user. If err > 0
+ * it's just the icmp type << 8 | icmp code. After adjustment
+ * header points to the first 8 bytes of the tcp header. We need
+ * to find the appropriate port.
+ *
+ * The locking strategy used here is very "optimistic". When
+ * someone else accesses the socket the ICMP is just dropped
+ * and for some paths there is no check at all.
+ * A more general error queue to queue errors for later handling
+ * is probably better.
+ *
+ * sk->err and sk->err_soft should be atomic_t.
+ */
+
+void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len)
+{
+ struct iphdr *iph = (struct iphdr*)dp;
+ struct tcphdr *th;
+ struct tcp_opt *tp;
+ int type = skb->h.icmph->type;
+ int code = skb->h.icmph->code;
+#if ICMP_MIN_LENGTH < 14
+ int no_flags = 0;
+#else
+#define no_flags 0
+#endif
+ struct sock *sk;
+ __u32 seq;
+ int err;
+
+ if (len < (iph->ihl << 2) + ICMP_MIN_LENGTH) {
+ icmp_statistics.IcmpInErrors++;
+ return;
+ }
+#if ICMP_MIN_LENGTH < 14
+ if (len < (iph->ihl << 2) + 14)
+ no_flags = 1;
+#endif
+
+ th = (struct tcphdr*)(dp+(iph->ihl<<2));
+
+ sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, th->source, skb->dev->ifindex);
+ if (sk == NULL || sk->state == TCP_TIME_WAIT) {
+ icmp_statistics.IcmpInErrors++;
+ return;
+ }
+
+ tp = &sk->tp_pinfo.af_tcp;
+ seq = ntohl(th->seq);
+ if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) {
+ net_statistics.OutOfWindowIcmps++;
+ return;
+ }
+
+ switch (type) {
+ case ICMP_SOURCE_QUENCH:
+#ifndef OLD_SOURCE_QUENCH /* This is deprecated */
+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ tp->snd_cwnd = tp->snd_ssthresh;
+ tp->snd_cwnd_cnt = 0;
+ tp->high_seq = tp->snd_nxt;
+#endif
+ return;
+ case ICMP_PARAMETERPROB:
+ err = EPROTO;
+ break;
+ case ICMP_DEST_UNREACH:
+ if (code > NR_ICMP_UNREACH)
+ return;
+
+ if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
+ do_pmtu_discovery(sk, iph, ntohs(skb->h.icmph->un.frag.mtu));
+ return;
+ }
+
+ err = icmp_err_convert[code].errno;
+ break;
+ case ICMP_TIME_EXCEEDED:
+ err = EHOSTUNREACH;
+ break;
+ default:
+ return;
+ }
+
+ switch (sk->state) {
+ struct open_request *req, *prev;
+ case TCP_LISTEN:
+ /* Prevent race conditions with accept() -
+ * ICMP is unreliable.
+ */
+ if (atomic_read(&sk->sock_readers)) {
+ net_statistics.LockDroppedIcmps++;
+ /* If too many ICMPs get dropped on busy
+ * servers this needs to be solved differently.
+ */
+ return;
+ }
+
+ /* The final ACK of the handshake should be already
+ * handled in the new socket context, not here.
+ * Strictly speaking - an ICMP error for the final
+ * ACK should set the opening flag, but that is too
+ * complicated right now.
+ */
+ if (!no_flags && !th->syn && !th->ack)
+ return;
+
+ req = tcp_v4_search_req(tp, iph, th, &prev);
+ if (!req)
+ return;
+ if (seq != req->snt_isn) {
+ net_statistics.OutOfWindowIcmps++;
+ return;
+ }
+ if (req->sk) {
+ /*
+ * Already in ESTABLISHED and a big socket is created,
+ * set error code there.
+ * The error will _not_ be reported in the accept(),
+ * but only with the next operation on the socket after
+ * accept.
+ */
+ sk = req->sk;
+ } else {
+ /*
+ * Still in SYN_RECV, just remove it silently.
+ * There is no good way to pass the error to the newly
+ * created socket, and POSIX does not want network
+ * errors returned from accept().
+ */
+ tp->syn_backlog--;
+ tcp_synq_unlink(tp, req, prev);
+ req->class->destructor(req);
+ tcp_openreq_free(req);
+ return;
+ }
+ break;
+ case TCP_SYN_SENT:
+ case TCP_SYN_RECV: /* Cannot happen */
+ if (!no_flags && !th->syn)
+ return;
+ tcp_statistics.TcpAttemptFails++;
+ sk->err = err;
+ sk->zapped = 1;
+ mb();
+ sk->error_report(sk);
+ return;
+ }
+
+ /* If we've already connected we will keep trying
+ * until we time out, or the user gives up.
+ *
+ * rfc1122 4.2.3.9 allows to consider as hard errors
+ * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
+ * but it is obsoleted by pmtu discovery).
+ *
+ * Note, that in modern internet, where routing is unreliable
+ * and in each dark corner broken firewalls sit, sending random
+ * errors ordered by their masters even this two messages finally lose
+ * their original sense (even Linux sends invalid PORT_UNREACHs)
+ *
+ * Now we are in compliance with RFCs.
+ * --ANK (980905)
+ */
+
+ if (sk->ip_recverr) {
+ /* This code isn't serialized with the socket code */
+ /* ANK (980927) ... which is harmless now,
+ sk->err's may be safely lost.
+ */
+ sk->err = err;
+ mb();
+ sk->error_report(sk); /* Wake people up to see the error (see connect in sock.c) */
+ } else { /* Only an error on timeout */
+ sk->err_soft = err;
+ mb();
+ }
+}
+
+/* This routine computes an IPv4 TCP checksum. */
+void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
+ struct sk_buff *skb)
+{
+ th->check = 0;
+ th->check = tcp_v4_check(th, len, sk->saddr, sk->daddr,
+ csum_partial((char *)th, th->doff<<2, skb->csum));
+}
+
+/*
+ * This routine will send an RST to the other tcp.
+ *
+ * Someone asks: why I NEVER use socket parameters (TOS, TTL etc.)
+ * for reset.
+ * Answer: if a packet caused RST, it is not for a socket
+ * existing in our system, if it is matched to a socket,
+ * it is just duplicate segment or bug in other side's TCP.
+ * So that we build reply only basing on parameters
+ * arrived with segment.
+ * Exception: precedence violation. We do not implement it in any case.
+ */
+
+static void tcp_v4_send_reset(struct sk_buff *skb)
+{
+ struct tcphdr *th = skb->h.th;
+ struct tcphdr rth;
+ struct ip_reply_arg arg;
+
+ /* Never send a reset in response to a reset. */
+ if (th->rst)
+ return;
+
+ if (((struct rtable*)skb->dst)->rt_type != RTN_LOCAL) {
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (((struct rtable*)skb->dst)->rt_type == RTN_UNICAST)
+ icmp_send(skb, ICMP_DEST_UNREACH,
+ ICMP_PORT_UNREACH, 0);
+#endif
+ return;
+ }
+
+ /* Swap the send and the receive. */
+ memset(&rth, 0, sizeof(struct tcphdr));
+ rth.dest = th->source;
+ rth.source = th->dest;
+ rth.doff = sizeof(struct tcphdr)/4;
+ rth.rst = 1;
+
+ if (th->ack) {
+ rth.seq = th->ack_seq;
+ } else {
+ rth.ack = 1;
+ rth.ack_seq = th->syn ? htonl(ntohl(th->seq)+1) : th->seq;
+ }
+
+ memset(&arg, 0, sizeof arg);
+ arg.iov[0].iov_base = (unsigned char *)&rth;
+ arg.iov[0].iov_len = sizeof rth;
+ arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
+ skb->nh.iph->saddr, /*XXX*/
+ sizeof(struct tcphdr),
+ IPPROTO_TCP,
+ 0);
+ arg.n_iov = 1;
+ arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+
+ ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth);
+
+ tcp_statistics.TcpOutSegs++;
+ tcp_statistics.TcpOutRsts++;
+}
+
+/*
+ * Send an ACK for a socket less packet (needed for time wait)
+ *
+ * FIXME: Does not echo timestamps yet.
+ *
+ * Assumes that the caller did basic address and flag checks.
+ */
+static void tcp_v4_send_ack(struct sk_buff *skb, __u32 seq, __u32 ack, __u16 window)
+{
+ struct tcphdr *th = skb->h.th;
+ struct tcphdr rth;
+ struct ip_reply_arg arg;
+
+ /* Swap the send and the receive. */
+ memset(&rth, 0, sizeof(struct tcphdr));
+ rth.dest = th->source;
+ rth.source = th->dest;
+ rth.doff = sizeof(struct tcphdr)/4;
+
+ rth.seq = seq;
+ rth.ack_seq = ack;
+ rth.ack = 1;
+
+ rth.window = htons(window);
+
+ memset(&arg, 0, sizeof arg);
+ arg.iov[0].iov_base = (unsigned char *)&rth;
+ arg.iov[0].iov_len = sizeof rth;
+ arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
+ skb->nh.iph->saddr, /*XXX*/
+ sizeof(struct tcphdr),
+ IPPROTO_TCP,
+ 0);
+ arg.n_iov = 1;
+ arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+
+ ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth);
+
+ tcp_statistics.TcpOutSegs++;
+}
+
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+
+/*
+ Seems, I never wrote nothing more stupid.
+ I hope Gods will forgive me, but I cannot forgive myself 8)
+ --ANK (981001)
+ */
+
+static struct sock *tcp_v4_search_proxy_openreq(struct sk_buff *skb)
+{
+ struct iphdr *iph = skb->nh.iph;
+ struct tcphdr *th = (struct tcphdr *)(skb->nh.raw + iph->ihl*4);
+ struct sock *sk;
+ int i;
+
+ for (i=0; i<TCP_LHTABLE_SIZE; i++) {
+ for(sk = tcp_listening_hash[i]; sk; sk = sk->next) {
+ struct open_request *dummy;
+ if (tcp_v4_search_req(&sk->tp_pinfo.af_tcp, iph,
+ th, &dummy) &&
+ (!sk->bound_dev_if ||
+ sk->bound_dev_if == skb->dev->ifindex))
+ return sk;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Check whether a received TCP packet might be for one of our
+ * connections.
+ */
+
+int tcp_chkaddr(struct sk_buff *skb)
+{
+ struct iphdr *iph = skb->nh.iph;
+ struct tcphdr *th = (struct tcphdr *)(skb->nh.raw + iph->ihl*4);
+ struct sock *sk;
+
+ sk = tcp_v4_lookup(iph->saddr, th->source, iph->daddr,
+ th->dest, skb->dev->ifindex);
+
+ if (!sk)
+ return tcp_v4_search_proxy_openreq(skb) != NULL;
+
+ if (sk->state == TCP_LISTEN) {
+ struct open_request *dummy;
+ if (tcp_v4_search_req(&sk->tp_pinfo.af_tcp, skb->nh.iph,
+ th, &dummy) &&
+ (!sk->bound_dev_if ||
+ sk->bound_dev_if == skb->dev->ifindex))
+ return 1;
+ }
+
+ /* 0 means accept all LOCAL addresses here, not all the world... */
+
+ if (sk->rcv_saddr == 0)
+ return 0;
+
+ return 1;
+}
+#endif
+
+/*
+ * Send a SYN-ACK after having received an ACK.
+ * This still operates on a open_request only, not on a big
+ * socket.
+ */
+static void tcp_v4_send_synack(struct sock *sk, struct open_request *req)
+{
+ struct rtable *rt;
+ struct ip_options *opt;
+ struct sk_buff * skb;
+ int mss;
+
+ /* First, grab a route. */
+ opt = req->af.v4_req.opt;
+ if(ip_route_output(&rt, ((opt && opt->srr) ?
+ opt->faddr :
+ req->af.v4_req.rmt_addr),
+ req->af.v4_req.loc_addr,
+ RT_TOS(sk->ip_tos) | RTO_CONN | sk->localroute,
+ sk->bound_dev_if)) {
+ ip_statistics.IpOutNoRoutes++;
+ return;
+ }
+ if(opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
+ ip_rt_put(rt);
+ ip_statistics.IpOutNoRoutes++;
+ return;
+ }
+
+ mss = rt->u.dst.pmtu - sizeof(struct iphdr) - sizeof(struct tcphdr);
+
+ skb = tcp_make_synack(sk, &rt->u.dst, req, mss);
+ if (skb) {
+ struct tcphdr *th = skb->h.th;
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ th->source = req->lcl_port; /* LVE */
+#endif
+
+ th->check = tcp_v4_check(th, skb->len,
+ req->af.v4_req.loc_addr, req->af.v4_req.rmt_addr,
+ csum_partial((char *)th, skb->len, skb->csum));
+
+ ip_build_and_send_pkt(skb, sk, req->af.v4_req.loc_addr,
+ req->af.v4_req.rmt_addr, req->af.v4_req.opt);
+ }
+ ip_rt_put(rt);
+}
+
+/*
+ * IPv4 open_request destructor.
+ */
+static void tcp_v4_or_free(struct open_request *req)
+{
+ if(!req->sk && req->af.v4_req.opt)
+ kfree_s(req->af.v4_req.opt, optlength(req->af.v4_req.opt));
+}
+
+static inline void syn_flood_warning(struct sk_buff *skb)
+{
+ static unsigned long warntime;
+
+ if (jiffies - warntime > HZ*60) {
+ warntime = jiffies;
+ printk(KERN_INFO
+ "possible SYN flooding on port %d. Sending cookies.\n",
+ ntohs(skb->h.th->dest));
+ }
+}
+
+/*
+ * Save and compile IPv4 options into the open_request if needed.
+ */
+static inline struct ip_options *
+tcp_v4_save_options(struct sock *sk, struct sk_buff *skb)
+{
+ struct ip_options *opt = &(IPCB(skb)->opt);
+ struct ip_options *dopt = NULL;
+
+ if (opt && opt->optlen) {
+ int opt_size = optlength(opt);
+ dopt = kmalloc(opt_size, GFP_ATOMIC);
+ if (dopt) {
+ if (ip_options_echo(dopt, skb)) {
+ kfree_s(dopt, opt_size);
+ dopt = NULL;
+ }
+ }
+ }
+ return dopt;
+}
+
+/*
+ * Maximum number of SYN_RECV sockets in queue per LISTEN socket.
+ * One SYN_RECV socket costs about 80bytes on a 32bit machine.
+ * It would be better to replace it with a global counter for all sockets
+ * but then some measure against one socket starving all other sockets
+ * would be needed.
+ */
+int sysctl_max_syn_backlog = 128;
+
+struct or_calltable or_ipv4 = {
+ tcp_v4_send_synack,
+ tcp_v4_or_free,
+ tcp_v4_send_reset
+};
+
+#define BACKLOG(sk) ((sk)->tp_pinfo.af_tcp.syn_backlog) /* lvalue! */
+#define BACKLOGMAX(sk) sysctl_max_syn_backlog
+
+int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, __u32 isn)
+{
+ struct tcp_opt tp;
+ struct open_request *req;
+ struct tcphdr *th = skb->h.th;
+ __u32 saddr = skb->nh.iph->saddr;
+ __u32 daddr = skb->nh.iph->daddr;
+#ifdef CONFIG_SYN_COOKIES
+ int want_cookie = 0;
+#else
+#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
+#endif
+
+ /* If the socket is dead, don't accept the connection. */
+ if (sk->dead)
+ goto dead;
+
+ /* Never answer to SYNs send to broadcast or multicast */
+ if (((struct rtable *)skb->dst)->rt_flags &
+ (RTCF_BROADCAST|RTCF_MULTICAST))
+ goto drop;
+
+ /* XXX: Check against a global syn pool counter. */
+ if (BACKLOG(sk) > BACKLOGMAX(sk)) {
+#ifdef CONFIG_SYN_COOKIES
+ if (sysctl_tcp_syncookies) {
+ syn_flood_warning(skb);
+ want_cookie = 1;
+ } else
+#endif
+ goto drop;
+ } else {
+ if (isn == 0)
+ isn = tcp_v4_init_sequence(sk, skb);
+ BACKLOG(sk)++;
+ }
+
+ req = tcp_openreq_alloc();
+ if (req == NULL) {
+ goto dropbacklog;
+ }
+
+ req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */
+
+ req->rcv_isn = TCP_SKB_CB(skb)->seq;
+ tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
+
+ tp.mss_clamp = 65535;
+ tcp_parse_options(NULL, th, &tp, want_cookie);
+ if (tp.mss_clamp == 65535)
+ tp.mss_clamp = 576 - sizeof(struct iphdr) - sizeof(struct iphdr);
+
+ if (sk->tp_pinfo.af_tcp.user_mss && sk->tp_pinfo.af_tcp.user_mss < tp.mss_clamp)
+ tp.mss_clamp = sk->tp_pinfo.af_tcp.user_mss;
+ req->mss = tp.mss_clamp;
+
+ if (tp.saw_tstamp)
+ req->ts_recent = tp.rcv_tsval;
+ req->tstamp_ok = tp.tstamp_ok;
+ req->sack_ok = tp.sack_ok;
+ req->snd_wscale = tp.snd_wscale;
+ req->wscale_ok = tp.wscale_ok;
+ req->rmt_port = th->source;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ req->lcl_port = th->dest ; /* LVE */
+#endif
+ req->af.v4_req.loc_addr = daddr;
+ req->af.v4_req.rmt_addr = saddr;
+
+ /* Note that we ignore the isn passed from the TIME_WAIT
+ * state here. That's the price we pay for cookies.
+ */
+ if (want_cookie)
+ isn = cookie_v4_init_sequence(sk, skb, &req->mss);
+
+ req->snt_isn = isn;
+
+ req->af.v4_req.opt = tcp_v4_save_options(sk, skb);
+
+ req->class = &or_ipv4;
+ req->retrans = 0;
+ req->sk = NULL;
+
+ tcp_v4_send_synack(sk, req);
+
+ if (want_cookie) {
+ if (req->af.v4_req.opt)
+ kfree(req->af.v4_req.opt);
+ tcp_v4_or_free(req);
+ tcp_openreq_free(req);
+ } else {
+ req->expires = jiffies + TCP_TIMEOUT_INIT;
+ tcp_inc_slow_timer(TCP_SLT_SYNACK);
+ tcp_synq_queue(&sk->tp_pinfo.af_tcp, req);
+ }
+
+ return 0;
+
+dead:
+ SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n",sk);
+ tcp_statistics.TcpAttemptFails++;
+ return -ENOTCONN; /* send reset */
+
+dropbacklog:
+ if (!want_cookie)
+ BACKLOG(sk)--;
+drop:
+ tcp_statistics.TcpAttemptFails++;
+ return 0;
+}
+
+/* This is not only more efficient than what we used to do, it eliminates
+ * a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM
+ *
+ * This function wants to be moved to a common for IPv[46] file. --ANK
+ */
+struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, struct sk_buff *skb)
+{
+ struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0);
+
+ if(newsk != NULL) {
+ struct tcp_opt *newtp;
+#ifdef CONFIG_FILTER
+ struct sk_filter *filter;
+#endif
+
+ memcpy(newsk, sk, sizeof(*newsk));
+ newsk->sklist_next = NULL;
+ newsk->state = TCP_SYN_RECV;
+
+ /* Clone the TCP header template */
+ newsk->dport = req->rmt_port;
+
+ atomic_set(&newsk->sock_readers, 0);
+ atomic_set(&newsk->rmem_alloc, 0);
+ skb_queue_head_init(&newsk->receive_queue);
+ atomic_set(&newsk->wmem_alloc, 0);
+ skb_queue_head_init(&newsk->write_queue);
+ atomic_set(&newsk->omem_alloc, 0);
+
+ newsk->done = 0;
+ newsk->proc = 0;
+ skb_queue_head_init(&newsk->back_log);
+ skb_queue_head_init(&newsk->error_queue);
+#ifdef CONFIG_FILTER
+ if ((filter = newsk->filter) != NULL)
+ sk_filter_charge(newsk, filter);
+#endif
+
+ /* Now setup tcp_opt */
+ newtp = &(newsk->tp_pinfo.af_tcp);
+ newtp->pred_flags = 0;
+ newtp->rcv_nxt = req->rcv_isn + 1;
+ newtp->snd_nxt = req->snt_isn + 1;
+ newtp->snd_una = req->snt_isn + 1;
+ newtp->srtt = 0;
+ newtp->ato = 0;
+ newtp->snd_wl1 = req->rcv_isn;
+ newtp->snd_wl2 = req->snt_isn;
+
+ /* RFC1323: The window in SYN & SYN/ACK segments
+ * is never scaled.
+ */
+ newtp->snd_wnd = ntohs(skb->h.th->window);
+
+ newtp->max_window = newtp->snd_wnd;
+ newtp->pending = 0;
+ newtp->retransmits = 0;
+ newtp->last_ack_sent = req->rcv_isn + 1;
+ newtp->backoff = 0;
+ newtp->mdev = TCP_TIMEOUT_INIT;
+
+ /* So many TCP implementations out there (incorrectly) count the
+ * initial SYN frame in their delayed-ACK and congestion control
+ * algorithms that we must have the following bandaid to talk
+ * efficiently to them. -DaveM
+ */
+ newtp->snd_cwnd = 2;
+
+ newtp->rto = TCP_TIMEOUT_INIT;
+ newtp->packets_out = 0;
+ newtp->fackets_out = 0;
+ newtp->retrans_out = 0;
+ newtp->high_seq = 0;
+ newtp->snd_ssthresh = 0x7fffffff;
+ newtp->snd_cwnd_cnt = 0;
+ newtp->dup_acks = 0;
+ newtp->delayed_acks = 0;
+ init_timer(&newtp->retransmit_timer);
+ newtp->retransmit_timer.function = &tcp_retransmit_timer;
+ newtp->retransmit_timer.data = (unsigned long) newsk;
+ init_timer(&newtp->delack_timer);
+ newtp->delack_timer.function = &tcp_delack_timer;
+ newtp->delack_timer.data = (unsigned long) newsk;
+ skb_queue_head_init(&newtp->out_of_order_queue);
+ newtp->send_head = newtp->retrans_head = NULL;
+ newtp->rcv_wup = req->rcv_isn + 1;
+ newtp->write_seq = req->snt_isn + 1;
+ newtp->copied_seq = req->rcv_isn + 1;
+
+ newtp->saw_tstamp = 0;
+ newtp->mss_clamp = req->mss;
+
+ init_timer(&newtp->probe_timer);
+ newtp->probe_timer.function = &tcp_probe_timer;
+ newtp->probe_timer.data = (unsigned long) newsk;
+ newtp->probes_out = 0;
+ newtp->syn_seq = req->rcv_isn;
+ newtp->fin_seq = req->rcv_isn;
+ newtp->urg_data = 0;
+ tcp_synq_init(newtp);
+ newtp->syn_backlog = 0;
+ if (skb->len >= 536)
+ newtp->last_seg_size = skb->len;
+
+ /* Back to base struct sock members. */
+ newsk->err = 0;
+ newsk->ack_backlog = 0;
+ newsk->max_ack_backlog = SOMAXCONN;
+ newsk->priority = 0;
+
+ /* IP layer stuff */
+ newsk->timeout = 0;
+ init_timer(&newsk->timer);
+ newsk->timer.function = &net_timer;
+ newsk->timer.data = (unsigned long) newsk;
+ newsk->socket = NULL;
+
+ newtp->tstamp_ok = req->tstamp_ok;
+ if((newtp->sack_ok = req->sack_ok) != 0)
+ newtp->num_sacks = 0;
+ newtp->window_clamp = req->window_clamp;
+ newtp->rcv_wnd = req->rcv_wnd;
+ newtp->wscale_ok = req->wscale_ok;
+ if (newtp->wscale_ok) {
+ newtp->snd_wscale = req->snd_wscale;
+ newtp->rcv_wscale = req->rcv_wscale;
+ } else {
+ newtp->snd_wscale = newtp->rcv_wscale = 0;
+ newtp->window_clamp = min(newtp->window_clamp,65535);
+ }
+ if (newtp->tstamp_ok) {
+ newtp->ts_recent = req->ts_recent;
+ newtp->ts_recent_stamp = tcp_time_stamp;
+ newtp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
+ } else {
+ newtp->tcp_header_len = sizeof(struct tcphdr);
+ }
+ }
+ return newsk;
+}
+
+/*
+ * The three way handshake has completed - we got a valid synack -
+ * now create the new socket.
+ */
+struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ struct open_request *req,
+ struct dst_entry *dst)
+{
+ struct ip_options *opt = req->af.v4_req.opt;
+ struct tcp_opt *newtp;
+ struct sock *newsk;
+
+ if (sk->ack_backlog > sk->max_ack_backlog)
+ goto exit; /* head drop */
+ if (dst == NULL) {
+ struct rtable *rt;
+
+ if (ip_route_output(&rt,
+ opt && opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
+ req->af.v4_req.loc_addr, sk->ip_tos|RTO_CONN, 0))
+ return NULL;
+ dst = &rt->u.dst;
+ }
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ /* The new socket created for transparent proxy may fall
+ * into a non-existed bind bucket because sk->num != newsk->num.
+ * Ensure existance of the bucket now. The placement of the check
+ * later will require to destroy just created newsk in the case of fail.
+ * 1998/04/22 Andrey V. Savochkin <saw@msu.ru>
+ */
+ if (__tcp_bucket_check(ntohs(skb->h.th->dest)))
+ goto exit;
+#endif
+
+ newsk = tcp_create_openreq_child(sk, req, skb);
+ if (!newsk)
+ goto exit;
+
+ sk->tp_pinfo.af_tcp.syn_backlog--;
+ sk->ack_backlog++;
+
+ newsk->dst_cache = dst;
+
+ newtp = &(newsk->tp_pinfo.af_tcp);
+ newsk->daddr = req->af.v4_req.rmt_addr;
+ newsk->saddr = req->af.v4_req.loc_addr;
+ newsk->rcv_saddr = req->af.v4_req.loc_addr;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ newsk->num = ntohs(skb->h.th->dest);
+ newsk->sport = req->lcl_port;
+#endif
+ newsk->opt = req->af.v4_req.opt;
+ newtp->ext_header_len = 0;
+ if (newsk->opt)
+ newtp->ext_header_len = newsk->opt->optlen;
+
+ tcp_sync_mss(newsk, dst->pmtu);
+ newtp->rcv_mss = newtp->mss_clamp;
+
+ /* It would be better to use newtp->mss_clamp here */
+ if (newsk->rcvbuf < (3 * newtp->pmtu_cookie))
+ newsk->rcvbuf = min ((3 * newtp->pmtu_cookie), sysctl_rmem_max);
+ if (newsk->sndbuf < (3 * newtp->pmtu_cookie))
+ newsk->sndbuf = min ((3 * newtp->pmtu_cookie), sysctl_wmem_max);
+
+ /* We run in BH processing itself or within a BH atomic
+ * sequence (backlog) so no locking is needed.
+ */
+ __tcp_v4_hash(newsk);
+ __tcp_inherit_port(sk, newsk);
+ __add_to_prot_sklist(newsk);
+
+ sk->data_ready(sk, 0); /* Deliver SIGIO */
+
+ return newsk;
+
+exit:
+ dst_release(dst);
+ return NULL;
+}
+
+static void tcp_v4_rst_req(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct open_request *req, *prev;
+
+ req = tcp_v4_search_req(tp,skb->nh.iph, skb->h.th, &prev);
+ if (!req)
+ return;
+ /* Sequence number check required by RFC793 */
+ if (before(TCP_SKB_CB(skb)->seq, req->rcv_isn) ||
+ after(TCP_SKB_CB(skb)->seq, req->rcv_isn+1))
+ return;
+ tcp_synq_unlink(tp, req, prev);
+ (req->sk ? sk->ack_backlog : tp->syn_backlog)--;
+ req->class->destructor(req);
+ tcp_openreq_free(req);
+
+ net_statistics.EmbryonicRsts++;
+}
+
+/* Check for embryonic sockets (open_requests) We check packets with
+ * only the SYN bit set against the open_request queue too: This
+ * increases connection latency a bit, but is required to detect
+ * retransmitted SYNs.
+ */
+static inline struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb)
+{
+ struct tcphdr *th = skb->h.th;
+ u32 flg = ((u32 *)th)[3];
+
+ /* Check for RST */
+ if (flg & __constant_htonl(0x00040000)) {
+ tcp_v4_rst_req(sk, skb);
+ return NULL;
+ }
+
+ /* Check for SYN|ACK */
+ if (flg & __constant_htonl(0x00120000)) {
+ struct open_request *req, *dummy;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Find possible connection requests. */
+ req = tcp_v4_search_req(tp, skb->nh.iph, th, &dummy);
+ if (req) {
+ sk = tcp_check_req(sk, skb, req);
+ }
+#ifdef CONFIG_SYN_COOKIES
+ else if (flg == __constant_htonl(0x00120000)) {
+ sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
+ }
+#endif
+ }
+ return sk;
+}
+
+int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+#ifdef CONFIG_FILTER
+ struct sk_filter *filter = sk->filter;
+ if (filter && sk_filter(skb, filter))
+ goto discard;
+#endif /* CONFIG_FILTER */
+
+ /*
+ * This doesn't check if the socket has enough room for the packet.
+ * Either process the packet _without_ queueing it and then free it,
+ * or do the check later.
+ */
+ skb_set_owner_r(skb, sk);
+
+ if (sk->state == TCP_ESTABLISHED) { /* Fast path */
+ if (tcp_rcv_established(sk, skb, skb->h.th, skb->len))
+ goto reset;
+ return 0;
+ }
+
+
+ if (sk->state == TCP_LISTEN) {
+ struct sock *nsk;
+
+ nsk = tcp_v4_hnd_req(sk, skb);
+ if (!nsk)
+ goto discard;
+
+ /*
+ * Queue it on the new socket if the new socket is active,
+ * otherwise we just shortcircuit this and continue with
+ * the new socket..
+ */
+ if (atomic_read(&nsk->sock_readers)) {
+ skb_orphan(skb);
+ __skb_queue_tail(&nsk->back_log, skb);
+ return 0;
+ }
+ sk = nsk;
+ }
+
+ if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
+ goto reset;
+ return 0;
+
+reset:
+ tcp_v4_send_reset(skb);
+discard:
+ kfree_skb(skb);
+ /* Be careful here. If this function gets more complicated and
+ * gcc suffers from register pressure on the x86, sk (in %ebx)
+ * might be destroyed here. This current version compiles correctly,
+ * but you have been warned.
+ */
+ return 0;
+}
+
+/*
+ * From tcp_input.c
+ */
+
+int tcp_v4_rcv(struct sk_buff *skb, unsigned short len)
+{
+ struct tcphdr *th;
+ struct sock *sk;
+
+ if (skb->pkt_type!=PACKET_HOST)
+ goto discard_it;
+
+ th = skb->h.th;
+
+ /* Pull up the IP header. */
+ __skb_pull(skb, skb->h.raw - skb->data);
+
+ /* Count it even if it's bad */
+ tcp_statistics.TcpInSegs++;
+
+ len = skb->len;
+ if (len < sizeof(struct tcphdr))
+ goto bad_packet;
+
+ /* Try to use the device checksum if provided. */
+ switch (skb->ip_summed) {
+ case CHECKSUM_NONE:
+ skb->csum = csum_partial((char *)th, len, 0);
+ case CHECKSUM_HW:
+ if (tcp_v4_check(th,len,skb->nh.iph->saddr,skb->nh.iph->daddr,skb->csum)) {
+ NETDEBUG(printk(KERN_DEBUG "TCPv4 bad checksum "
+ "from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, "
+ "len=%d/%d/%d\n",
+ NIPQUAD(skb->nh.iph->saddr),
+ ntohs(th->source),
+ NIPQUAD(skb->nh.iph->daddr),
+ ntohs(th->dest),
+ len, skb->len,
+ ntohs(skb->nh.iph->tot_len)));
+ bad_packet:
+ tcp_statistics.TcpInErrs++;
+ goto discard_it;
+ }
+ default:
+ /* CHECKSUM_UNNECESSARY */
+ }
+
+ if((th->doff * 4) < sizeof(struct tcphdr) ||
+ len < (th->doff * 4))
+ goto bad_packet;
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (IPCB(skb)->redirport)
+ sk = tcp_v4_proxy_lookup(th->dest, skb->nh.iph->saddr, th->source,
+ skb->nh.iph->daddr, skb->dev,
+ IPCB(skb)->redirport, skb->dev->ifindex);
+ else {
+#endif
+ sk = __tcp_v4_lookup(th, skb->nh.iph->saddr, th->source,
+ skb->nh.iph->daddr, th->dest, skb->dev->ifindex);
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (!sk)
+ sk = tcp_v4_search_proxy_openreq(skb);
+ }
+#endif
+ if (!sk)
+ goto no_tcp_socket;
+ if(!ipsec_sk_policy(sk,skb))
+ goto discard_it;
+
+ TCP_SKB_CB(skb)->seq = ntohl(th->seq);
+ TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
+ len - th->doff*4);
+ TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
+
+ skb->used = 0;
+
+ if (sk->state == TCP_TIME_WAIT)
+ goto do_time_wait;
+ if (!atomic_read(&sk->sock_readers))
+ return tcp_v4_do_rcv(sk, skb);
+
+ __skb_queue_tail(&sk->back_log, skb);
+ return 0;
+
+no_tcp_socket:
+ tcp_v4_send_reset(skb);
+
+discard_it:
+ /* Discard frame. */
+ kfree_skb(skb);
+ return 0;
+
+do_time_wait:
+ /* Sorry for the ugly switch. 2.3 will have a better solution. */
+ switch (tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
+ skb, th, skb->len)) {
+ case TCP_TW_ACK:
+ tcp_v4_send_ack(skb,
+ ((struct tcp_tw_bucket *)sk)->snd_nxt,
+ ((struct tcp_tw_bucket *)sk)->rcv_nxt,
+ ((struct tcp_tw_bucket *)sk)->window);
+ goto discard_it;
+ case TCP_TW_RST:
+ goto no_tcp_socket;
+ default:
+ goto discard_it;
+ }
+}
+
+static void __tcp_v4_rehash(struct sock *sk)
+{
+ struct sock **skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
+
+ SOCKHASH_LOCK();
+ if(sk->pprev) {
+ if(sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ tcp_reg_zap(sk);
+ }
+ if((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+ *skp = sk;
+ sk->pprev = skp;
+ SOCKHASH_UNLOCK();
+}
+
+int tcp_v4_rebuild_header(struct sock *sk)
+{
+ struct rtable *rt = (struct rtable *)sk->dst_cache;
+ __u32 new_saddr;
+ int want_rewrite = sysctl_ip_dynaddr && sk->state == TCP_SYN_SENT;
+
+ if(rt == NULL)
+ return 0;
+
+ /* Force route checking if want_rewrite.
+ * The idea is good, the implementation is disguisting.
+ * Well, if I made bind on this socket, you cannot randomly ovewrite
+ * its source address. --ANK
+ */
+ if (want_rewrite) {
+ int tmp;
+ struct rtable *new_rt;
+ __u32 old_saddr = rt->rt_src;
+
+ /* Query new route using another rt buffer */
+ tmp = ip_route_connect(&new_rt, rt->rt_dst, 0,
+ RT_TOS(sk->ip_tos)|sk->localroute,
+ sk->bound_dev_if);
+
+ /* Only useful if different source addrs */
+ if (tmp == 0) {
+ /*
+ * Only useful if different source addrs
+ */
+ if (new_rt->rt_src != old_saddr ) {
+ dst_release(sk->dst_cache);
+ sk->dst_cache = &new_rt->u.dst;
+ rt = new_rt;
+ goto do_rewrite;
+ }
+ dst_release(&new_rt->u.dst);
+ }
+ }
+ if (rt->u.dst.obsolete) {
+ int err;
+ err = ip_route_output(&rt, rt->rt_dst, rt->rt_src, rt->key.tos|RTO_CONN, rt->key.oif);
+ if (err) {
+ sk->err_soft=-err;
+ sk->error_report(sk);
+ return -1;
+ }
+ dst_release(xchg(&sk->dst_cache, &rt->u.dst));
+ }
+
+ return 0;
+
+do_rewrite:
+ new_saddr = rt->rt_src;
+
+ /* Ouch!, this should not happen. */
+ if (!sk->saddr || !sk->rcv_saddr) {
+ printk(KERN_WARNING "tcp_v4_rebuild_header(): not valid sock addrs: "
+ "saddr=%08lX rcv_saddr=%08lX\n",
+ ntohl(sk->saddr),
+ ntohl(sk->rcv_saddr));
+ return 0;
+ }
+
+ if (new_saddr != sk->saddr) {
+ if (sysctl_ip_dynaddr > 1) {
+ printk(KERN_INFO "tcp_v4_rebuild_header(): shifting sk->saddr "
+ "from %d.%d.%d.%d to %d.%d.%d.%d\n",
+ NIPQUAD(sk->saddr),
+ NIPQUAD(new_saddr));
+ }
+
+ sk->saddr = new_saddr;
+ sk->rcv_saddr = new_saddr;
+
+ /* XXX The only one ugly spot where we need to
+ * XXX really change the sockets identity after
+ * XXX it has entered the hashes. -DaveM
+ */
+ __tcp_v4_rehash(sk);
+ }
+
+ return 0;
+}
+
+static struct sock * tcp_v4_get_sock(struct sk_buff *skb, struct tcphdr *th)
+{
+ return tcp_v4_lookup(skb->nh.iph->saddr, th->source,
+ skb->nh.iph->daddr, th->dest, skb->dev->ifindex);
+}
+
+static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *) uaddr;
+
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = sk->daddr;
+ sin->sin_port = sk->dport;
+}
+
+struct tcp_func ipv4_specific = {
+ ip_queue_xmit,
+ tcp_v4_send_check,
+ tcp_v4_rebuild_header,
+ tcp_v4_conn_request,
+ tcp_v4_syn_recv_sock,
+ tcp_v4_get_sock,
+ sizeof(struct iphdr),
+
+ ip_setsockopt,
+ ip_getsockopt,
+ v4_addr2sockaddr,
+ sizeof(struct sockaddr_in)
+};
+
+/* NOTE: A lot of things set to zero explicitly by call to
+ * sk_alloc() so need not be done here.
+ */
+static int tcp_v4_init_sock(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ skb_queue_head_init(&tp->out_of_order_queue);
+ tcp_init_xmit_timers(sk);
+
+ tp->rto = TCP_TIMEOUT_INIT; /*TCP_WRITE_TIME*/
+ tp->mdev = TCP_TIMEOUT_INIT;
+ tp->mss_clamp = ~0;
+
+ /* So many TCP implementations out there (incorrectly) count the
+ * initial SYN frame in their delayed-ACK and congestion control
+ * algorithms that we must have the following bandaid to talk
+ * efficiently to them. -DaveM
+ */
+ tp->snd_cwnd = 2;
+
+ /* See draft-stevens-tcpca-spec-01 for discussion of the
+ * initialization of these values.
+ */
+ tp->snd_cwnd_cnt = 0;
+ tp->snd_ssthresh = 0x7fffffff; /* Infinity */
+
+ sk->state = TCP_CLOSE;
+ sk->max_ack_backlog = SOMAXCONN;
+ tp->rcv_mss = 536;
+
+ sk->write_space = tcp_write_space;
+
+ /* Init SYN queue. */
+ tcp_synq_init(tp);
+
+ sk->tp_pinfo.af_tcp.af_specific = &ipv4_specific;
+
+ return 0;
+}
+
+static int tcp_v4_destroy_sock(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+
+ tcp_clear_xmit_timers(sk);
+
+ if (sk->keepopen)
+ tcp_dec_slow_timer(TCP_SLT_KEEPALIVE);
+
+ /* Cleanup up the write buffer. */
+ while((skb = __skb_dequeue(&sk->write_queue)) != NULL)
+ kfree_skb(skb);
+
+ /* Cleans up our, hopefuly empty, out_of_order_queue. */
+ while((skb = __skb_dequeue(&tp->out_of_order_queue)) != NULL)
+ kfree_skb(skb);
+
+ /* Clean up a referenced TCP bind bucket, this only happens if a
+ * port is allocated for a socket, but it never fully connects.
+ */
+ if(sk->prev != NULL)
+ tcp_put_port(sk);
+
+ return 0;
+}
+
+struct proto tcp_prot = {
+ (struct sock *)&tcp_prot, /* sklist_next */
+ (struct sock *)&tcp_prot, /* sklist_prev */
+ tcp_close, /* close */
+ tcp_v4_connect, /* connect */
+ tcp_accept, /* accept */
+ NULL, /* retransmit */
+ tcp_write_wakeup, /* write_wakeup */
+ tcp_read_wakeup, /* read_wakeup */
+ tcp_poll, /* poll */
+ tcp_ioctl, /* ioctl */
+ tcp_v4_init_sock, /* init */
+ tcp_v4_destroy_sock, /* destroy */
+ tcp_shutdown, /* shutdown */
+ tcp_setsockopt, /* setsockopt */
+ tcp_getsockopt, /* getsockopt */
+ tcp_v4_sendmsg, /* sendmsg */
+ tcp_recvmsg, /* recvmsg */
+ NULL, /* bind */
+ tcp_v4_do_rcv, /* backlog_rcv */
+ tcp_v4_hash, /* hash */
+ tcp_v4_unhash, /* unhash */
+ tcp_v4_get_port, /* get_port */
+ 128, /* max_header */
+ 0, /* retransmits */
+ "TCP", /* name */
+ 0, /* inuse */
+ 0 /* highestinuse */
+};
+
+
+
+__initfunc(void tcp_v4_init(struct net_proto_family *ops))
+{
+ int err;
+
+ tcp_inode.i_mode = S_IFSOCK;
+ tcp_inode.i_sock = 1;
+ tcp_inode.i_uid = 0;
+ tcp_inode.i_gid = 0;
+
+ tcp_socket->inode = &tcp_inode;
+ tcp_socket->state = SS_UNCONNECTED;
+ tcp_socket->type=SOCK_RAW;
+
+ if ((err=ops->create(tcp_socket, IPPROTO_TCP))<0)
+ panic("Failed to create the TCP control socket.\n");
+ tcp_socket->sk->allocation=GFP_ATOMIC;
+ tcp_socket->sk->num = 256; /* Don't receive any data */
+ tcp_socket->sk->ip_ttl = MAXTTL;
+}
diff --git a/pfinet/linux-src/net/ipv4/tcp_output.c b/pfinet/linux-src/net/ipv4/tcp_output.c
new file mode 100644
index 00000000..2ac5e8a2
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/tcp_output.c
@@ -0,0 +1,1143 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id: tcp_output.c,v 1.108.2.1 1999/05/14 23:07:36 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ * Linus Torvalds, <torvalds@cs.helsinki.fi>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Matthew Dillon, <dillon@apollo.west.oic.com>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+/*
+ * Changes: Pedro Roque : Retransmit queue handled by TCP.
+ * : Fragmentation on mtu decrease
+ * : Segment collapse on retransmit
+ * : AF independence
+ *
+ * Linus Torvalds : send_delayed_ack
+ * David S. Miller : Charge memory using the right skb
+ * during syn/ack processing.
+ * David S. Miller : Output engine completely rewritten.
+ * Andrea Arcangeli: SYNACK carry ts_recent in tsecr.
+ *
+ */
+
+#include <net/tcp.h>
+
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+extern int sysctl_tcp_sack;
+
+/* People can turn this off for buggy TCP's found in printers etc. */
+int sysctl_tcp_retrans_collapse = 1;
+
+/* Get rid of any delayed acks, we sent one already.. */
+static __inline__ void clear_delayed_acks(struct sock * sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ tp->delayed_acks = 0;
+ if(tcp_in_quickack_mode(tp))
+ tcp_exit_quickack_mode(tp);
+ tcp_clear_xmit_timer(sk, TIME_DACK);
+}
+
+static __inline__ void update_send_head(struct sock *sk)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ tp->send_head = tp->send_head->next;
+ if (tp->send_head == (struct sk_buff *) &sk->write_queue)
+ tp->send_head = NULL;
+}
+
+/* This routine actually transmits TCP packets queued in by
+ * tcp_do_sendmsg(). This is used by both the initial
+ * transmission and possible later retransmissions.
+ * All SKB's seen here are completely headerless. It is our
+ * job to build the TCP header, and pass the packet down to
+ * IP so it can do the same plus pass the packet off to the
+ * device.
+ *
+ * We are working here with either a clone of the original
+ * SKB, or a fresh unique copy made by the retransmit engine.
+ */
+void tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+ if(skb != NULL) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
+ int tcp_header_size = tp->tcp_header_len;
+ struct tcphdr *th;
+ int sysctl_flags;
+
+#define SYSCTL_FLAG_TSTAMPS 0x1
+#define SYSCTL_FLAG_WSCALE 0x2
+#define SYSCTL_FLAG_SACK 0x4
+
+ sysctl_flags = 0;
+ if(tcb->flags & TCPCB_FLAG_SYN) {
+ tcp_header_size = sizeof(struct tcphdr) + TCPOLEN_MSS;
+ if(sysctl_tcp_timestamps) {
+ tcp_header_size += TCPOLEN_TSTAMP_ALIGNED;
+ sysctl_flags |= SYSCTL_FLAG_TSTAMPS;
+ }
+ if(sysctl_tcp_window_scaling) {
+ tcp_header_size += TCPOLEN_WSCALE_ALIGNED;
+ sysctl_flags |= SYSCTL_FLAG_WSCALE;
+ }
+ if(sysctl_tcp_sack) {
+ sysctl_flags |= SYSCTL_FLAG_SACK;
+ if(!(sysctl_flags & SYSCTL_FLAG_TSTAMPS))
+ tcp_header_size += TCPOLEN_SACKPERM_ALIGNED;
+ }
+ } else if(tp->sack_ok && tp->num_sacks) {
+ /* A SACK is 2 pad bytes, a 2 byte header, plus
+ * 2 32-bit sequence numbers for each SACK block.
+ */
+ tcp_header_size += (TCPOLEN_SACK_BASE_ALIGNED +
+ (tp->num_sacks * TCPOLEN_SACK_PERBLOCK));
+ }
+ th = (struct tcphdr *) skb_push(skb, tcp_header_size);
+ skb->h.th = th;
+ skb_set_owner_w(skb, sk);
+
+ /* Build TCP header and checksum it. */
+ th->source = sk->sport;
+ th->dest = sk->dport;
+ th->seq = htonl(TCP_SKB_CB(skb)->seq);
+ th->ack_seq = htonl(tp->rcv_nxt);
+ th->doff = (tcp_header_size >> 2);
+ th->res1 = 0;
+ *(((__u8 *)th) + 13) = tcb->flags;
+ if(!(tcb->flags & TCPCB_FLAG_SYN))
+ th->window = htons(tcp_select_window(sk));
+ th->check = 0;
+ th->urg_ptr = ntohs(tcb->urg_ptr);
+ if(tcb->flags & TCPCB_FLAG_SYN) {
+ /* RFC1323: The window in SYN & SYN/ACK segments
+ * is never scaled.
+ */
+ th->window = htons(tp->rcv_wnd);
+ tcp_syn_build_options((__u32 *)(th + 1), tp->mss_clamp,
+ (sysctl_flags & SYSCTL_FLAG_TSTAMPS),
+ (sysctl_flags & SYSCTL_FLAG_SACK),
+ (sysctl_flags & SYSCTL_FLAG_WSCALE),
+ tp->rcv_wscale,
+ TCP_SKB_CB(skb)->when,
+ tp->ts_recent);
+ } else {
+ tcp_build_and_update_options((__u32 *)(th + 1),
+ tp, TCP_SKB_CB(skb)->when);
+ }
+ tp->af_specific->send_check(sk, th, skb->len, skb);
+
+ clear_delayed_acks(sk);
+ tp->last_ack_sent = tp->rcv_nxt;
+ tcp_statistics.TcpOutSegs++;
+ tp->af_specific->queue_xmit(skb);
+ }
+#undef SYSCTL_FLAG_TSTAMPS
+#undef SYSCTL_FLAG_WSCALE
+#undef SYSCTL_FLAG_SACK
+}
+
+/* This is the main buffer sending routine. We queue the buffer
+ * and decide whether to queue or transmit now.
+ */
+void tcp_send_skb(struct sock *sk, struct sk_buff *skb, int force_queue)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Advance write_seq and place onto the write_queue. */
+ tp->write_seq += (TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq);
+ __skb_queue_tail(&sk->write_queue, skb);
+
+ if (!force_queue && tp->send_head == NULL && tcp_snd_test(sk, skb)) {
+ /* Send it out now. */
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ tp->packets_out++;
+ tcp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
+ if(!tcp_timer_is_set(sk, TIME_RETRANS))
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+ } else {
+ /* Queue it, remembering where we must start sending. */
+ if (tp->send_head == NULL)
+ tp->send_head = skb;
+ if (!force_queue && tp->packets_out == 0 && !tp->pending) {
+ tp->pending = TIME_PROBE0;
+ tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto);
+ }
+ }
+}
+
+/* Function to create two new TCP segments. Shrinks the given segment
+ * to the specified size and appends a new segment with the rest of the
+ * packet to the list. This won't be called frequently, I hope.
+ * Remember, these are still headerless SKBs at this point.
+ */
+static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
+{
+ struct sk_buff *buff;
+ int nsize = skb->len - len;
+ u16 flags;
+
+ /* Get a new skb... force flag on. */
+ buff = sock_wmalloc(sk,
+ (nsize + MAX_HEADER + sk->prot->max_header),
+ 1, GFP_ATOMIC);
+ if (buff == NULL)
+ return -1; /* We'll just try again later. */
+
+ /* Reserve space for headers. */
+ skb_reserve(buff, MAX_HEADER + sk->prot->max_header);
+
+ /* Correct the sequence numbers. */
+ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
+ TCP_SKB_CB(buff)->end_seq = TCP_SKB_CB(skb)->end_seq;
+
+ /* PSH and FIN should only be set in the second packet. */
+ flags = TCP_SKB_CB(skb)->flags;
+ TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN | TCPCB_FLAG_PSH);
+ if(flags & TCPCB_FLAG_URG) {
+ u16 old_urg_ptr = TCP_SKB_CB(skb)->urg_ptr;
+
+ /* Urgent data is always a pain in the ass. */
+ if(old_urg_ptr > len) {
+ TCP_SKB_CB(skb)->flags &= ~(TCPCB_FLAG_URG);
+ TCP_SKB_CB(skb)->urg_ptr = 0;
+ TCP_SKB_CB(buff)->urg_ptr = old_urg_ptr - len;
+ } else {
+ flags &= ~(TCPCB_FLAG_URG);
+ }
+ }
+ if(!(flags & TCPCB_FLAG_URG))
+ TCP_SKB_CB(buff)->urg_ptr = 0;
+ TCP_SKB_CB(buff)->flags = flags;
+ TCP_SKB_CB(buff)->sacked = 0;
+
+ /* Copy and checksum data tail into the new buffer. */
+ buff->csum = csum_partial_copy(skb->data + len, skb_put(buff, nsize),
+ nsize, 0);
+
+ /* This takes care of the FIN sequence number too. */
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(buff)->seq;
+ skb_trim(skb, len);
+
+ /* Rechecksum original buffer. */
+ skb->csum = csum_partial(skb->data, skb->len, 0);
+
+ /* Looks stupid, but our code really uses when of
+ * skbs, which it never sent before. --ANK
+ */
+ TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
+
+ /* Link BUFF into the send queue. */
+ __skb_append(skb, buff);
+
+ return 0;
+}
+
+/* This function synchronize snd mss to current pmtu/exthdr set.
+
+ tp->user_mss is mss set by user by TCP_MAXSEG. It does NOT counts
+ for TCP options, but includes only bare TCP header.
+
+ tp->mss_clamp is mss negotiated at connection setup.
+ It is minumum of user_mss and mss received with SYN.
+ It also does not include TCP options.
+
+ tp->pmtu_cookie is last pmtu, seen by this function.
+
+ tp->mss_cache is current effective sending mss, including
+ all tcp options except for SACKs. It is evaluated,
+ taking into account current pmtu, but never exceeds
+ tp->mss_clamp.
+
+ NOTE1. rfc1122 clearly states that advertised MSS
+ DOES NOT include either tcp or ip options.
+
+ NOTE2. tp->pmtu_cookie and tp->mss_cache are READ ONLY outside
+ this function. --ANK (980731)
+ */
+
+int tcp_sync_mss(struct sock *sk, u32 pmtu)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ int mss_now;
+
+ /* Calculate base mss without TCP options:
+ It is MMS_S - sizeof(tcphdr) of rfc1122
+ */
+ mss_now = pmtu - tp->af_specific->net_header_len - sizeof(struct tcphdr);
+
+ /* Clamp it (mss_clamp does not include tcp options) */
+ if (mss_now > tp->mss_clamp)
+ mss_now = tp->mss_clamp;
+
+ /* Now subtract TCP options size, not including SACKs */
+ mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
+
+ /* Now subtract optional transport overhead */
+ mss_now -= tp->ext_header_len;
+
+ /* It we got too small (or even negative) value,
+ clamp it by 8 from below. Why 8 ?
+ Well, it could be 1 with the same success,
+ but if IP accepted segment of length 1,
+ it would love 8 even more 8) --ANK (980731)
+ */
+ if (mss_now < 8)
+ mss_now = 8;
+
+ /* And store cached results */
+ tp->pmtu_cookie = pmtu;
+ tp->mss_cache = mss_now;
+ return mss_now;
+}
+
+
+/* This routine writes packets to the network. It advances the
+ * send_head. This happens as incoming acks open up the remote
+ * window for us.
+ */
+void tcp_write_xmit(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ unsigned int mss_now;
+
+ /* Account for SACKS, we may need to fragment due to this.
+ * It is just like the real MSS changing on us midstream.
+ * We also handle things correctly when the user adds some
+ * IP options mid-stream. Silly to do, but cover it.
+ */
+ mss_now = tcp_current_mss(sk);
+
+ /* If we are zapped, the bytes will have to remain here.
+ * In time closedown will empty the write queue and all
+ * will be happy.
+ */
+ if(!sk->zapped) {
+ struct sk_buff *skb;
+ int sent_pkts = 0;
+
+ /* Anything on the transmit queue that fits the window can
+ * be added providing we are:
+ *
+ * a) following SWS avoidance [and Nagle algorithm]
+ * b) not exceeding our congestion window.
+ * c) not retransmitting [Nagle]
+ */
+ while((skb = tp->send_head) && tcp_snd_test(sk, skb)) {
+ if (skb->len > mss_now) {
+ if (tcp_fragment(sk, skb, mss_now))
+ break;
+ }
+
+ /* Advance the send_head. This one is going out. */
+ update_send_head(sk);
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ tp->packets_out++;
+ tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+ sent_pkts = 1;
+ }
+
+ /* If we sent anything, make sure the retransmit
+ * timer is active.
+ */
+ if (sent_pkts && !tcp_timer_is_set(sk, TIME_RETRANS))
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+ }
+}
+
+/* This function returns the amount that we can raise the
+ * usable window based on the following constraints
+ *
+ * 1. The window can never be shrunk once it is offered (RFC 793)
+ * 2. We limit memory per socket
+ *
+ * RFC 1122:
+ * "the suggested [SWS] avoidance algorithm for the receiver is to keep
+ * RECV.NEXT + RCV.WIN fixed until:
+ * RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)"
+ *
+ * i.e. don't raise the right edge of the window until you can raise
+ * it at least MSS bytes.
+ *
+ * Unfortunately, the recommended algorithm breaks header prediction,
+ * since header prediction assumes th->window stays fixed.
+ *
+ * Strictly speaking, keeping th->window fixed violates the receiver
+ * side SWS prevention criteria. The problem is that under this rule
+ * a stream of single byte packets will cause the right side of the
+ * window to always advance by a single byte.
+ *
+ * Of course, if the sender implements sender side SWS prevention
+ * then this will not be a problem.
+ *
+ * BSD seems to make the following compromise:
+ *
+ * If the free space is less than the 1/4 of the maximum
+ * space available and the free space is less than 1/2 mss,
+ * then set the window to 0.
+ * Otherwise, just prevent the window from shrinking
+ * and from being larger than the largest representable value.
+ *
+ * This prevents incremental opening of the window in the regime
+ * where TCP is limited by the speed of the reader side taking
+ * data out of the TCP receive queue. It does nothing about
+ * those cases where the window is constrained on the sender side
+ * because the pipeline is full.
+ *
+ * BSD also seems to "accidentally" limit itself to windows that are a
+ * multiple of MSS, at least until the free space gets quite small.
+ * This would appear to be a side effect of the mbuf implementation.
+ * Combining these two algorithms results in the observed behavior
+ * of having a fixed window size at almost all times.
+ *
+ * Below we obtain similar behavior by forcing the offered window to
+ * a multiple of the mss when it is feasible to do so.
+ *
+ * Note, we don't "adjust" for TIMESTAMP or SACK option bytes.
+ */
+u32 __tcp_select_window(struct sock *sk)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ unsigned int mss = tp->mss_cache;
+ int free_space;
+ u32 window;
+
+ /* Sometimes free_space can be < 0. */
+ free_space = (sk->rcvbuf - atomic_read(&sk->rmem_alloc)) / 2;
+ if (tp->window_clamp) {
+ if (free_space > ((int) tp->window_clamp))
+ free_space = tp->window_clamp;
+ mss = min(tp->window_clamp, mss);
+ } else {
+ printk("tcp_select_window: tp->window_clamp == 0.\n");
+ }
+
+ if (mss < 1) {
+ mss = 1;
+ printk("tcp_select_window: sk->mss fell to 0.\n");
+ }
+
+ if ((free_space < (sk->rcvbuf/4)) && (free_space < ((int) (mss/2)))) {
+ window = 0;
+ tp->pred_flags = 0;
+ } else {
+ /* Get the largest window that is a nice multiple of mss.
+ * Window clamp already applied above.
+ * If our current window offering is within 1 mss of the
+ * free space we just keep it. This prevents the divide
+ * and multiply from happening most of the time.
+ * We also don't do any window rounding when the free space
+ * is too small.
+ */
+ window = tp->rcv_wnd;
+ if ((((int) window) <= (free_space - ((int) mss))) ||
+ (((int) window) > free_space))
+ window = (((unsigned int) free_space)/mss)*mss;
+ }
+ return window;
+}
+
+/* Attempt to collapse two adjacent SKB's during retransmission. */
+static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int mss_now)
+{
+ struct sk_buff *next_skb = skb->next;
+
+ /* The first test we must make is that neither of these two
+ * SKB's are still referenced by someone else.
+ */
+ if(!skb_cloned(skb) && !skb_cloned(next_skb)) {
+ int skb_size = skb->len, next_skb_size = next_skb->len;
+ u16 flags = TCP_SKB_CB(skb)->flags;
+
+ /* Punt if the first SKB has URG set. */
+ if(flags & TCPCB_FLAG_URG)
+ return;
+
+ /* Also punt if next skb has been SACK'd. */
+ if(TCP_SKB_CB(next_skb)->sacked & TCPCB_SACKED_ACKED)
+ return;
+
+ /* Punt if not enough space exists in the first SKB for
+ * the data in the second, or the total combined payload
+ * would exceed the MSS.
+ */
+ if ((next_skb_size > skb_tailroom(skb)) ||
+ ((skb_size + next_skb_size) > mss_now))
+ return;
+
+ /* Ok. We will be able to collapse the packet. */
+ __skb_unlink(next_skb, next_skb->list);
+
+ if(skb->len % 4) {
+ /* Must copy and rechecksum all data. */
+ memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size);
+ skb->csum = csum_partial(skb->data, skb->len, 0);
+ } else {
+ /* Optimize, actually we could also combine next_skb->csum
+ * to skb->csum using a single add w/carry operation too.
+ */
+ skb->csum = csum_partial_copy(next_skb->data,
+ skb_put(skb, next_skb_size),
+ next_skb_size, skb->csum);
+ }
+
+ /* Update sequence range on original skb. */
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(next_skb)->end_seq;
+
+ /* Merge over control information. */
+ flags |= TCP_SKB_CB(next_skb)->flags; /* This moves PSH/FIN etc. over */
+ if(flags & TCPCB_FLAG_URG) {
+ u16 urgptr = TCP_SKB_CB(next_skb)->urg_ptr;
+ TCP_SKB_CB(skb)->urg_ptr = urgptr + skb_size;
+ }
+ TCP_SKB_CB(skb)->flags = flags;
+
+ /* All done, get rid of second SKB and account for it so
+ * packet counting does not break.
+ */
+ kfree_skb(next_skb);
+ sk->tp_pinfo.af_tcp.packets_out--;
+ }
+}
+
+/* Do a simple retransmit without using the backoff mechanisms in
+ * tcp_timer. This is used for path mtu discovery.
+ * The socket is already locked here.
+ */
+void tcp_simple_retransmit(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb, *old_next_skb;
+ unsigned int mss = tcp_current_mss(sk);
+
+ /* Don't muck with the congestion window here. */
+ tp->dup_acks = 0;
+ tp->high_seq = tp->snd_nxt;
+ tp->retrans_head = NULL;
+
+ /* Input control flow will see that this was retransmitted
+ * and not use it for RTT calculation in the absence of
+ * the timestamp option.
+ */
+ for (old_next_skb = skb = skb_peek(&sk->write_queue);
+ ((skb != tp->send_head) &&
+ (skb != (struct sk_buff *)&sk->write_queue));
+ skb = skb->next) {
+ int resend_skb = 0;
+
+ /* Our goal is to push out the packets which we
+ * sent already, but are being chopped up now to
+ * account for the PMTU information we have.
+ *
+ * As we resend the queue, packets are fragmented
+ * into two pieces, and when we try to send the
+ * second piece it may be collapsed together with
+ * a subsequent packet, and so on. -DaveM
+ */
+ if (old_next_skb != skb || skb->len > mss)
+ resend_skb = 1;
+ old_next_skb = skb->next;
+ if (resend_skb != 0)
+ tcp_retransmit_skb(sk, skb);
+ }
+}
+
+static __inline__ void update_retrans_head(struct sock *sk)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ tp->retrans_head = tp->retrans_head->next;
+ if((tp->retrans_head == tp->send_head) ||
+ (tp->retrans_head == (struct sk_buff *) &sk->write_queue)) {
+ tp->retrans_head = NULL;
+ tp->rexmt_done = 1;
+ }
+}
+
+/* This retransmits one SKB. Policy decisions and retransmit queue
+ * state updates are done by the caller. Returns non-zero if an
+ * error occurred which prevented the send.
+ */
+int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ unsigned int cur_mss = tcp_current_mss(sk);
+
+ if(skb->len > cur_mss) {
+ if(tcp_fragment(sk, skb, cur_mss))
+ return 1; /* We'll try again later. */
+
+ /* New SKB created, account for it. */
+ tp->packets_out++;
+ }
+
+ /* Collapse two adjacent packets if worthwhile and we can. */
+ if(!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_SYN) &&
+ (skb->len < (cur_mss >> 1)) &&
+ (skb->next != tp->send_head) &&
+ (skb->next != (struct sk_buff *)&sk->write_queue) &&
+ (sysctl_tcp_retrans_collapse != 0))
+ tcp_retrans_try_collapse(sk, skb, cur_mss);
+
+ if(tp->af_specific->rebuild_header(sk))
+ return 1; /* Routing failure or similar. */
+
+ /* Some Solaris stacks overoptimize and ignore the FIN on a
+ * retransmit when old data is attached. So strip it off
+ * since it is cheap to do so and saves bytes on the network.
+ */
+ if(skb->len > 0 &&
+ (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+ tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
+ TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+ skb_trim(skb, 0);
+ skb->csum = 0;
+ }
+
+ /* Ok, we're gonna send it out, update state. */
+ TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_RETRANS;
+ tp->retrans_out++;
+
+ /* Make a copy, if the first transmission SKB clone we made
+ * is still in somebody's hands, else make a clone.
+ */
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ if(skb_cloned(skb))
+ skb = skb_copy(skb, GFP_ATOMIC);
+ else
+ skb = skb_clone(skb, GFP_ATOMIC);
+
+ tcp_transmit_skb(sk, skb);
+
+ /* Update global TCP statistics and return success. */
+ sk->prot->retransmits++;
+ tcp_statistics.TcpRetransSegs++;
+
+ return 0;
+}
+
+/* This gets called after a retransmit timeout, and the initially
+ * retransmitted data is acknowledged. It tries to continue
+ * resending the rest of the retransmit queue, until either
+ * we've sent it all or the congestion window limit is reached.
+ * If doing SACK, the first ACK which comes back for a timeout
+ * based retransmit packet might feed us FACK information again.
+ * If so, we use it to avoid unnecessarily retransmissions.
+ */
+void tcp_xmit_retransmit_queue(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+
+ if (tp->retrans_head == NULL &&
+ tp->rexmt_done == 0)
+ tp->retrans_head = skb_peek(&sk->write_queue);
+ if (tp->retrans_head == tp->send_head)
+ tp->retrans_head = NULL;
+
+ /* Each time, advance the retrans_head if we got
+ * a packet out or we skipped one because it was
+ * SACK'd. -DaveM
+ */
+ while ((skb = tp->retrans_head) != NULL) {
+ /* If it has been ack'd by a SACK block, we don't
+ * retransmit it.
+ */
+ if(!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) {
+ /* Send it out, punt if error occurred. */
+ if(tcp_retransmit_skb(sk, skb))
+ break;
+
+ update_retrans_head(sk);
+
+ /* Stop retransmitting if we've hit the congestion
+ * window limit.
+ */
+ if (tp->retrans_out >= tp->snd_cwnd)
+ break;
+ } else {
+ update_retrans_head(sk);
+ }
+ }
+}
+
+/* Using FACK information, retransmit all missing frames at the receiver
+ * up to the forward most SACK'd packet (tp->fackets_out) if the packet
+ * has not been retransmitted already.
+ */
+void tcp_fack_retransmit(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb = skb_peek(&sk->write_queue);
+ int packet_cnt = 0;
+
+ while((skb != NULL) &&
+ (skb != tp->send_head) &&
+ (skb != (struct sk_buff *)&sk->write_queue)) {
+ __u8 sacked = TCP_SKB_CB(skb)->sacked;
+
+ if(sacked & (TCPCB_SACKED_ACKED | TCPCB_SACKED_RETRANS))
+ goto next_packet;
+
+ /* Ok, retransmit it. */
+ if(tcp_retransmit_skb(sk, skb))
+ break;
+
+ if(tcp_packets_in_flight(tp) >= tp->snd_cwnd)
+ break;
+next_packet:
+ packet_cnt++;
+ if(packet_cnt >= tp->fackets_out)
+ break;
+ skb = skb->next;
+ }
+}
+
+/* Send a fin. The caller locks the socket for us. This cannot be
+ * allowed to fail queueing a FIN frame under any circumstances.
+ */
+void tcp_send_fin(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb = skb_peek_tail(&sk->write_queue);
+ unsigned int mss_now;
+
+ /* Optimization, tack on the FIN if we have a queue of
+ * unsent frames. But be careful about outgoing SACKS
+ * and IP options.
+ */
+ mss_now = tcp_current_mss(sk);
+
+ if((tp->send_head != NULL) && (skb->len < mss_now)) {
+ /* tcp_write_xmit() takes care of the rest. */
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
+ TCP_SKB_CB(skb)->end_seq++;
+ tp->write_seq++;
+
+ /* Special case to avoid Nagle bogosity. If this
+ * segment is the last segment, and it was queued
+ * due to Nagle/SWS-avoidance, send it out now.
+ */
+ if(tp->send_head == skb &&
+ !sk->nonagle &&
+ skb->len < (tp->mss_cache >> 1) &&
+ tp->packets_out &&
+ !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG)) {
+ update_send_head(sk);
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ tp->packets_out++;
+ tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+ if(!tcp_timer_is_set(sk, TIME_RETRANS))
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+ }
+ } else {
+ /* Socket is locked, keep trying until memory is available. */
+ do {
+ skb = sock_wmalloc(sk,
+ (MAX_HEADER +
+ sk->prot->max_header),
+ 1, GFP_KERNEL);
+ } while (skb == NULL);
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(skb, MAX_HEADER + sk->prot->max_header);
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
+ TCP_SKB_CB(skb)->sacked = 0;
+ TCP_SKB_CB(skb)->urg_ptr = 0;
+
+ /* FIN eats a sequence byte, write_seq advanced by tcp_send_skb(). */
+ TCP_SKB_CB(skb)->seq = tp->write_seq;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+ tcp_send_skb(sk, skb, 0);
+ }
+}
+
+/* We get here when a process closes a file descriptor (either due to
+ * an explicit close() or as a byproduct of exit()'ing) and there
+ * was unread data in the receive queue. This behavior is recommended
+ * by draft-ietf-tcpimpl-prob-03.txt section 3.10. -DaveM
+ */
+void tcp_send_active_reset(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+
+ /* NOTE: No TCP options attached and we never retransmit this. */
+ skb = alloc_skb(MAX_HEADER + sk->prot->max_header, GFP_KERNEL);
+ if (!skb)
+ return;
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(skb, MAX_HEADER + sk->prot->max_header);
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
+ TCP_SKB_CB(skb)->sacked = 0;
+ TCP_SKB_CB(skb)->urg_ptr = 0;
+
+ /* Send it off. */
+ TCP_SKB_CB(skb)->seq = tp->write_seq;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tcp_transmit_skb(sk, skb);
+}
+
+/* WARNING: This routine must only be called when we have already sent
+ * a SYN packet that crossed the incoming SYN that caused this routine
+ * to get called. If this assumption fails then the initial rcv_wnd
+ * and rcv_wscale values will not be correct.
+ */
+int tcp_send_synack(struct sock *sk)
+{
+ struct tcp_opt* tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff* skb;
+
+ skb = sock_wmalloc(sk, (MAX_HEADER + sk->prot->max_header),
+ 1, GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(skb, MAX_HEADER + sk->prot->max_header);
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_SYN);
+ TCP_SKB_CB(skb)->sacked = 0;
+ TCP_SKB_CB(skb)->urg_ptr = 0;
+
+ /* SYN eats a sequence byte. */
+ TCP_SKB_CB(skb)->seq = tp->snd_una;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+ __skb_queue_tail(&sk->write_queue, skb);
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tp->packets_out++;
+ tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+ return 0;
+}
+
+/*
+ * Prepare a SYN-ACK.
+ */
+struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
+ struct open_request *req, int mss)
+{
+ struct tcphdr *th;
+ int tcp_header_size;
+ struct sk_buff *skb;
+
+ skb = sock_wmalloc(sk, MAX_HEADER + sk->prot->max_header, 1, GFP_ATOMIC);
+ if (skb == NULL)
+ return NULL;
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, MAX_HEADER + sk->prot->max_header);
+
+ skb->dst = dst_clone(dst);
+
+ /* Don't offer more than they did.
+ * This way we don't have to memorize who said what.
+ * FIXME: maybe this should be changed for better performance
+ * with syncookies.
+ */
+ req->mss = min(mss, req->mss);
+ if (req->mss < 8) {
+ printk(KERN_DEBUG "initial req->mss below 8\n");
+ req->mss = 8;
+ }
+
+ tcp_header_size = (sizeof(struct tcphdr) + TCPOLEN_MSS +
+ (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0) +
+ (req->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
+ /* SACK_PERM is in the place of NOP NOP of TS */
+ ((req->sack_ok && !req->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
+ skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size);
+
+ memset(th, 0, sizeof(struct tcphdr));
+ th->syn = 1;
+ th->ack = 1;
+ th->source = sk->sport;
+ th->dest = req->rmt_port;
+ TCP_SKB_CB(skb)->seq = req->snt_isn;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+ th->seq = htonl(TCP_SKB_CB(skb)->seq);
+ th->ack_seq = htonl(req->rcv_isn + 1);
+ if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
+ __u8 rcv_wscale;
+ /* Set this up on the first call only */
+ req->window_clamp = skb->dst->window;
+ tcp_select_initial_window(sock_rspace(sk)/2,req->mss,
+ &req->rcv_wnd,
+ &req->window_clamp,
+ req->wscale_ok,
+ &rcv_wscale);
+ req->rcv_wscale = rcv_wscale;
+ }
+
+ /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
+ th->window = htons(req->rcv_wnd);
+
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tcp_syn_build_options((__u32 *)(th + 1), req->mss, req->tstamp_ok,
+ req->sack_ok, req->wscale_ok, req->rcv_wscale,
+ TCP_SKB_CB(skb)->when,
+ req->ts_recent);
+
+ skb->csum = 0;
+ th->doff = (tcp_header_size >> 2);
+ tcp_statistics.TcpOutSegs++;
+ return skb;
+}
+
+void tcp_connect(struct sock *sk, struct sk_buff *buff, int mtu)
+{
+ struct dst_entry *dst = sk->dst_cache;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Reserve space for headers. */
+ skb_reserve(buff, MAX_HEADER + sk->prot->max_header);
+
+ tp->snd_wnd = 0;
+ tp->snd_wl1 = 0;
+ tp->snd_wl2 = tp->write_seq;
+ tp->snd_una = tp->write_seq;
+ tp->rcv_nxt = 0;
+
+ sk->err = 0;
+
+ /* We'll fix this up when we get a response from the other end.
+ * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
+ */
+ tp->tcp_header_len = sizeof(struct tcphdr) +
+ (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
+
+ /* If user gave his TCP_MAXSEG, record it to clamp */
+ if (tp->user_mss)
+ tp->mss_clamp = tp->user_mss;
+ tcp_sync_mss(sk, mtu);
+
+ /* Now unpleasant action: if initial pmtu is too low
+ set lower clamp. I am not sure that it is good.
+ To be more exact, I do not think that clamping at value, which
+ is apparently transient and may improve in future is good idea.
+ It would be better to wait until peer will returns its MSS
+ (probably 65535 too) and now advertise something sort of 65535
+ or at least first hop device mtu. Is it clear, what I mean?
+ We should tell peer what maximal mss we expect to RECEIVE,
+ it has nothing to do with pmtu.
+ I am afraid someone will be confused by such huge value.
+ --ANK (980731)
+ */
+ if (tp->mss_cache + tp->tcp_header_len - sizeof(struct tcphdr) < tp->mss_clamp )
+ tp->mss_clamp = tp->mss_cache + tp->tcp_header_len - sizeof(struct tcphdr);
+
+ TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
+ TCP_SKB_CB(buff)->sacked = 0;
+ TCP_SKB_CB(buff)->urg_ptr = 0;
+ buff->csum = 0;
+ TCP_SKB_CB(buff)->seq = tp->write_seq++;
+ TCP_SKB_CB(buff)->end_seq = tp->write_seq;
+ tp->snd_nxt = TCP_SKB_CB(buff)->end_seq;
+
+ tp->window_clamp = dst->window;
+ tcp_select_initial_window(sock_rspace(sk)/2,tp->mss_clamp,
+ &tp->rcv_wnd,
+ &tp->window_clamp,
+ sysctl_tcp_window_scaling,
+ &tp->rcv_wscale);
+ /* Ok, now lock the socket before we make it visible to
+ * the incoming packet engine.
+ */
+ lock_sock(sk);
+
+ /* Socket identity change complete, no longer
+ * in TCP_CLOSE, so enter ourselves into the
+ * hash tables.
+ */
+ tcp_set_state(sk,TCP_SYN_SENT);
+ sk->prot->hash(sk);
+
+ tp->rto = dst->rtt;
+ tcp_init_xmit_timers(sk);
+ tp->retransmits = 0;
+ tp->fackets_out = 0;
+ tp->retrans_out = 0;
+
+ /* Send it off. */
+ __skb_queue_tail(&sk->write_queue, buff);
+ TCP_SKB_CB(buff)->when = tcp_time_stamp;
+ tp->packets_out++;
+ tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL));
+ tcp_statistics.TcpActiveOpens++;
+
+ /* Timer for repeating the SYN until an answer. */
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+
+ /* Now, it is safe to release the socket. */
+ release_sock(sk);
+}
+
+/* Send out a delayed ack, the caller does the policy checking
+ * to see if we should even be here. See tcp_input.c:tcp_ack_snd_check()
+ * for details.
+ */
+void tcp_send_delayed_ack(struct tcp_opt *tp, int max_timeout)
+{
+ unsigned long timeout;
+
+ /* Stay within the limit we were given */
+ timeout = tp->ato;
+ if (timeout > max_timeout)
+ timeout = max_timeout;
+ timeout += jiffies;
+
+ /* Use new timeout only if there wasn't a older one earlier. */
+ if (!tp->delack_timer.prev) {
+ tp->delack_timer.expires = timeout;
+ add_timer(&tp->delack_timer);
+ } else {
+ if (time_before(timeout, tp->delack_timer.expires))
+ mod_timer(&tp->delack_timer, timeout);
+ }
+}
+
+/* This routine sends an ack and also updates the window. */
+void tcp_send_ack(struct sock *sk)
+{
+ /* If we have been reset, we may not send again. */
+ if(!sk->zapped) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *buff;
+
+ /* We are not putting this on the write queue, so
+ * tcp_transmit_skb() will set the ownership to this
+ * sock.
+ */
+ buff = alloc_skb(MAX_HEADER + sk->prot->max_header, GFP_ATOMIC);
+ if (buff == NULL) {
+ /* Force it to send an ack. We don't have to do this
+ * (ACK is unreliable) but it's much better use of
+ * bandwidth on slow links to send a spare ack than
+ * resend packets.
+ *
+ * This is the one possible way that we can delay an
+ * ACK and have tp->ato indicate that we are in
+ * quick ack mode, so clear it.
+ */
+ if(tcp_in_quickack_mode(tp))
+ tcp_exit_quickack_mode(tp);
+ tcp_send_delayed_ack(tp, HZ/2);
+ return;
+ }
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(buff, MAX_HEADER + sk->prot->max_header);
+ buff->csum = 0;
+ TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
+ TCP_SKB_CB(buff)->sacked = 0;
+ TCP_SKB_CB(buff)->urg_ptr = 0;
+
+ /* Send it off, this clears delayed acks for us. */
+ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tp->snd_nxt;
+ TCP_SKB_CB(buff)->when = tcp_time_stamp;
+ tcp_transmit_skb(sk, buff);
+ }
+}
+
+/* This routine sends a packet with an out of date sequence
+ * number. It assumes the other end will try to ack it.
+ */
+void tcp_write_wakeup(struct sock *sk)
+{
+ /* After a valid reset we can send no more. */
+ if (!sk->zapped) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+
+ /* Write data can still be transmitted/retransmitted in the
+ * following states. If any other state is encountered, return.
+ * [listen/close will never occur here anyway]
+ */
+ if ((1 << sk->state) &
+ ~(TCPF_ESTABLISHED|TCPF_CLOSE_WAIT|TCPF_FIN_WAIT1|
+ TCPF_LAST_ACK|TCPF_CLOSING))
+ return;
+
+ if (before(tp->snd_nxt, tp->snd_una + tp->snd_wnd) &&
+ ((skb = tp->send_head) != NULL)) {
+ unsigned long win_size;
+
+ /* We are probing the opening of a window
+ * but the window size is != 0
+ * must have been a result SWS avoidance ( sender )
+ */
+ win_size = tp->snd_wnd - (tp->snd_nxt - tp->snd_una);
+ if (win_size < TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq) {
+ if (tcp_fragment(sk, skb, win_size))
+ return; /* Let a retransmit get it. */
+ }
+ update_send_head(sk);
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ tp->packets_out++;
+ tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+ if (!tcp_timer_is_set(sk, TIME_RETRANS))
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+ } else {
+ /* We don't queue it, tcp_transmit_skb() sets ownership. */
+ skb = alloc_skb(MAX_HEADER + sk->prot->max_header,
+ GFP_ATOMIC);
+ if (skb == NULL)
+ return;
+
+ /* Reserve space for headers and set control bits. */
+ skb_reserve(skb, MAX_HEADER + sk->prot->max_header);
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
+ TCP_SKB_CB(skb)->sacked = 0;
+ TCP_SKB_CB(skb)->urg_ptr = 0;
+
+ /* Use a previous sequence. This should cause the other
+ * end to send an ack. Don't queue or clone SKB, just
+ * send it.
+ */
+ TCP_SKB_CB(skb)->seq = tp->snd_nxt - 1;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tcp_transmit_skb(sk, skb);
+ }
+ }
+}
+
+/* A window probe timeout has occurred. If window is not closed send
+ * a partial packet else a zero probe.
+ */
+void tcp_send_probe0(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ tcp_write_wakeup(sk);
+ tp->pending = TIME_PROBE0;
+ tp->backoff++;
+ tp->probes_out++;
+ tcp_reset_xmit_timer (sk, TIME_PROBE0,
+ min(tp->rto << tp->backoff, 120*HZ));
+}
diff --git a/pfinet/linux-src/net/ipv4/tcp_timer.c b/pfinet/linux-src/net/ipv4/tcp_timer.c
new file mode 100644
index 00000000..21029f8e
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/tcp_timer.c
@@ -0,0 +1,595 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id: tcp_timer.c,v 1.62.2.3 1999/06/20 20:14:30 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ * Linus Torvalds, <torvalds@cs.helsinki.fi>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Matthew Dillon, <dillon@apollo.west.oic.com>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+#include <net/tcp.h>
+
+int sysctl_tcp_syn_retries = TCP_SYN_RETRIES;
+int sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
+int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
+int sysctl_tcp_retries1 = TCP_RETR1;
+int sysctl_tcp_retries2 = TCP_RETR2;
+
+static void tcp_sltimer_handler(unsigned long);
+static void tcp_syn_recv_timer(unsigned long);
+static void tcp_keepalive(unsigned long data);
+static void tcp_twkill(unsigned long);
+
+struct timer_list tcp_slow_timer = {
+ NULL, NULL,
+ 0, 0,
+ tcp_sltimer_handler,
+};
+
+
+struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX] = {
+ {ATOMIC_INIT(0), TCP_SYNACK_PERIOD, 0, tcp_syn_recv_timer},/* SYNACK */
+ {ATOMIC_INIT(0), TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive}, /* KEEPALIVE */
+ {ATOMIC_INIT(0), TCP_TWKILL_PERIOD, 0, tcp_twkill} /* TWKILL */
+};
+
+const char timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
+
+/*
+ * Using different timers for retransmit, delayed acks and probes
+ * We may wish use just one timer maintaining a list of expire jiffies
+ * to optimize.
+ */
+
+void tcp_init_xmit_timers(struct sock *sk)
+{
+ init_timer(&sk->tp_pinfo.af_tcp.retransmit_timer);
+ sk->tp_pinfo.af_tcp.retransmit_timer.function=&tcp_retransmit_timer;
+ sk->tp_pinfo.af_tcp.retransmit_timer.data = (unsigned long) sk;
+
+ init_timer(&sk->tp_pinfo.af_tcp.delack_timer);
+ sk->tp_pinfo.af_tcp.delack_timer.function=&tcp_delack_timer;
+ sk->tp_pinfo.af_tcp.delack_timer.data = (unsigned long) sk;
+
+ init_timer(&sk->tp_pinfo.af_tcp.probe_timer);
+ sk->tp_pinfo.af_tcp.probe_timer.function=&tcp_probe_timer;
+ sk->tp_pinfo.af_tcp.probe_timer.data = (unsigned long) sk;
+}
+
+/*
+ * Reset the retransmission timer
+ */
+
+void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ switch (what) {
+ case TIME_RETRANS:
+ /* When seting the transmit timer the probe timer
+ * should not be set.
+ * The delayed ack timer can be set if we are changing the
+ * retransmit timer when removing acked frames.
+ */
+ if(tp->probe_timer.prev)
+ del_timer(&tp->probe_timer);
+ mod_timer(&tp->retransmit_timer, jiffies+when);
+ break;
+
+ case TIME_DACK:
+ mod_timer(&tp->delack_timer, jiffies+when);
+ break;
+
+ case TIME_PROBE0:
+ mod_timer(&tp->probe_timer, jiffies+when);
+ break;
+
+ case TIME_WRITE:
+ printk(KERN_DEBUG "bug: tcp_reset_xmit_timer TIME_WRITE\n");
+ break;
+
+ default:
+ printk(KERN_DEBUG "bug: unknown timer value\n");
+ };
+}
+
+void tcp_clear_xmit_timers(struct sock *sk)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ if(tp->retransmit_timer.prev)
+ del_timer(&tp->retransmit_timer);
+ if(tp->delack_timer.prev)
+ del_timer(&tp->delack_timer);
+ if(tp->probe_timer.prev)
+ del_timer(&tp->probe_timer);
+}
+
+static int tcp_write_err(struct sock *sk, int force)
+{
+ sk->err = sk->err_soft ? sk->err_soft : ETIMEDOUT;
+ sk->error_report(sk);
+
+ tcp_clear_xmit_timers(sk);
+
+ /* Time wait the socket. */
+ if (!force && ((1<<sk->state) & (TCPF_FIN_WAIT1|TCPF_FIN_WAIT2|TCPF_CLOSING))) {
+ tcp_time_wait(sk);
+ } else {
+ /* Clean up time. */
+ tcp_set_state(sk, TCP_CLOSE);
+ return 0;
+ }
+ return 1;
+}
+
+/* A write timeout has occurred. Process the after effects. */
+static int tcp_write_timeout(struct sock *sk)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Look for a 'soft' timeout. */
+ if ((sk->state == TCP_ESTABLISHED &&
+ tp->retransmits && (tp->retransmits % TCP_QUICK_TRIES) == 0) ||
+ (sk->state != TCP_ESTABLISHED && tp->retransmits > sysctl_tcp_retries1)) {
+ dst_negative_advice(&sk->dst_cache);
+ }
+
+ /* Have we tried to SYN too many times (repent repent 8)) */
+ if(tp->retransmits > sysctl_tcp_syn_retries && sk->state==TCP_SYN_SENT) {
+ tcp_write_err(sk, 1);
+ /* Don't FIN, we got nothing back */
+ return 0;
+ }
+
+ /* Has it gone just too far? */
+ if (tp->retransmits > sysctl_tcp_retries2)
+ return tcp_write_err(sk, 0);
+
+ return 1;
+}
+
+void tcp_delack_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock*)data;
+
+ if(!sk->zapped &&
+ sk->tp_pinfo.af_tcp.delayed_acks &&
+ sk->state != TCP_CLOSE) {
+ /* If socket is currently locked, defer the ACK. */
+ if (!atomic_read(&sk->sock_readers))
+ tcp_send_ack(sk);
+ else
+ tcp_send_delayed_ack(&(sk->tp_pinfo.af_tcp), HZ/10);
+ }
+}
+
+void tcp_probe_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock*)data;
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ if(sk->zapped)
+ return;
+
+ if (atomic_read(&sk->sock_readers)) {
+ /* Try again later. */
+ tcp_reset_xmit_timer(sk, TIME_PROBE0, HZ/5);
+ return;
+ }
+
+ /* *WARNING* RFC 1122 forbids this
+ * It doesn't AFAIK, because we kill the retransmit timer -AK
+ * FIXME: We ought not to do it, Solaris 2.5 actually has fixing
+ * this behaviour in Solaris down as a bug fix. [AC]
+ */
+ if (tp->probes_out > sysctl_tcp_retries2) {
+ if(sk->err_soft)
+ sk->err = sk->err_soft;
+ else
+ sk->err = ETIMEDOUT;
+ sk->error_report(sk);
+
+ if ((1<<sk->state) & (TCPF_FIN_WAIT1|TCPF_FIN_WAIT2|TCPF_CLOSING)) {
+ /* Time wait the socket. */
+ tcp_time_wait(sk);
+ } else {
+ /* Clean up time. */
+ tcp_set_state(sk, TCP_CLOSE);
+ }
+ } else {
+ /* Only send another probe if we didn't close things up. */
+ tcp_send_probe0(sk);
+ }
+}
+
+static __inline__ int tcp_keepopen_proc(struct sock *sk)
+{
+ int res = 0;
+
+ if ((1<<sk->state) & (TCPF_ESTABLISHED|TCPF_CLOSE_WAIT|TCPF_FIN_WAIT2)) {
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp;
+
+ if (elapsed >= sysctl_tcp_keepalive_time) {
+ if (tp->probes_out > sysctl_tcp_keepalive_probes) {
+ if(sk->err_soft)
+ sk->err = sk->err_soft;
+ else
+ sk->err = ETIMEDOUT;
+
+ tcp_set_state(sk, TCP_CLOSE);
+ sk->shutdown = SHUTDOWN_MASK;
+ if (!sk->dead)
+ sk->state_change(sk);
+ } else {
+ tp->probes_out++;
+ tp->pending = TIME_KEEPOPEN;
+ tcp_write_wakeup(sk);
+ res = 1;
+ }
+ }
+ }
+ return res;
+}
+
+/* Kill off TIME_WAIT sockets once their lifetime has expired. */
+int tcp_tw_death_row_slot = 0;
+static struct tcp_tw_bucket *tcp_tw_death_row[TCP_TWKILL_SLOTS] =
+ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+extern void tcp_timewait_kill(struct tcp_tw_bucket *tw);
+
+static void tcp_twkill(unsigned long data)
+{
+ struct tcp_tw_bucket *tw;
+ int killed = 0;
+
+ tw = tcp_tw_death_row[tcp_tw_death_row_slot];
+ tcp_tw_death_row[tcp_tw_death_row_slot] = NULL;
+ while(tw != NULL) {
+ struct tcp_tw_bucket *next = tw->next_death;
+
+ tcp_timewait_kill(tw);
+ killed++;
+ tw = next;
+ }
+ if(killed != 0) {
+ struct tcp_sl_timer *slt = (struct tcp_sl_timer *)data;
+ atomic_sub(killed, &slt->count);
+ }
+ tcp_tw_death_row_slot =
+ ((tcp_tw_death_row_slot + 1) & (TCP_TWKILL_SLOTS - 1));
+}
+
+/* These are always called from BH context. See callers in
+ * tcp_input.c to verify this.
+ */
+void tcp_tw_schedule(struct tcp_tw_bucket *tw)
+{
+ int slot = (tcp_tw_death_row_slot - 1) & (TCP_TWKILL_SLOTS - 1);
+ struct tcp_tw_bucket **tpp = &tcp_tw_death_row[slot];
+
+ if((tw->next_death = *tpp) != NULL)
+ (*tpp)->pprev_death = &tw->next_death;
+ *tpp = tw;
+ tw->pprev_death = tpp;
+
+ tw->death_slot = slot;
+
+ tcp_inc_slow_timer(TCP_SLT_TWKILL);
+}
+
+/* Happens rarely if at all, no care about scalability here. */
+void tcp_tw_reschedule(struct tcp_tw_bucket *tw)
+{
+ struct tcp_tw_bucket **tpp;
+ int slot;
+
+ if(tw->next_death)
+ tw->next_death->pprev_death = tw->pprev_death;
+ *tw->pprev_death = tw->next_death;
+ tw->pprev_death = NULL;
+
+ slot = (tcp_tw_death_row_slot - 1) & (TCP_TWKILL_SLOTS - 1);
+ tpp = &tcp_tw_death_row[slot];
+ if((tw->next_death = *tpp) != NULL)
+ (*tpp)->pprev_death = &tw->next_death;
+ *tpp = tw;
+ tw->pprev_death = tpp;
+
+ tw->death_slot = slot;
+ /* Timer was incremented when we first entered the table. */
+}
+
+/* This is for handling early-kills of TIME_WAIT sockets. */
+void tcp_tw_deschedule(struct tcp_tw_bucket *tw)
+{
+ if(tw->next_death)
+ tw->next_death->pprev_death = tw->pprev_death;
+ *tw->pprev_death = tw->next_death;
+ tw->pprev_death = NULL;
+ tcp_dec_slow_timer(TCP_SLT_TWKILL);
+}
+
+/*
+ * Check all sockets for keepalive timer
+ * Called every 75 seconds
+ * This timer is started by af_inet init routine and is constantly
+ * running.
+ *
+ * It might be better to maintain a count of sockets that need it using
+ * setsockopt/tcp_destroy_sk and only set the timer when needed.
+ */
+
+/*
+ * don't send over 5 keepopens at a time to avoid burstiness
+ * on big servers [AC]
+ */
+#define MAX_KA_PROBES 5
+
+int sysctl_tcp_max_ka_probes = MAX_KA_PROBES;
+
+/* Keepopen's are only valid for "established" TCP's, nicely our listener
+ * hash gets rid of most of the useless testing, so we run through a couple
+ * of the established hash chains each clock tick. -DaveM
+ *
+ * And now, even more magic... TIME_WAIT TCP's cannot have keepalive probes
+ * going off for them, so we only need check the first half of the established
+ * hash table, even less testing under heavy load.
+ *
+ * I _really_ would rather do this by adding a new timer_struct to struct sock,
+ * and this way only those who set the keepalive option will get the overhead.
+ * The idea is you set it for 2 hours when the sock is first connected, when it
+ * does fire off (if at all, most sockets die earlier) you check for the keepalive
+ * option and also if the sock has been idle long enough to start probing.
+ */
+static void tcp_keepalive(unsigned long data)
+{
+ static int chain_start = 0;
+ int count = 0;
+ int i;
+
+ for(i = chain_start; i < (chain_start + ((TCP_HTABLE_SIZE/2) >> 2)); i++) {
+ struct sock *sk = tcp_established_hash[i];
+ while(sk) {
+ if(!atomic_read(&sk->sock_readers) && sk->keepopen) {
+ count += tcp_keepopen_proc(sk);
+ if(count == sysctl_tcp_max_ka_probes)
+ goto out;
+ }
+ sk = sk->next;
+ }
+ }
+out:
+ chain_start = ((chain_start + ((TCP_HTABLE_SIZE/2)>>2)) &
+ ((TCP_HTABLE_SIZE/2) - 1));
+}
+
+/*
+ * The TCP retransmit timer. This lacks a few small details.
+ *
+ * 1. An initial rtt timeout on the probe0 should cause what we can
+ * of the first write queue buffer to be split and sent.
+ * 2. On a 'major timeout' as defined by RFC1122 we shouldn't report
+ * ETIMEDOUT if we know an additional 'soft' error caused this.
+ * tcp_err should save a 'soft error' for us.
+ * [Unless someone has broken it then it does, except for one 2.0
+ * broken case of a send when the route/device is directly unreachable,
+ * and we error but should retry! - FIXME] [AC]
+ */
+
+void tcp_retransmit_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock*)data;
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ /* We are reset. We will send no more retransmits. */
+ if(sk->zapped) {
+ tcp_clear_xmit_timer(sk, TIME_RETRANS);
+ return;
+ }
+
+ if (atomic_read(&sk->sock_readers)) {
+ /* Try again later */
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, HZ/20);
+ return;
+ }
+
+ /* Clear delay ack timer. */
+ tcp_clear_xmit_timer(sk, TIME_DACK);
+
+ /* RFC 2018, clear all 'sacked' flags in retransmission queue,
+ * the sender may have dropped out of order frames and we must
+ * send them out should this timer fire on us.
+ */
+ if(tp->sack_ok) {
+ struct sk_buff *skb = skb_peek(&sk->write_queue);
+
+ while((skb != NULL) &&
+ (skb != tp->send_head) &&
+ (skb != (struct sk_buff *)&sk->write_queue)) {
+ TCP_SKB_CB(skb)->sacked &=
+ ~(TCPCB_SACKED_ACKED | TCPCB_SACKED_RETRANS);
+ skb = skb->next;
+ }
+ }
+
+ /* Retransmission. */
+ tp->retrans_head = NULL;
+ tp->rexmt_done = 0;
+ tp->fackets_out = 0;
+ tp->retrans_out = 0;
+ if (tp->retransmits == 0) {
+ /* Remember window where we lost:
+ * "one half of the current window but at least 2 segments"
+ *
+ * Here "current window" means the effective one, which
+ * means it must be an accurate representation of our current
+ * sending rate _and_ the snd_wnd.
+ */
+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ tp->snd_cwnd_cnt = 0;
+ tp->snd_cwnd = 1;
+ }
+
+ tp->retransmits++;
+
+ tp->dup_acks = 0;
+ tp->high_seq = tp->snd_nxt;
+ tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+
+ /* Increase the timeout each time we retransmit. Note that
+ * we do not increase the rtt estimate. rto is initialized
+ * from rtt, but increases here. Jacobson (SIGCOMM 88) suggests
+ * that doubling rto each time is the least we can get away with.
+ * In KA9Q, Karn uses this for the first few times, and then
+ * goes to quadratic. netBSD doubles, but only goes up to *64,
+ * and clamps at 1 to 64 sec afterwards. Note that 120 sec is
+ * defined in the protocol as the maximum possible RTT. I guess
+ * we'll have to use something other than TCP to talk to the
+ * University of Mars.
+ *
+ * PAWS allows us longer timeouts and large windows, so once
+ * implemented ftp to mars will work nicely. We will have to fix
+ * the 120 second clamps though!
+ */
+ tp->backoff++;
+ tp->rto = min(tp->rto << 1, 120*HZ);
+ tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+
+ tcp_write_timeout(sk);
+}
+
+/*
+ * Slow timer for SYN-RECV sockets
+ */
+
+/* This now scales very nicely. -DaveM */
+static void tcp_syn_recv_timer(unsigned long data)
+{
+ struct sock *sk;
+ unsigned long now = jiffies;
+ int i;
+
+ for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
+ sk = tcp_listening_hash[i];
+
+ while(sk) {
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ /* TCP_LISTEN is implied. */
+ if (!atomic_read(&sk->sock_readers) && tp->syn_wait_queue) {
+ struct open_request *prev = (struct open_request *)(&tp->syn_wait_queue);
+ struct open_request *req = tp->syn_wait_queue;
+ do {
+ struct open_request *conn;
+
+ conn = req;
+ req = req->dl_next;
+
+ if (conn->sk ||
+ ((long)(now - conn->expires)) <= 0) {
+ prev = conn;
+ continue;
+ }
+
+ tcp_synq_unlink(tp, conn, prev);
+ if (conn->retrans >= sysctl_tcp_retries1) {
+#ifdef TCP_DEBUG
+ printk(KERN_DEBUG "syn_recv: "
+ "too many retransmits\n");
+#endif
+ (*conn->class->destructor)(conn);
+ tcp_dec_slow_timer(TCP_SLT_SYNACK);
+ tp->syn_backlog--;
+ tcp_openreq_free(conn);
+
+ if (!tp->syn_wait_queue)
+ break;
+ } else {
+ unsigned long timeo;
+ struct open_request *op;
+
+ (*conn->class->rtx_syn_ack)(sk, conn);
+
+ conn->retrans++;
+#ifdef TCP_DEBUG
+ printk(KERN_DEBUG "syn_ack rtx %d\n",
+ conn->retrans);
+#endif
+ timeo = min((TCP_TIMEOUT_INIT
+ << conn->retrans),
+ 120*HZ);
+ conn->expires = now + timeo;
+ op = prev->dl_next;
+ tcp_synq_queue(tp, conn);
+ if (op != prev->dl_next)
+ prev = prev->dl_next;
+ }
+ /* old prev still valid here */
+ } while (req);
+ }
+ sk = sk->next;
+ }
+ }
+}
+
+void tcp_sltimer_handler(unsigned long data)
+{
+ struct tcp_sl_timer *slt = tcp_slt_array;
+ unsigned long next = ~0UL;
+ unsigned long now = jiffies;
+ int i;
+
+ for (i=0; i < TCP_SLT_MAX; i++, slt++) {
+ if (atomic_read(&slt->count)) {
+ long trigger;
+
+ trigger = slt->period - ((long)(now - slt->last));
+
+ if (trigger <= 0) {
+ (*slt->handler)((unsigned long) slt);
+ slt->last = now;
+ trigger = slt->period;
+ }
+
+ /* Only reschedule if some events remain. */
+ if (atomic_read(&slt->count))
+ next = min(next, trigger);
+ }
+ }
+ if (next != ~0UL)
+ mod_timer(&tcp_slow_timer, (now + next));
+}
+
+void __tcp_inc_slow_timer(struct tcp_sl_timer *slt)
+{
+ unsigned long now = jiffies;
+ unsigned long when;
+
+ slt->last = now;
+
+ when = now + slt->period;
+
+ if (tcp_slow_timer.prev) {
+ if ((long)(tcp_slow_timer.expires - when) >= 0)
+ mod_timer(&tcp_slow_timer, when);
+ } else {
+ tcp_slow_timer.expires = when;
+ add_timer(&tcp_slow_timer);
+ }
+}
diff --git a/pfinet/linux-src/net/ipv4/timer.c b/pfinet/linux-src/net/ipv4/timer.c
new file mode 100644
index 00000000..3821a7c4
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/timer.c
@@ -0,0 +1,127 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * TIMER - implementation of software timers for IP.
+ *
+ * Version: $Id: timer.c,v 1.15 1999/02/22 13:54:29 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ *
+ * Fixes:
+ * Alan Cox : To avoid destroying a wait queue as we use it
+ * we defer destruction until the destroy timer goes
+ * off.
+ * Alan Cox : Destroy socket doesn't write a status value to the
+ * socket buffer _AFTER_ freeing it! Also sock ensures
+ * the socket will get removed BEFORE this is called
+ * otherwise if the timer TIME_DESTROY occurs inside
+ * of inet_bh() with this socket being handled it goes
+ * BOOM! Have to stop timer going off if net_bh is
+ * active or the destroy causes crashes.
+ * Alan Cox : Cleaned up unused code.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <asm/system.h>
+#include <linux/interrupt.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/arp.h>
+
+void net_delete_timer (struct sock *t)
+{
+ if(t->timer.prev)
+ del_timer (&t->timer);
+ t->timeout = 0;
+}
+
+void net_reset_timer (struct sock *t, int timeout, unsigned long len)
+{
+ t->timeout = timeout;
+ mod_timer(&t->timer, jiffies+len);
+}
+
+/* Now we will only be called whenever we need to do
+ * something, but we must be sure to process all of the
+ * sockets that need it.
+ */
+void net_timer (unsigned long data)
+{
+ struct sock *sk = (struct sock*)data;
+ int why = sk->timeout;
+
+ /* Only process if socket is not in use. */
+ if (atomic_read(&sk->sock_readers)) {
+ /* Try again later. */
+ mod_timer(&sk->timer, jiffies+HZ/20);
+ return;
+ }
+
+ /* Always see if we need to send an ack. */
+ if (sk->tp_pinfo.af_tcp.delayed_acks && !sk->zapped) {
+ sk->prot->read_wakeup (sk);
+ if (!sk->dead)
+ sk->data_ready(sk,0);
+ }
+
+ /* Now we need to figure out why the socket was on the timer. */
+ switch (why) {
+ case TIME_DONE:
+ /* If the socket hasn't been closed off, re-try a bit later. */
+ if (!sk->dead) {
+ net_reset_timer(sk, TIME_DONE, TCP_DONE_TIME);
+ break;
+ }
+
+ if (sk->state != TCP_CLOSE) {
+ printk (KERN_DEBUG "non CLOSE socket in time_done\n");
+ break;
+ }
+ destroy_sock (sk);
+ break;
+
+ case TIME_DESTROY:
+ /* We've waited for a while for all the memory associated with
+ * the socket to be freed.
+ */
+ destroy_sock(sk);
+ break;
+
+ case TIME_CLOSE:
+ /* We've waited long enough, close the socket. */
+ tcp_set_state(sk, TCP_CLOSE);
+ sk->shutdown = SHUTDOWN_MASK;
+ if (!sk->dead)
+ sk->state_change(sk);
+ net_reset_timer (sk, TIME_DONE, TCP_DONE_TIME);
+ break;
+
+ default:
+ /* I want to see these... */
+ printk ("net_timer: timer expired - reason %d is unknown\n", why);
+ break;
+ }
+}
+
diff --git a/pfinet/linux-src/net/ipv4/udp.c b/pfinet/linux-src/net/ipv4/udp.c
new file mode 100644
index 00000000..909e858f
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/udp.c
@@ -0,0 +1,1191 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * The User Datagram Protocol (UDP).
+ *
+ * Version: $Id: udp.c,v 1.66.2.3 1999/08/07 10:56:36 davem Exp $
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Alan Cox, <Alan.Cox@linux.org>
+ *
+ * Fixes:
+ * Alan Cox : verify_area() calls
+ * Alan Cox : stopped close while in use off icmp
+ * messages. Not a fix but a botch that
+ * for udp at least is 'valid'.
+ * Alan Cox : Fixed icmp handling properly
+ * Alan Cox : Correct error for oversized datagrams
+ * Alan Cox : Tidied select() semantics.
+ * Alan Cox : udp_err() fixed properly, also now
+ * select and read wake correctly on errors
+ * Alan Cox : udp_send verify_area moved to avoid mem leak
+ * Alan Cox : UDP can count its memory
+ * Alan Cox : send to an unknown connection causes
+ * an ECONNREFUSED off the icmp, but
+ * does NOT close.
+ * Alan Cox : Switched to new sk_buff handlers. No more backlog!
+ * Alan Cox : Using generic datagram code. Even smaller and the PEEK
+ * bug no longer crashes it.
+ * Fred Van Kempen : Net2e support for sk->broadcast.
+ * Alan Cox : Uses skb_free_datagram
+ * Alan Cox : Added get/set sockopt support.
+ * Alan Cox : Broadcasting without option set returns EACCES.
+ * Alan Cox : No wakeup calls. Instead we now use the callbacks.
+ * Alan Cox : Use ip_tos and ip_ttl
+ * Alan Cox : SNMP Mibs
+ * Alan Cox : MSG_DONTROUTE, and 0.0.0.0 support.
+ * Matt Dillon : UDP length checks.
+ * Alan Cox : Smarter af_inet used properly.
+ * Alan Cox : Use new kernel side addressing.
+ * Alan Cox : Incorrect return on truncated datagram receive.
+ * Arnt Gulbrandsen : New udp_send and stuff
+ * Alan Cox : Cache last socket
+ * Alan Cox : Route cache
+ * Jon Peatfield : Minor efficiency fix to sendto().
+ * Mike Shaver : RFC1122 checks.
+ * Alan Cox : Nonblocking error fix.
+ * Willy Konynenberg : Transparent proxying support.
+ * Mike McLagan : Routing by source
+ * David S. Miller : New socket lookup architecture.
+ * Last socket cache retained as it
+ * does have a high hit rate.
+ * Olaf Kirch : Don't linearise iovec on sendmsg.
+ * Andi Kleen : Some cleanups, cache destination entry
+ * for connect.
+ * Vitaly E. Lavrov : Transparent proxy revived after year coma.
+ * Melvin Smith : Check msg_name not msg_namelen in sendto(),
+ * return ENOTCONN for unconnected sockets (POSIX)
+ * Janos Farkas : don't deliver multi/broadcasts to a different
+ * bound-to-device socket
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/* RFC1122 Status:
+ 4.1.3.1 (Ports):
+ SHOULD send ICMP_PORT_UNREACHABLE in response to datagrams to
+ an un-listened port. (OK)
+ 4.1.3.2 (IP Options)
+ MUST pass IP options from IP -> application (OK)
+ MUST allow application to specify IP options (OK)
+ 4.1.3.3 (ICMP Messages)
+ MUST pass ICMP error messages to application (OK -- except when SO_BSDCOMPAT is set)
+ 4.1.3.4 (UDP Checksums)
+ MUST provide facility for checksumming (OK)
+ MAY allow application to control checksumming (OK)
+ MUST default to checksumming on (OK)
+ MUST discard silently datagrams with bad csums (OK, except during debugging)
+ 4.1.3.5 (UDP Multihoming)
+ MUST allow application to specify source address (OK)
+ SHOULD be able to communicate the chosen src addr up to application
+ when application doesn't choose (DOES - use recvmsg cmsgs)
+ 4.1.3.6 (Invalid Addresses)
+ MUST discard invalid source addresses (OK -- done in the new routing code)
+ MUST only send datagrams with one of our addresses (OK)
+*/
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/config.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/udp.h>
+#include <net/icmp.h>
+#include <net/route.h>
+#include <net/checksum.h>
+
+/*
+ * Snmp MIB for the UDP layer
+ */
+
+struct udp_mib udp_statistics;
+
+struct sock *udp_hash[UDP_HTABLE_SIZE];
+
+/* Shared by v4/v6 udp. */
+int udp_port_rover = 0;
+
+static int udp_v4_get_port(struct sock *sk, unsigned short snum)
+{
+ SOCKHASH_LOCK();
+ if (snum == 0) {
+ int best_size_so_far, best, result, i;
+
+ if (udp_port_rover > sysctl_local_port_range[1] ||
+ udp_port_rover < sysctl_local_port_range[0])
+ udp_port_rover = sysctl_local_port_range[0];
+ best_size_so_far = 32767;
+ best = result = udp_port_rover;
+ for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
+ struct sock *sk;
+ int size;
+
+ sk = udp_hash[result & (UDP_HTABLE_SIZE - 1)];
+ if (!sk) {
+ if (result > sysctl_local_port_range[1])
+ result = sysctl_local_port_range[0] +
+ ((result - sysctl_local_port_range[0]) &
+ (UDP_HTABLE_SIZE - 1));
+ goto gotit;
+ }
+ size = 0;
+ do {
+ if (++size >= best_size_so_far)
+ goto next;
+ } while ((sk = sk->next) != NULL);
+ best_size_so_far = size;
+ best = result;
+ next:
+ }
+ result = best;
+ for(;; result += UDP_HTABLE_SIZE) {
+ if (result > sysctl_local_port_range[1])
+ result = sysctl_local_port_range[0]
+ + ((result - sysctl_local_port_range[0]) &
+ (UDP_HTABLE_SIZE - 1));
+ if (!udp_lport_inuse(result))
+ break;
+ }
+gotit:
+ udp_port_rover = snum = result;
+ } else {
+ struct sock *sk2;
+
+ for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
+ sk2 != NULL;
+ sk2 = sk2->next) {
+ if (sk2->num == snum &&
+ sk2 != sk &&
+ sk2->bound_dev_if == sk->bound_dev_if &&
+ (!sk2->rcv_saddr ||
+ !sk->rcv_saddr ||
+ sk2->rcv_saddr == sk->rcv_saddr) &&
+ (!sk2->reuse || !sk->reuse))
+ goto fail;
+ }
+ }
+ sk->num = snum;
+ SOCKHASH_UNLOCK();
+ return 0;
+
+fail:
+ SOCKHASH_UNLOCK();
+ return 1;
+}
+
+/* Last hit UDP socket cache, this is ipv4 specific so make it static. */
+static u32 uh_cache_saddr, uh_cache_daddr;
+static u16 uh_cache_dport, uh_cache_sport;
+static struct sock *uh_cache_sk = NULL;
+
+static void udp_v4_hash(struct sock *sk)
+{
+ struct sock **skp = &udp_hash[sk->num & (UDP_HTABLE_SIZE - 1)];
+
+ SOCKHASH_LOCK();
+ if ((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+ *skp = sk;
+ sk->pprev = skp;
+ SOCKHASH_UNLOCK();
+}
+
+static void udp_v4_unhash(struct sock *sk)
+{
+ SOCKHASH_LOCK();
+ if (sk->pprev) {
+ if (sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ if(uh_cache_sk == sk)
+ uh_cache_sk = NULL;
+ }
+ SOCKHASH_UNLOCK();
+}
+
+/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
+ * harder than this here plus the last hit cache. -DaveM
+ */
+struct sock *udp_v4_lookup_longway(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
+{
+ struct sock *sk, *result = NULL;
+ unsigned short hnum = ntohs(dport);
+ int badness = -1;
+
+ for(sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; sk != NULL; sk = sk->next) {
+ if((sk->num == hnum) && !(sk->dead && (sk->state == TCP_CLOSE))) {
+ int score = 0;
+ if(sk->rcv_saddr) {
+ if(sk->rcv_saddr != daddr)
+ continue;
+ score++;
+ }
+ if(sk->daddr) {
+ if(sk->daddr != saddr)
+ continue;
+ score++;
+ }
+ if(sk->dport) {
+ if(sk->dport != sport)
+ continue;
+ score++;
+ }
+ if(sk->bound_dev_if) {
+ if(sk->bound_dev_if != dif)
+ continue;
+ score++;
+ }
+ if(score == 4) {
+ result = sk;
+ break;
+ } else if(score > badness) {
+ result = sk;
+ badness = score;
+ }
+ }
+ }
+ return result;
+}
+
+__inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
+{
+ struct sock *sk;
+
+ if(!dif && uh_cache_sk &&
+ uh_cache_saddr == saddr &&
+ uh_cache_sport == sport &&
+ uh_cache_dport == dport &&
+ uh_cache_daddr == daddr)
+ return uh_cache_sk;
+
+ sk = udp_v4_lookup_longway(saddr, sport, daddr, dport, dif);
+ if(!dif) {
+ uh_cache_sk = sk;
+ uh_cache_saddr = saddr;
+ uh_cache_daddr = daddr;
+ uh_cache_sport = sport;
+ uh_cache_dport = dport;
+ }
+ return sk;
+}
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+#define secondlist(hpnum, sk, fpass) \
+({ struct sock *s1; if(!(sk) && (fpass)--) \
+ s1 = udp_hash[(hpnum) & (UDP_HTABLE_SIZE - 1)]; \
+ else \
+ s1 = (sk); \
+ s1; \
+})
+
+#define udp_v4_proxy_loop_init(hnum, hpnum, sk, fpass) \
+ secondlist((hpnum), udp_hash[(hnum)&(UDP_HTABLE_SIZE-1)],(fpass))
+
+#define udp_v4_proxy_loop_next(hnum, hpnum, sk, fpass) \
+ secondlist((hpnum),(sk)->next,(fpass))
+
+static struct sock *udp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
+ unsigned short rnum, unsigned long laddr,
+ struct device *dev, unsigned short pnum,
+ int dif)
+{
+ struct sock *s, *result = NULL;
+ int badness = -1;
+ u32 paddr = 0;
+ unsigned short hnum = ntohs(num);
+ unsigned short hpnum = ntohs(pnum);
+ int firstpass = 1;
+
+ if(dev && dev->ip_ptr) {
+ struct in_device *idev = dev->ip_ptr;
+
+ if(idev->ifa_list)
+ paddr = idev->ifa_list->ifa_local;
+ }
+
+ SOCKHASH_LOCK();
+ for(s = udp_v4_proxy_loop_init(hnum, hpnum, s, firstpass);
+ s != NULL;
+ s = udp_v4_proxy_loop_next(hnum, hpnum, s, firstpass)) {
+ if(s->num == hnum || s->num == hpnum) {
+ int score = 0;
+ if(s->dead && (s->state == TCP_CLOSE))
+ continue;
+ if(s->rcv_saddr) {
+ if((s->num != hpnum || s->rcv_saddr != paddr) &&
+ (s->num != hnum || s->rcv_saddr != laddr))
+ continue;
+ score++;
+ }
+ if(s->daddr) {
+ if(s->daddr != raddr)
+ continue;
+ score++;
+ }
+ if(s->dport) {
+ if(s->dport != rnum)
+ continue;
+ score++;
+ }
+ if(s->bound_dev_if) {
+ if(s->bound_dev_if != dif)
+ continue;
+ score++;
+ }
+ if(score == 4 && s->num == hnum) {
+ result = s;
+ break;
+ } else if(score > badness && (s->num == hpnum || s->rcv_saddr)) {
+ result = s;
+ badness = score;
+ }
+ }
+ }
+ SOCKHASH_UNLOCK();
+ return result;
+}
+
+#undef secondlist
+#undef udp_v4_proxy_loop_init
+#undef udp_v4_proxy_loop_next
+
+#endif
+
+static inline struct sock *udp_v4_mcast_next(struct sock *sk,
+ unsigned short num,
+ unsigned long raddr,
+ unsigned short rnum,
+ unsigned long laddr,
+ int dif)
+{
+ struct sock *s = sk;
+ unsigned short hnum = ntohs(num);
+ for(; s; s = s->next) {
+ if ((s->num != hnum) ||
+ (s->dead && (s->state == TCP_CLOSE)) ||
+ (s->daddr && s->daddr!=raddr) ||
+ (s->dport != rnum && s->dport != 0) ||
+ (s->rcv_saddr && s->rcv_saddr != laddr) ||
+ (s->bound_dev_if && s->bound_dev_if != dif))
+ continue;
+ break;
+ }
+ return s;
+}
+
+/*
+ * This routine is called by the ICMP module when it gets some
+ * sort of error condition. If err < 0 then the socket should
+ * be closed and the error returned to the user. If err > 0
+ * it's just the icmp type << 8 | icmp code.
+ * Header points to the ip header of the error packet. We move
+ * on past this. Then (as it used to claim before adjustment)
+ * header points to the first 8 bytes of the udp header. We need
+ * to find the appropriate port.
+ */
+
+void udp_err(struct sk_buff *skb, unsigned char *dp, int len)
+{
+ struct iphdr *iph = (struct iphdr*)dp;
+ struct udphdr *uh = (struct udphdr*)(dp+(iph->ihl<<2));
+ int type = skb->h.icmph->type;
+ int code = skb->h.icmph->code;
+ struct sock *sk;
+ int harderr;
+ u32 info;
+ int err;
+
+ if (len < (iph->ihl<<2)+sizeof(struct udphdr)) {
+ icmp_statistics.IcmpInErrors++;
+ return;
+ }
+
+ sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev->ifindex);
+ if (sk == NULL) {
+ icmp_statistics.IcmpInErrors++;
+ return; /* No socket for error */
+ }
+
+ err = 0;
+ info = 0;
+ harderr = 0;
+
+ switch (type) {
+ default:
+ case ICMP_TIME_EXCEEDED:
+ err = EHOSTUNREACH;
+ break;
+ case ICMP_SOURCE_QUENCH:
+ return;
+ case ICMP_PARAMETERPROB:
+ err = EPROTO;
+ info = ntohl(skb->h.icmph->un.gateway)>>24;
+ harderr = 1;
+ break;
+ case ICMP_DEST_UNREACH:
+ if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
+ if (sk->ip_pmtudisc != IP_PMTUDISC_DONT) {
+ err = EMSGSIZE;
+ info = ntohs(skb->h.icmph->un.frag.mtu);
+ harderr = 1;
+ break;
+ }
+ return;
+ }
+ err = EHOSTUNREACH;
+ if (code <= NR_ICMP_UNREACH) {
+ harderr = icmp_err_convert[code].fatal;
+ err = icmp_err_convert[code].errno;
+ }
+ break;
+ }
+
+ /*
+ * Various people wanted BSD UDP semantics. Well they've come
+ * back out because they slow down response to stuff like dead
+ * or unreachable name servers and they screw term users something
+ * chronic. Oh and it violates RFC1122. So basically fix your
+ * client code people.
+ */
+
+ /*
+ * RFC1122: OK. Passes ICMP errors back to application, as per
+ * 4.1.3.3. After the comment above, that should be no surprise.
+ */
+
+ if (!harderr && !sk->ip_recverr)
+ return;
+
+ /*
+ * 4.x BSD compatibility item. Break RFC1122 to
+ * get BSD socket semantics.
+ */
+ if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
+ return;
+
+ if (sk->ip_recverr)
+ ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));
+ sk->err = err;
+ sk->error_report(sk);
+}
+
+
+static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
+{
+ return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
+}
+
+struct udpfakehdr
+{
+ struct udphdr uh;
+ u32 saddr;
+ u32 daddr;
+ struct iovec *iov;
+ u32 wcheck;
+};
+
+/*
+ * Copy and checksum a UDP packet from user space into a buffer. We still have
+ * to do the planning to get ip_build_xmit to spot direct transfer to network
+ * card and provide an additional callback mode for direct user->board I/O
+ * transfers. That one will be fun.
+ */
+
+static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned int fraglen)
+{
+ struct udpfakehdr *ufh = (struct udpfakehdr *)p;
+ if (offset==0) {
+ if (csum_partial_copy_fromiovecend(to+sizeof(struct udphdr), ufh->iov, offset,
+ fraglen-sizeof(struct udphdr), &ufh->wcheck))
+ return -EFAULT;
+ ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
+ ufh->wcheck);
+ ufh->uh.check = csum_tcpudp_magic(ufh->saddr, ufh->daddr,
+ ntohs(ufh->uh.len),
+ IPPROTO_UDP, ufh->wcheck);
+ if (ufh->uh.check == 0)
+ ufh->uh.check = -1;
+ memcpy(to, ufh, sizeof(struct udphdr));
+ return 0;
+ }
+ if (csum_partial_copy_fromiovecend(to, ufh->iov, offset-sizeof(struct udphdr),
+ fraglen, &ufh->wcheck))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ * Unchecksummed UDP is sufficiently critical to stuff like ATM video conferencing
+ * that we use two routines for this for speed. Probably we ought to have a
+ * CONFIG_FAST_NET set for >10Mb/second boards to activate this sort of coding.
+ * Timing needed to verify if this is a valid decision.
+ */
+
+static int udp_getfrag_nosum(const void *p, char * to, unsigned int offset, unsigned int fraglen)
+{
+ struct udpfakehdr *ufh = (struct udpfakehdr *)p;
+
+ if (offset==0) {
+ memcpy(to, ufh, sizeof(struct udphdr));
+ return memcpy_fromiovecend(to+sizeof(struct udphdr), ufh->iov, offset,
+ fraglen-sizeof(struct udphdr));
+ }
+ return memcpy_fromiovecend(to, ufh->iov, offset-sizeof(struct udphdr),
+ fraglen);
+}
+
+int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
+{
+ int ulen = len + sizeof(struct udphdr);
+ struct ipcm_cookie ipc;
+ struct udpfakehdr ufh;
+ struct rtable *rt = NULL;
+ int free = 0;
+ int connected = 0;
+ u32 daddr;
+ u8 tos;
+ int err;
+
+ /* This check is ONLY to check for arithmetic overflow
+ on integer(!) len. Not more! Real check will be made
+ in ip_build_xmit --ANK
+
+ BTW socket.c -> af_*.c -> ... make multiple
+ invalid conversions size_t -> int. We MUST repair it f.e.
+ by replacing all of them with size_t and revise all
+ the places sort of len += sizeof(struct iphdr)
+ If len was ULONG_MAX-10 it would be cathastrophe --ANK
+ */
+
+ if (len < 0 || len > 0xFFFF)
+ return -EMSGSIZE;
+
+ /*
+ * Check the flags.
+ */
+
+ if (msg->msg_flags&MSG_OOB) /* Mirror BSD error message compatibility */
+ return -EOPNOTSUPP;
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (msg->msg_flags&~(MSG_DONTROUTE|MSG_DONTWAIT|MSG_PROXY|MSG_NOSIGNAL))
+ return -EINVAL;
+ if ((msg->msg_flags&MSG_PROXY) && !capable(CAP_NET_ADMIN))
+ return -EPERM;
+#else
+ if (msg->msg_flags&~(MSG_DONTROUTE|MSG_DONTWAIT|MSG_NOSIGNAL))
+ return -EINVAL;
+#endif
+
+ /*
+ * Get and verify the address.
+ */
+
+ if (msg->msg_name) {
+ struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;
+ if (msg->msg_namelen < sizeof(*usin))
+ return(-EINVAL);
+ if (usin->sin_family != AF_INET) {
+ static int complained;
+ if (!complained++)
+ printk(KERN_WARNING "%s forgot to set AF_INET in udp sendmsg. Fix it!\n", current->comm);
+ if (usin->sin_family)
+ return -EINVAL;
+ }
+ ufh.daddr = usin->sin_addr.s_addr;
+ ufh.uh.dest = usin->sin_port;
+ if (ufh.uh.dest == 0)
+ return -EINVAL;
+ } else {
+ if (sk->state != TCP_ESTABLISHED)
+ return -ENOTCONN;
+ ufh.daddr = sk->daddr;
+ ufh.uh.dest = sk->dport;
+ /* Open fast path for connected socket.
+ Route will not be used, if at least one option is set.
+ */
+ connected = 1;
+ }
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (msg->msg_flags&MSG_PROXY) {
+ /*
+ * We map the first 8 bytes of a second sockaddr_in
+ * into the last 8 (unused) bytes of a sockaddr_in.
+ */
+ struct sockaddr_in *from = (struct sockaddr_in *)msg->msg_name;
+ from = (struct sockaddr_in *)&from->sin_zero;
+ if (from->sin_family != AF_INET)
+ return -EINVAL;
+ ipc.addr = from->sin_addr.s_addr;
+ ufh.uh.source = from->sin_port;
+ if (ipc.addr == 0)
+ ipc.addr = sk->saddr;
+ connected = 0;
+ } else
+#endif
+ {
+ ipc.addr = sk->saddr;
+ ufh.uh.source = sk->sport;
+ }
+
+ ipc.opt = NULL;
+ ipc.oif = sk->bound_dev_if;
+ if (msg->msg_controllen) {
+ err = ip_cmsg_send(msg, &ipc);
+ if (err)
+ return err;
+ if (ipc.opt)
+ free = 1;
+ connected = 0;
+ }
+ if (!ipc.opt)
+ ipc.opt = sk->opt;
+
+ ufh.saddr = ipc.addr;
+ ipc.addr = daddr = ufh.daddr;
+
+ if (ipc.opt && ipc.opt->srr) {
+ if (!daddr)
+ return -EINVAL;
+ daddr = ipc.opt->faddr;
+ connected = 0;
+ }
+ tos = RT_TOS(sk->ip_tos);
+ if (sk->localroute || (msg->msg_flags&MSG_DONTROUTE) ||
+ (ipc.opt && ipc.opt->is_strictroute)) {
+ tos |= RTO_ONLINK;
+ connected = 0;
+ }
+
+ if (MULTICAST(daddr)) {
+ if (!ipc.oif)
+ ipc.oif = sk->ip_mc_index;
+ if (!ufh.saddr)
+ ufh.saddr = sk->ip_mc_addr;
+ connected = 0;
+ }
+
+ if (connected && sk->dst_cache) {
+ rt = (struct rtable*)sk->dst_cache;
+ if (rt->u.dst.obsolete) {
+ sk->dst_cache = NULL;
+ dst_release(&rt->u.dst);
+ rt = NULL;
+ } else
+ dst_clone(&rt->u.dst);
+ }
+
+ if (rt == NULL) {
+ err = ip_route_output(&rt, daddr, ufh.saddr,
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ (msg->msg_flags&MSG_PROXY ? RTO_TPROXY : 0) |
+#endif
+ tos, ipc.oif);
+ if (err)
+ goto out;
+
+ err = -EACCES;
+ if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast)
+ goto out;
+ if (connected && sk->dst_cache == NULL)
+ sk->dst_cache = dst_clone(&rt->u.dst);
+ }
+
+ ufh.saddr = rt->rt_src;
+ if (!ipc.addr)
+ ufh.daddr = ipc.addr = rt->rt_dst;
+ ufh.uh.len = htons(ulen);
+ ufh.uh.check = 0;
+ ufh.iov = msg->msg_iov;
+ ufh.wcheck = 0;
+
+ /* RFC1122: OK. Provides the checksumming facility (MUST) as per */
+ /* 4.1.3.4. It's configurable by the application via setsockopt() */
+ /* (MAY) and it defaults to on (MUST). */
+
+ err = ip_build_xmit(sk,sk->no_check ? udp_getfrag_nosum : udp_getfrag,
+ &ufh, ulen, &ipc, rt, msg->msg_flags);
+
+out:
+ ip_rt_put(rt);
+ if (free)
+ kfree(ipc.opt);
+ if (!err) {
+ udp_statistics.UdpOutDatagrams++;
+ return len;
+ }
+ return err;
+}
+
+/*
+ * IOCTL requests applicable to the UDP protocol
+ */
+
+int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+ switch(cmd)
+ {
+ case TIOCOUTQ:
+ {
+ unsigned long amount;
+
+ amount = sock_wspace(sk);
+ return put_user(amount, (int *)arg);
+ }
+
+ case TIOCINQ:
+ {
+ struct sk_buff *skb;
+ unsigned long amount;
+
+ amount = 0;
+ /* N.B. Is this interrupt safe??
+ -> Yes. Interrupts do not remove skbs. --ANK (980725)
+ */
+ skb = skb_peek(&sk->receive_queue);
+ if (skb != NULL) {
+ /*
+ * We will only return the amount
+ * of this packet since that is all
+ * that will be read.
+ */
+ amount = skb->len - sizeof(struct udphdr);
+ }
+ return put_user(amount, (int *)arg);
+ }
+
+ default:
+ return(-ENOIOCTLCMD);
+ }
+ return(0);
+}
+
+#ifndef HAVE_CSUM_COPY_USER
+#undef CONFIG_UDP_DELAY_CSUM
+#endif
+
+/*
+ * This should be easy, if there is something there we
+ * return it, otherwise we block.
+ */
+
+int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
+ int noblock, int flags, int *addr_len)
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
+ struct sk_buff *skb;
+ int copied, err;
+
+ if (flags & MSG_ERRQUEUE)
+ return ip_recv_error(sk, msg, len);
+
+ /*
+ * From here the generic datagram does a lot of the work. Come
+ * the finished NET3, it will do _ALL_ the work!
+ */
+
+ skb = skb_recv_datagram(sk, flags, noblock, &err);
+ if (!skb)
+ goto out;
+
+ copied = skb->len - sizeof(struct udphdr);
+ if (copied > len) {
+ copied = len;
+ msg->msg_flags |= MSG_TRUNC;
+ }
+
+#ifndef CONFIG_UDP_DELAY_CSUM
+ err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
+ copied);
+#else
+ if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
+ err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
+ copied);
+ } else if (copied > msg->msg_iov[0].iov_len || (msg->msg_flags&MSG_TRUNC)) {
+ if ((unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum)))
+ goto csum_copy_err;
+ err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
+ copied);
+ } else {
+ unsigned int csum;
+
+ err = 0;
+ csum = csum_partial(skb->h.raw, sizeof(struct udphdr), skb->csum);
+ csum = csum_and_copy_to_user((char*)&skb->h.uh[1], msg->msg_iov[0].iov_base,
+ copied, csum, &err);
+ if (err)
+ goto out_free;
+ if ((unsigned short)csum_fold(csum))
+ goto csum_copy_err;
+ }
+#endif
+ if (err)
+ goto out_free;
+ sk->stamp=skb->stamp;
+
+ /* Copy the address. */
+ if (sin)
+ {
+ /*
+ * Check any passed addresses
+ */
+ if (addr_len)
+ *addr_len=sizeof(*sin);
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = skb->h.uh->source;
+ sin->sin_addr.s_addr = skb->nh.iph->saddr;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (flags&MSG_PROXY)
+ {
+ /*
+ * We map the first 8 bytes of a second sockaddr_in
+ * into the last 8 (unused) bytes of a sockaddr_in.
+ * This _is_ ugly, but it's the only way to do it
+ * easily, without adding system calls.
+ */
+ struct sockaddr_in *sinto =
+ (struct sockaddr_in *) sin->sin_zero;
+
+ sinto->sin_family = AF_INET;
+ sinto->sin_port = skb->h.uh->dest;
+ sinto->sin_addr.s_addr = skb->nh.iph->daddr;
+ }
+#endif
+ }
+ if (sk->ip_cmsg_flags)
+ ip_cmsg_recv(msg, skb);
+ err = copied;
+
+out_free:
+ skb_free_datagram(sk, skb);
+out:
+ return err;
+
+#ifdef CONFIG_UDP_DELAY_CSUM
+csum_copy_err:
+ udp_statistics.UdpInErrors++;
+ skb_free_datagram(sk, skb);
+
+ /*
+ * Error for blocking case is chosen to masquerade
+ * as some normal condition.
+ */
+ return (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
+#endif
+}
+
+int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+ struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
+ struct rtable *rt;
+ int err;
+
+
+ if (addr_len < sizeof(*usin))
+ return(-EINVAL);
+
+ /*
+ * 1003.1g - break association.
+ */
+
+ if (usin->sin_family==AF_UNSPEC)
+ {
+ sk->saddr=INADDR_ANY;
+ sk->rcv_saddr=INADDR_ANY;
+ sk->daddr=INADDR_ANY;
+ sk->state = TCP_CLOSE;
+ if(uh_cache_sk == sk)
+ uh_cache_sk = NULL;
+ return 0;
+ }
+
+ if (usin->sin_family && usin->sin_family != AF_INET)
+ return(-EAFNOSUPPORT);
+
+ dst_release(xchg(&sk->dst_cache, NULL));
+
+ err = ip_route_connect(&rt, usin->sin_addr.s_addr, sk->saddr,
+ sk->ip_tos|sk->localroute, sk->bound_dev_if);
+ if (err)
+ return err;
+ if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
+ ip_rt_put(rt);
+ return -EACCES;
+ }
+ if(!sk->saddr)
+ sk->saddr = rt->rt_src; /* Update source address */
+ if(!sk->rcv_saddr)
+ sk->rcv_saddr = rt->rt_src;
+ sk->daddr = rt->rt_dst;
+ sk->dport = usin->sin_port;
+ sk->state = TCP_ESTABLISHED;
+
+ if(uh_cache_sk == sk)
+ uh_cache_sk = NULL;
+
+ sk->dst_cache = &rt->u.dst;
+ return(0);
+}
+
+
+static void udp_close(struct sock *sk, long timeout)
+{
+ /* See for explanation: raw_close in ipv4/raw.c */
+ sk->state = TCP_CLOSE;
+ udp_v4_unhash(sk);
+ sk->dead = 1;
+ destroy_sock(sk);
+}
+
+static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
+{
+ /*
+ * Charge it to the socket, dropping if the queue is full.
+ */
+
+#if defined(CONFIG_FILTER) && defined(CONFIG_UDP_DELAY_CSUM)
+ if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
+ if ((unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum))) {
+ udp_statistics.UdpInErrors++;
+ ip_statistics.IpInDiscards++;
+ ip_statistics.IpInDelivers--;
+ kfree_skb(skb);
+ return -1;
+ }
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+#endif
+
+ if (sock_queue_rcv_skb(sk,skb)<0) {
+ udp_statistics.UdpInErrors++;
+ ip_statistics.IpInDiscards++;
+ ip_statistics.IpInDelivers--;
+ kfree_skb(skb);
+ return -1;
+ }
+ udp_statistics.UdpInDatagrams++;
+ return 0;
+}
+
+
+static inline void udp_deliver(struct sock *sk, struct sk_buff *skb)
+{
+ udp_queue_rcv_skb(sk, skb);
+}
+
+/*
+ * Multicasts and broadcasts go to each listener.
+ *
+ * Note: called only from the BH handler context,
+ * so we don't need to lock the hashes.
+ */
+static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
+ u32 saddr, u32 daddr)
+{
+ struct sock *sk;
+ int dif;
+
+ sk = udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)];
+ dif = skb->dev->ifindex;
+ sk = udp_v4_mcast_next(sk, uh->dest, saddr, uh->source, daddr, dif);
+ if (sk) {
+ struct sock *sknext = NULL;
+
+ do {
+ struct sk_buff *skb1 = skb;
+
+ sknext = udp_v4_mcast_next(sk->next, uh->dest, saddr,
+ uh->source, daddr, dif);
+ if(sknext)
+ skb1 = skb_clone(skb, GFP_ATOMIC);
+
+ if(skb1)
+ udp_deliver(sk, skb1);
+ sk = sknext;
+ } while(sknext);
+ } else
+ kfree_skb(skb);
+ return 0;
+}
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ * Check whether a received UDP packet might be for one of our
+ * sockets.
+ */
+
+int udp_chkaddr(struct sk_buff *skb)
+{
+ struct iphdr *iph = skb->nh.iph;
+ struct udphdr *uh = (struct udphdr *)(skb->nh.raw + iph->ihl*4);
+ struct sock *sk;
+
+ sk = udp_v4_lookup(iph->saddr, uh->source, iph->daddr, uh->dest, skb->dev->ifindex);
+ if (!sk)
+ return 0;
+
+ /* 0 means accept all LOCAL addresses here, not all the world... */
+ if (sk->rcv_saddr == 0)
+ return 0;
+
+ return 1;
+}
+#endif
+
+/*
+ * All we need to do is get the socket, and then do a checksum.
+ */
+
+int udp_rcv(struct sk_buff *skb, unsigned short len)
+{
+ struct sock *sk;
+ struct udphdr *uh;
+ unsigned short ulen;
+ struct rtable *rt = (struct rtable*)skb->dst;
+ u32 saddr = skb->nh.iph->saddr;
+ u32 daddr = skb->nh.iph->daddr;
+
+ /*
+ * First time through the loop.. Do all the setup stuff
+ * (including finding out the socket we go to etc)
+ */
+
+ /*
+ * Get the header.
+ */
+
+ uh = skb->h.uh;
+ __skb_pull(skb, skb->h.raw - skb->data);
+
+ ip_statistics.IpInDelivers++;
+
+ /*
+ * Validate the packet and the UDP length.
+ */
+
+ ulen = ntohs(uh->len);
+
+ if (ulen > len || ulen < sizeof(*uh)) {
+ NETDEBUG(printk(KERN_DEBUG "UDP: short packet: %d/%d\n", ulen, len));
+ udp_statistics.UdpInErrors++;
+ kfree_skb(skb);
+ return(0);
+ }
+ skb_trim(skb, ulen);
+
+#ifndef CONFIG_UDP_DELAY_CSUM
+ if (uh->check &&
+ (((skb->ip_summed==CHECKSUM_HW)&&udp_check(uh,ulen,saddr,daddr,skb->csum)) ||
+ ((skb->ip_summed==CHECKSUM_NONE) &&
+ (udp_check(uh,ulen,saddr,daddr, csum_partial((char*)uh, ulen, 0))))))
+ goto csum_error;
+#else
+ if (uh->check==0)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else if (skb->ip_summed==CHECKSUM_HW) {
+ if (udp_check(uh,ulen,saddr,daddr,skb->csum))
+ goto csum_error;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+ skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+#endif
+
+ if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
+ return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
+
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ if (IPCB(skb)->redirport)
+ sk = udp_v4_proxy_lookup(uh->dest, saddr, uh->source,
+ daddr, skb->dev, IPCB(skb)->redirport,
+ skb->dev->ifindex);
+ else
+#endif
+ sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex);
+
+ if (sk == NULL) {
+#ifdef CONFIG_UDP_DELAY_CSUM
+ if (skb->ip_summed != CHECKSUM_UNNECESSARY &&
+ (unsigned short)csum_fold(csum_partial((char*)uh, ulen, skb->csum)))
+ goto csum_error;
+#endif
+ udp_statistics.UdpNoPorts++;
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+ /*
+ * Hmm. We got an UDP broadcast to a port to which we
+ * don't wanna listen. Ignore it.
+ */
+ kfree_skb(skb);
+ return(0);
+ }
+ udp_deliver(sk, skb);
+ return 0;
+
+csum_error:
+ /*
+ * RFC1122: OK. Discards the bad packet silently (as far as
+ * the network is concerned, anyway) as per 4.1.3.4 (MUST).
+ */
+ NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
+ NIPQUAD(saddr),
+ ntohs(uh->source),
+ NIPQUAD(daddr),
+ ntohs(uh->dest),
+ ulen));
+ udp_statistics.UdpInErrors++;
+ kfree_skb(skb);
+ return(0);
+}
+
+struct proto udp_prot = {
+ (struct sock *)&udp_prot, /* sklist_next */
+ (struct sock *)&udp_prot, /* sklist_prev */
+ udp_close, /* close */
+ udp_connect, /* connect */
+ NULL, /* accept */
+ NULL, /* retransmit */
+ NULL, /* write_wakeup */
+ NULL, /* read_wakeup */
+ datagram_poll, /* poll */
+ udp_ioctl, /* ioctl */
+ NULL, /* init */
+ NULL, /* destroy */
+ NULL, /* shutdown */
+ ip_setsockopt, /* setsockopt */
+ ip_getsockopt, /* getsockopt */
+ udp_sendmsg, /* sendmsg */
+ udp_recvmsg, /* recvmsg */
+ NULL, /* bind */
+ udp_queue_rcv_skb, /* backlog_rcv */
+ udp_v4_hash, /* hash */
+ udp_v4_unhash, /* unhash */
+ udp_v4_get_port, /* good_socknum */
+ 128, /* max_header */
+ 0, /* retransmits */
+ "UDP", /* name */
+ 0, /* inuse */
+ 0 /* highestinuse */
+};
diff --git a/pfinet/linux-src/net/ipv4/utils.c b/pfinet/linux-src/net/ipv4/utils.c
new file mode 100644
index 00000000..ce74ade2
--- /dev/null
+++ b/pfinet/linux-src/net/ipv4/utils.c
@@ -0,0 +1,91 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Various kernel-resident INET utility functions; mainly
+ * for format conversion and debugging output.
+ *
+ * Version: $Id: utils.c,v 1.6 1997/12/13 21:53:03 kuznet Exp $
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * Fixes:
+ * Alan Cox : verify_area check.
+ * Alan Cox : removed old debugging.
+ * Andi Kleen : add net_ratelimit()
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/stat.h>
+#include <stdarg.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <linux/skbuff.h>
+
+
+/*
+ * Display an IP address in readable format.
+ */
+
+char *in_ntoa(__u32 in)
+{
+ static char buff[18];
+ char *p;
+
+ p = (char *) &in;
+ sprintf(buff, "%d.%d.%d.%d",
+ (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
+ return(buff);
+}
+
+
+/*
+ * Convert an ASCII string to binary IP.
+ */
+
+__u32 in_aton(const char *str)
+{
+ unsigned long l;
+ unsigned int val;
+ int i;
+
+ l = 0;
+ for (i = 0; i < 4; i++)
+ {
+ l <<= 8;
+ if (*str != '\0')
+ {
+ val = 0;
+ while (*str != '\0' && *str != '.')
+ {
+ val *= 10;
+ val += *str - '0';
+ str++;
+ }
+ l |= val;
+ if (*str != '\0')
+ str++;
+ }
+ }
+ return(htonl(l));
+}
+