Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
74beaae0
Commit
74beaae0
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 1.1.47
parent
ab114917
Changes
22
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1046 additions
and
209 deletions
+1046
-209
Makefile
Makefile
+1
-1
drivers/block/blk.h
drivers/block/blk.h
+0
-4
drivers/block/floppy.c
drivers/block/floppy.c
+1
-1
drivers/block/hd.c
drivers/block/hd.c
+1
-0
drivers/char/console.c
drivers/char/console.c
+2
-2
drivers/char/kbd_kern.h
drivers/char/kbd_kern.h
+6
-2
drivers/char/keyboard.c
drivers/char/keyboard.c
+7
-12
drivers/char/n_tty.c
drivers/char/n_tty.c
+2
-2
drivers/char/tty_io.c
drivers/char/tty_io.c
+5
-3
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.c
+15
-4
drivers/scsi/constants.h
drivers/scsi/constants.h
+1
-0
drivers/scsi/pas16.c
drivers/scsi/pas16.c
+43
-13
drivers/scsi/sr.c
drivers/scsi/sr.c
+14
-1
fs/ext2/balloc.c
fs/ext2/balloc.c
+1
-4
include/asm-i386/bitops.h
include/asm-i386/bitops.h
+12
-0
include/linux/ncp.h
include/linux/ncp.h
+106
-0
include/linux/socket.h
include/linux/socket.h
+1
-0
net/inet/datagram.c
net/inet/datagram.c
+2
-1
net/inet/ipx.c
net/inet/ipx.c
+796
-158
net/inet/ncp.h
net/inet/ncp.h
+26
-0
net/inet/sock.h
net/inet/sock.h
+2
-0
net/socket.c
net/socket.c
+2
-1
No files found.
Makefile
View file @
74beaae0
VERSION
=
1
PATCHLEVEL
=
1
SUBLEVEL
=
4
6
SUBLEVEL
=
4
7
ARCH
=
i386
...
...
drivers/block/blk.h
View file @
74beaae0
...
...
@@ -223,10 +223,6 @@ static void floppy_off(unsigned int nr);
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#else
#error "unknown blk device"
#endif
#if (MAJOR_NR != SCSI_TAPE_MAJOR)
...
...
drivers/block/floppy.c
View file @
74beaae0
...
...
@@ -231,7 +231,7 @@ static struct {
{{
3
,
250
,
16
,
16
,
3000
,
100
,
300
,
0
,
2
,
5
,
83
,
3
*
HZ
,
20
,
{
3
,
1
,
2
,
0
,
2
},
0
,
0
,
{
4
,
22
,
21
,
30
,
3
,
0
,
0
,
0
},
150
,
4
},
"720k"
},
/*3 1/2 DD*/
{{
4
,
500
,
16
,
16
,
3
000
,
40
,
300
,
10
,
2
,
5
,
83
,
3
*
HZ
,
20
,
{
3
,
1
,
2
,
0
,
2
},
0
,
{{
4
,
500
,
16
,
16
,
4
000
,
40
,
300
,
10
,
2
,
5
,
83
,
3
*
HZ
,
20
,
{
3
,
1
,
2
,
0
,
2
},
0
,
0
,
{
7
,
4
,
25
,
22
,
31
,
21
,
29
,
11
},
150
,
7
},
"1.44M"
},
/*3 1/2 HD*/
{{
5
,
1000
,
15
,
8
,
3000
,
40
,
300
,
10
,
2
,
5
,
83
,
3
*
HZ
,
40
,
{
3
,
1
,
2
,
0
,
2
},
0
,
...
...
drivers/block/hd.c
View file @
74beaae0
...
...
@@ -866,6 +866,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
if
(
err
)
return
err
;
memcpy_tofs
((
char
*
)
arg
,
(
char
*
)
hd_ident_info
[
dev
],
sizeof
(
struct
hd_driveid
));
return
0
;
RO_IOCTLS
(
inode
->
i_rdev
,
arg
);
default:
...
...
drivers/char/console.c
View file @
74beaae0
...
...
@@ -1457,13 +1457,13 @@ void poke_blanked_console(void)
}
}
void
*
memsetw
(
void
*
s
,
unsigned
short
c
,
int
count
)
void
*
memsetw
(
void
*
s
,
unsigned
short
c
,
unsigned
int
count
)
{
__asm__
(
"cld
\n\t
"
"rep
\n\t
"
"stosw"
:
/* no output */
:
"a"
(
c
),
"D"
(
s
),
"c"
(
count
)
:
"a"
(
c
),
"D"
(
s
),
"c"
(
count
/
2
)
:
"cx"
,
"di"
);
return
s
;
}
...
...
drivers/char/kbd_kern.h
View file @
74beaae0
...
...
@@ -18,11 +18,15 @@
struct
kbd_struct
{
unsigned
char
ledstate
;
/* 3 bits */
unsigned
char
default_ledstate
;
unsigned
char
lockstate
;
/* 3 bits */
#define VC_SCROLLOCK 0
/* scroll-lock mode */
#define VC_NUMLOCK 1
/* numeric lock mode */
#define VC_CAPSLOCK 2
/* capslock mode */
unsigned
char
lockstate
;
/* 4 bits - must be in 0..15 */
#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 */
unsigned
char
modeflags
;
#define VC_APPLIC 0
/* application key mode */
...
...
drivers/char/keyboard.c
View file @
74beaae0
...
...
@@ -344,15 +344,15 @@ static void keyboard_interrupt(int int_pt_regs)
u_char
type
;
/* the XOR below used to be an OR */
int
shift_final
=
shift_state
^
vc_kbd_lock
(
kbd
,
VC_CAPSLOCK
)
;
int
shift_final
=
shift_state
^
kbd
->
lockstate
;
key_code
=
key_map
[
shift_final
][
scancode
];
type
=
KTYP
(
key_code
);
if
(
type
==
KT_LETTER
)
{
type
=
KT_LATIN
;
if
(
vc_kbd_l
ock
(
kbd
,
VC_CAPSLOCK
))
key_code
=
key_map
[
shift_final
][
scancode
];
if
(
vc_kbd_l
ed
(
kbd
,
VC_CAPSLOCK
))
key_code
=
key_map
[
shift_final
^
(
1
<<
KG_SHIFT
)
][
scancode
];
}
(
*
key_handler
[
type
])(
key_code
&
0xff
,
up_flag
);
}
...
...
@@ -404,7 +404,6 @@ static void caps_toggle(void)
if
(
rep
)
return
;
chg_vc_kbd_led
(
kbd
,
VC_CAPSLOCK
);
chg_vc_kbd_lock
(
kbd
,
VC_CAPSLOCK
);
}
static
void
caps_on
(
void
)
...
...
@@ -412,7 +411,6 @@ static void caps_on(void)
if
(
rep
)
return
;
set_vc_kbd_led
(
kbd
,
VC_CAPSLOCK
);
set_vc_kbd_lock
(
kbd
,
VC_CAPSLOCK
);
}
static
void
show_ptregs
(
void
)
...
...
@@ -463,10 +461,8 @@ static void num(void)
applkey
(
'P'
,
1
);
return
;
}
if
(
!
rep
)
{
/* no autorepeat for numlock, ChN */
if
(
!
rep
)
/* no autorepeat for numlock, ChN */
chg_vc_kbd_led
(
kbd
,
VC_NUMLOCK
);
chg_vc_kbd_lock
(
kbd
,
VC_NUMLOCK
);
}
}
static
void
lastcons
(
void
)
...
...
@@ -647,7 +643,8 @@ static void do_pad(unsigned char value, char up_flag)
applkey
(
app_map
[
value
],
1
);
return
;
}
if
(
!
vc_kbd_lock
(
kbd
,
VC_NUMLOCK
))
if
(
!
vc_kbd_led
(
kbd
,
VC_NUMLOCK
))
switch
(
value
)
{
case
KVAL
(
K_PCOMMA
):
case
KVAL
(
K_PDOT
):
...
...
@@ -709,10 +706,8 @@ static void do_shift(unsigned char value, char up_flag)
/* kludge... */
if
(
value
==
KVAL
(
K_CAPSSHIFT
))
{
value
=
KVAL
(
K_SHIFT
);
if
(
!
up_flag
)
{
if
(
!
up_flag
)
clr_vc_kbd_led
(
kbd
,
VC_CAPSLOCK
);
clr_vc_kbd_lock
(
kbd
,
VC_CAPSLOCK
);
}
}
if
(
up_flag
)
{
...
...
drivers/char/n_tty.c
View file @
74beaae0
...
...
@@ -931,9 +931,9 @@ static int write_chan(struct tty_struct * tty, struct file * file,
if
(
opost
(
c
,
tty
)
<
0
)
break
;
b
++
;
nr
--
;
}
if
(
tty
->
driver
.
flush_chars
)
tty
->
driver
.
flush_chars
(
tty
);
}
}
else
{
c
=
tty
->
driver
.
write
(
tty
,
1
,
b
,
nr
);
b
+=
c
;
...
...
drivers/char/tty_io.c
View file @
74beaae0
...
...
@@ -1535,8 +1535,10 @@ int tty_register_driver(struct tty_driver *driver)
return
0
;
error
=
register_chrdev
(
driver
->
major
,
driver
->
name
,
&
tty_fops
);
if
(
error
)
if
(
error
<
0
)
return
error
;
else
if
(
driver
->
major
==
0
)
driver
->
major
=
error
;
if
(
!
driver
->
put_char
)
driver
->
put_char
=
tty_default_put_char
;
...
...
@@ -1545,7 +1547,7 @@ int tty_register_driver(struct tty_driver *driver)
driver
->
next
=
tty_drivers
;
tty_drivers
->
prev
=
driver
;
tty_drivers
=
driver
;
return
0
;
return
error
;
}
/*
...
...
@@ -1589,7 +1591,7 @@ long tty_init(long kmem_start)
panic
(
"size of tty structure > PAGE_SIZE!"
);
if
(
register_chrdev
(
TTY_MAJOR
,
"tty"
,
&
tty_fops
))
panic
(
"unable to get major %d for tty device"
,
TTY_MAJOR
);
if
(
register_chrdev
(
TTYAUX_MAJOR
,
"
tty
"
,
&
tty_fops
))
if
(
register_chrdev
(
TTYAUX_MAJOR
,
"
cua
"
,
&
tty_fops
))
panic
(
"unable to get major %d for tty device"
,
TTYAUX_MAJOR
);
kmem_start
=
kbd_init
(
kmem_start
);
...
...
drivers/scsi/NCR5380.c
View file @
74beaae0
...
...
@@ -193,6 +193,11 @@
* DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
* transceivers.
*
* LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512
* bytes at a time. Since interrupts are disabled by default during
* these transfers, we might need this to give reasonable interrupt
* service time if the transfer size gets too large.
*
* LINKED - if defined, linked commands are supported.
*
* PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases.
...
...
@@ -1980,8 +1985,14 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) {
if
(
!
cmd
->
device
->
borken
&&
(
transfersize
=
NCR5380_dma_xfer_len
(
instance
,
cmd
))
!=
0
)
{
#else
if
(
!
cmd
->
device
->
borken
&&
(
transfersize
=
cmd
->
transfersize
)
&&
transfersize
=
cmd
->
transfersize
;
#ifdef LIMIT_TRANSFERSIZE
/* If we have problems with interrupt service */
if
(
transfersize
>
512
)
transfersize
=
512
;
#endif
/* LIMIT_TRANSFERSIZE */
if
(
!
cmd
->
device
->
borken
&&
transfersize
&&
cmd
->
SCp
.
this_residual
&&
!
(
cmd
->
SCp
.
this_residual
%
transfersize
))
{
#endif
...
...
drivers/scsi/constants.h
View file @
74beaae0
...
...
@@ -4,4 +4,5 @@ extern void print_command(unsigned char *);
extern
int
print_msg
(
unsigned
char
*
);
extern
void
print_sense
(
char
*
,
Scsi_Cmnd
*
);
extern
void
print_status
(
int
);
extern
void
print_Scsi_Cmnd
(
Scsi_Cmnd
*
);
#endif
/* def _CONSTANTS_H */
drivers/scsi/pas16.c
View file @
74beaae0
#define AUTOSENSE
#define PSEUDO_DMA
#define FOO
#define UNSAFE
/* Not unsafe for PAS16 -- use it */
/*
* This driver adapted from Drew Eckhardt's Trantor T128 driver
...
...
@@ -40,6 +42,11 @@
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
* for commands that return with a CHECK CONDITION status.
*
* LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512
* bytes at a time. Since interrupts are disabled by default during
* these transfers, we might need this to give reasonable interrupt
* service time if the transfer size gets too large.
*
* PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
* increase compared to polled I/O.
*
...
...
@@ -47,11 +54,13 @@
*
* SCSI2 - enable support for SCSI-II tagged queueing. Untested.
*
*
* UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You
* only really want to use this if you're having a problem with
* dropped characters during high speed communications, and even
* then, you're going to be better off twiddling with transfersize.
* UNSAFE - leave interrupts enabled during pseudo-DMA transfers. This
* parameter comes from the NCR5380 code. It is NOT unsafe with
* the PAS16 and you should use it. If you don't you will have
* a problem with dropped characters during high speed
* communications during SCSI transfers. If you really don't
* want to use UNSAFE you can try defining LIMIT_TRANSFERSIZE or
* twiddle with the transfer size in the high level code.
*
* USLEEP - enable support for devices that don't disconnect. Untested.
*
...
...
@@ -242,7 +251,7 @@ void init_board( unsigned short io_port, int irq, int force_irq )
int
pas16_hw_detect
(
unsigned
short
board_num
)
{
unsigned
char
board_rev
,
tmp
;
unsigned
short
port
=
bases
[
board_num
].
io_port
;
unsigned
short
io_
port
=
bases
[
board_num
].
io_port
;
/* See if we can find a PAS16 board at the address associated
* with this logical board number.
...
...
@@ -251,26 +260,39 @@ int pas16_hw_detect( unsigned short board_num )
/* First, attempt to take a newer model board out of reset and
* give it a base address. This shouldn't affect older boards.
*/
enable_board
(
board_num
,
port
);
enable_board
(
board_num
,
io_
port
);
/* Now see if it looks like a PAS16 board */
board_rev
=
inb
(
port
+
PCB_CONFIG
);
board_rev
=
inb
(
io_
port
+
PCB_CONFIG
);
if
(
board_rev
==
0xff
)
return
0
;
tmp
=
board_rev
^
0xe0
;
outb
(
tmp
,
port
+
PCB_CONFIG
);
tmp
=
inb
(
port
+
PCB_CONFIG
);
outb
(
board_rev
,
port
+
PCB_CONFIG
);
outb
(
tmp
,
io_
port
+
PCB_CONFIG
);
tmp
=
inb
(
io_
port
+
PCB_CONFIG
);
outb
(
board_rev
,
io_
port
+
PCB_CONFIG
);
if
(
board_rev
!=
tmp
)
/* Not a PAS-16 */
return
0
;
if
(
(
inb
(
port
+
OPERATION_MODE_1
)
&
0x03
)
!=
0x03
)
if
(
(
inb
(
io_
port
+
OPERATION_MODE_1
)
&
0x03
)
!=
0x03
)
return
0
;
/* return if no SCSI interface found */
/* Mediavision has some new model boards that return ID bits
* that indicate a SCSI interface, but they're not (LMS). We'll
* put in an additional test to try and weed them out.
*/
outb
(
0x01
,
io_port
+
WAIT_STATE
);
/* 1 Wait state */
NCR5380_write
(
MODE_REG
,
0x20
);
/* Is it really SCSI? */
if
(
NCR5380_read
(
MODE_REG
)
!=
0x20
)
/* Write to a reg. */
return
0
;
/* and try to read */
NCR5380_write
(
MODE_REG
,
0x00
);
/* it back. */
if
(
NCR5380_read
(
MODE_REG
)
!=
0x00
)
return
0
;
return
1
;
}
...
...
@@ -426,7 +448,15 @@ int pas16_biosparam(Disk * disk, int dev, int * ip)
int
size
=
disk
->
capacity
;
ip
[
0
]
=
64
;
ip
[
1
]
=
32
;
ip
[
2
]
=
size
>>
11
;
ip
[
2
]
=
size
>>
11
;
/* I think I have it as /(32*64) */
if
(
ip
[
2
]
>
1024
)
{
/* yes, >, not >= */
ip
[
0
]
=
255
;
ip
[
1
]
=
63
;
ip
[
2
]
=
size
/
(
63
*
255
);
if
(
ip
[
2
]
>
1023
)
/* yes >1023... */
ip
[
2
]
=
1023
;
}
return
0
;
}
...
...
drivers/scsi/sr.c
View file @
74beaae0
...
...
@@ -628,6 +628,19 @@ are any multiple of 512 bytes long. */
};
#endif
/* Some dumb host adapters can speed transfers by knowing the
* minimum tranfersize in advance.
*
* We shouldn't disconnect in the middle of a sector, but the cdrom
* sector size can be larger than the size of a buffer and the
* transfer may be split to the size of a buffer. So it's safe to
* assume that we can at least transfer the minimum of the buffer
* size (1024) and the sector size between each connect / disconnect.
*/
SCpnt
->
transfersize
=
(
scsi_CDs
[
dev
].
sector_size
>
1024
)
?
1024
:
scsi_CDs
[
dev
].
sector_size
;
SCpnt
->
this_count
=
this_count
;
scsi_do_cmd
(
SCpnt
,
(
void
*
)
cmd
,
buffer
,
realcount
*
scsi_CDs
[
dev
].
sector_size
,
...
...
fs/ext2/balloc.c
View file @
74beaae0
...
...
@@ -316,10 +316,7 @@ int ext2_new_block (struct super_block * sb, unsigned long goal,
else
lmap
|=
0xffffffff
<<
(
31
-
(
j
&
31
));
if
(
lmap
!=
0xffffffffl
)
{
__asm__
(
"bsfl %1,%0"
:
"=r"
(
k
)
:
"r"
(
~
lmap
));
k
++
;
k
=
ffz
(
lmap
)
+
1
;
if
((
j
+
k
)
<
EXT2_BLOCKS_PER_GROUP
(
sb
))
{
j
+=
k
;
goto
got_block
;
...
...
include/asm-i386/bitops.h
View file @
74beaae0
...
...
@@ -121,4 +121,16 @@ extern inline int find_next_zero_bit (unsigned long * addr, int size,
return
(
offset
+
set
+
res
);
}
/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
*/
extern
inline
unsigned
long
ffz
(
unsigned
long
word
)
{
__asm__
(
"bsfl %1,%0"
:
"=r"
(
word
)
:
"r"
(
~
word
));
return
word
;
}
#endif
/* _I386_BITOPS_H */
include/linux/ncp.h
0 → 100644
View file @
74beaae0
#ifndef _LINUX_NCP_H_
#define _LINUX_NCP_H_
#define NCP_OPEN 0x1111
#define NCP_CLOSE 0x5555
#define NCP_REQUEST 0x2222
#define NCP_REPLY 0x3333
struct
ncp_request
{
unsigned
short
p_type
__attribute__
((
packed
));
unsigned
char
seq
__attribute__
((
packed
));
unsigned
char
c_low
__attribute__
((
packed
));
unsigned
char
task
__attribute__
((
packed
));
unsigned
char
c_high
__attribute__
((
packed
));
unsigned
char
func
__attribute__
((
packed
));
};
struct
ncp_request_sf
{
unsigned
short
p_type
__attribute__
((
packed
));
unsigned
char
seq
__attribute__
((
packed
));
unsigned
char
c_low
__attribute__
((
packed
));
unsigned
char
task
__attribute__
((
packed
));
unsigned
char
c_high
__attribute__
((
packed
));
unsigned
char
func
__attribute__
((
packed
));
unsigned
short
s_len
__attribute__
((
packed
));
unsigned
char
s_func
__attribute__
((
packed
));
};
struct
ncp_reply
{
unsigned
short
p_type
__attribute__
((
packed
));
unsigned
char
seq
__attribute__
((
packed
));
unsigned
char
c_low
__attribute__
((
packed
));
unsigned
char
task
__attribute__
((
packed
));
unsigned
char
c_high
__attribute__
((
packed
));
unsigned
char
f_stat
__attribute__
((
packed
));
unsigned
char
c_stat
__attribute__
((
packed
));
};
#define OTYPE_USER 0x0001
#define OTYPE_GROUP 0x0002
#define OTYPE_PQUEUE 0x0003
#define OTYPE_FSERVER 0x0004
#define OTYPE_JSERVER 0x0005
#define OTYPE_PSERVER 0x0007
#define OTYPE_UNKNOWN_1 0x002E
#define OTYPE_ADV_PSERVER 0x0047
#define OTYPE_AFSERVER 0x0107
#define OTYPE_UNKNOWN_2 0x0143
#define OTYPE_UNKNOWN_3 0x01F5
#define OTYPE_UNKNOWN_4 0x023F
#define LIMIT_OBJNAME 47
struct
bind_obj
{
unsigned
long
id
__attribute__
((
packed
));
unsigned
short
type
__attribute__
((
packed
));
char
name
[
LIMIT_OBJNAME
+
1
]
__attribute__
((
packed
));
};
struct
get_bind_obj
{
unsigned
short
type
__attribute__
((
packed
));
unsigned
char
n_len
__attribute__
((
packed
));
char
name
[
0
]
__attribute__
((
packed
));
};
struct
scan_bind_obj
{
unsigned
long
id
__attribute__
((
packed
));
unsigned
short
type
__attribute__
((
packed
));
unsigned
char
n_len
__attribute__
((
packed
));
char
name
[
0
]
__attribute__
((
packed
));
};
struct
login_req
{
unsigned
char
password
[
8
]
__attribute__
((
packed
));
unsigned
short
type
__attribute__
((
packed
));
unsigned
char
n_len
__attribute__
((
packed
));
char
name
[
0
]
__attribute__
((
packed
));
};
struct
ncp_time
{
unsigned
char
year
__attribute__
((
packed
));
unsigned
char
month
__attribute__
((
packed
));
unsigned
char
day
__attribute__
((
packed
));
unsigned
char
hours
__attribute__
((
packed
));
unsigned
char
mins
__attribute__
((
packed
));
unsigned
char
secs
__attribute__
((
packed
));
unsigned
char
c_secs
__attribute__
((
packed
));
};
struct
login_info
{
unsigned
long
id
__attribute__
((
packed
));
unsigned
short
un1
__attribute__
((
packed
));
char
name
[
LIMIT_OBJNAME
+
1
]
__attribute__
((
packed
));
struct
ncp_time
time
__attribute__
((
packed
));
};
#endif
include/linux/socket.h
View file @
74beaae0
...
...
@@ -20,6 +20,7 @@ struct linger {
#define SOCK_RAW 3
/* raw socket */
#define SOCK_RDM 4
/* reliably-delivered message */
#define SOCK_SEQPACKET 5
/* sequential packet socket */
#define SOCK_NCP 6
/* Novell NCP socket */
#define SOCK_PACKET 10
/* linux specific way of */
/* getting packets at the dev */
/* level. For writing rarp and */
...
...
net/inet/datagram.c
View file @
74beaae0
...
...
@@ -177,7 +177,8 @@ int datagram_select(struct sock *sk, int sel_type, select_table *wait)
switch
(
sel_type
)
{
case
SEL_IN
:
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
sk
->
state
==
TCP_CLOSE
)
if
((
sk
->
type
==
SOCK_SEQPACKET
||
sk
->
type
==
SOCK_NCP
)
&&
sk
->
state
==
TCP_CLOSE
)
{
/* Connection closed: Wake up */
return
(
1
);
...
...
net/inet/ipx.c
View file @
74beaae0
...
...
@@ -56,8 +56,16 @@
#include <linux/termios.h>
/* For TIOCOUTQ/INQ */
#include <linux/interrupt.h>
#include "p8022.h"
#include "ncp.h"
#ifdef CONFIG_IPX
static
void
ipx_delete_timer
(
ipx_socket
*
sk
);
static
int
ipx_do_sendto
(
ipx_socket
*
sk
,
ipx_address
*
ipx
,
void
*
ubuf
,
int
len
,
int
flag
,
unsigned
char
type
);
static
void
ipx_add_timer
(
ipx_socket
*
sk
,
int
len
);
static
void
ipx_reset_timer
(
ipx_socket
*
sk
,
int
len
);
/***********************************************************************************************************************\
* *
* Handlers for the socket list. *
...
...
@@ -75,7 +83,9 @@ static ipx_socket *volatile ipx_socket_list=NULL;
static
void
ipx_remove_socket
(
ipx_socket
*
sk
)
{
ipx_socket
*
s
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
s
=
ipx_socket_list
;
if
(
s
==
sk
)
...
...
@@ -89,20 +99,23 @@ static void ipx_remove_socket(ipx_socket *sk)
if
(
s
->
next
==
sk
)
{
s
->
next
=
sk
->
next
;
sti
(
);
restore_flags
(
flags
);
return
;
}
s
=
s
->
next
;
}
sti
(
);
restore_flags
(
flags
);
}
static
void
ipx_insert_socket
(
ipx_socket
*
sk
)
{
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
sk
->
next
=
ipx_socket_list
;
ipx_socket_list
=
sk
;
sti
(
);
restore_flags
(
flags
);
}
static
ipx_socket
*
ipx_find_socket
(
int
port
)
...
...
@@ -133,9 +146,10 @@ static void ipx_destroy_socket(ipx_socket *sk)
ipx_remove_socket
(
sk
);
while
((
skb
=
skb_dequeue
(
&
sk
->
receive_queue
))
!=
NULL
)
{
kfree_skb
(
skb
,
FREE_READ
);
}
while
((
skb
=
skb_dequeue
(
&
sk
->
write_queue
))
!=
NULL
)
kfree_skb
(
skb
,
FREE_WRITE
);
kfree_s
(
sk
,
sizeof
(
*
sk
));
}
...
...
@@ -151,20 +165,24 @@ int ipx_get_info(char *buffer, char **start, off_t offset, int length)
/* Theory.. Keep printing in the same place until we pass offset */
len
+=
sprintf
(
buffer
,
"
Type local_address rem_address
tx_queue rx_queue st uid
\n
"
);
len
+=
sprintf
(
buffer
,
"
local_address rem_address
tx_queue rx_queue st uid
\n
"
);
for
(
s
=
ipx_socket_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
len
+=
sprintf
(
buffer
+
len
,
"%02X "
,
s
->
ipx_type
);
len
+=
sprintf
(
buffer
+
len
,
"%08lX:%02X%02X%02X%02X%02X%02X:%0
2
X "
,
htonl
(
s
->
ipx_source_addr
.
net
),
len
+=
sprintf
(
buffer
+
len
,
"%08lX:%02X%02X%02X%02X%02X%02X:%0
4
X "
,
htonl
(
s
->
ipx_source_addr
.
net
),
s
->
ipx_source_addr
.
node
[
0
],
s
->
ipx_source_addr
.
node
[
1
],
s
->
ipx_source_addr
.
node
[
2
],
s
->
ipx_source_addr
.
node
[
3
],
s
->
ipx_source_addr
.
node
[
4
],
s
->
ipx_source_addr
.
node
[
5
],
htons
(
s
->
ipx_source_addr
.
sock
));
len
+=
sprintf
(
buffer
+
len
,
"%08lX:%02X%02X%02X%02X%02X%02X:%0
2
X "
,
htonl
(
s
->
ipx_dest_addr
.
net
),
len
+=
sprintf
(
buffer
+
len
,
"%08lX:%02X%02X%02X%02X%02X%02X:%0
4
X "
,
htonl
(
s
->
ipx_dest_addr
.
net
),
s
->
ipx_dest_addr
.
node
[
0
],
s
->
ipx_dest_addr
.
node
[
1
],
s
->
ipx_dest_addr
.
node
[
2
],
s
->
ipx_dest_addr
.
node
[
3
],
s
->
ipx_dest_addr
.
node
[
4
],
s
->
ipx_dest_addr
.
node
[
5
],
htons
(
s
->
ipx_dest_addr
.
sock
));
len
+=
sprintf
(
buffer
+
len
,
"%08lX:%08lX "
,
s
->
wmem_alloc
,
s
->
rmem_alloc
);
len
+=
sprintf
(
buffer
+
len
,
"%02X %d
\n
"
,
s
->
state
,
SOCK_INODE
(
s
->
socket
)
->
i_uid
);
len
+=
sprintf
(
buffer
+
len
,
"%02X "
,
s
->
state
);
if
(
s
->
socket
)
len
+=
sprintf
(
buffer
+
len
,
"%d
\n
"
,
SOCK_INODE
(
s
->
socket
)
->
i_uid
);
else
len
+=
sprintf
(
buffer
+
len
,
"%d
\n
"
,
SOCK_INODE
(
s
->
ncp
.
ncp
->
socket
)
->
i_uid
);
/* Are we still dumping unwanted data then discard the record */
pos
=
begin
+
len
;
...
...
@@ -566,20 +584,56 @@ static void def_callback2(struct sock *sk, int len)
wake_up_interruptible
(
sk
->
sleep
);
}
static
int
ipx_create
(
struct
socket
*
sock
,
int
protocol
)
static
void
watch_callback
(
struct
sock
*
sk
,
int
len
)
{
ipx_socket
*
sk
;
sk
=
(
ipx_socket
*
)
kmalloc
(
sizeof
(
*
sk
),
GFP_KERNEL
);
if
(
sk
==
NULL
)
return
(
-
ENOMEM
);
switch
(
sock
->
type
)
ipx_packet
*
ipx
;
struct
sk_buff
*
skb
;
char
*
data
;
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
if
(
skb
==
NULL
)
return
;
ipx
=
(
ipx_packet
*
)(
skb
->
h
.
raw
);
data
=
(
char
*
)(
ipx
+
1
);
if
(
*
(
data
+
1
)
==
'?'
)
ipx_do_sendto
(
sk
,
&
(
ipx
->
ipx_source
),
"
\0
Y"
,
2
,
0
,
sk
->
ipx_type
);
kfree_skb
(
skb
,
FREE_READ
);
}
static
void
mail_callback
(
struct
sock
*
sk
,
int
len
)
{
ipx_packet
*
ipx
;
struct
sk_buff
*
skb
;
char
*
data
;
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
if
(
skb
==
NULL
)
return
;
ipx
=
(
ipx_packet
*
)(
skb
->
h
.
raw
);
data
=
(
char
*
)(
ipx
+
1
);
if
(
*
(
data
+
1
)
==
'!'
)
{
case
SOCK_DGRAM
:
break
;
default:
kfree_s
((
void
*
)
sk
,
sizeof
(
*
sk
));
return
(
-
ESOCKTNOSUPPORT
);
struct
ncp_request_sf
req
;
req
.
func
=
0x15
;
req
.
s_func
=
0x01
;
req
.
s_len
=
htons
(
1
);
ipx_do_sendto
(
sk
->
ncp
.
ncp
,
&
(
sk
->
ncp
.
ncp
->
ipx_dest_addr
),
&
req
,
sizeof
(
req
),
0
,
sk
->
ncp
.
ncp
->
ipx_type
);
}
kfree_skb
(
skb
,
FREE_READ
);
}
static
void
ipx_do_create
(
struct
socket
*
sock
,
ipx_socket
*
sk
)
{
sk
->
dead
=
0
;
sk
->
next
=
NULL
;
sk
->
broadcast
=
0
;
...
...
@@ -598,7 +652,6 @@ static int ipx_create(struct socket *sock, int protocol)
skb_queue_head_init
(
&
sk
->
back_log
);
sk
->
state
=
TCP_CLOSE
;
sk
->
socket
=
sock
;
sk
->
type
=
sock
->
type
;
sk
->
ipx_type
=
0
;
/* General user level IPX */
sk
->
debug
=
0
;
...
...
@@ -610,14 +663,76 @@ static int ipx_create(struct socket *sock, int protocol)
{
sock
->
data
=
(
void
*
)
sk
;
sk
->
sleep
=
sock
->
wait
;
sk
->
type
=
sock
->
type
;
}
else
sk
->
type
=
SOCK_DGRAM
;
sk
->
priority
=
SOPRI_NORMAL
;
sk
->
state_change
=
def_callback1
;
sk
->
data_ready
=
def_callback2
;
sk
->
write_space
=
def_callback1
;
sk
->
error_report
=
def_callback1
;
sk
->
zapped
=
1
;
return
;
}
static
int
ncp_create
(
struct
socket
*
sock
,
int
protocol
)
{
ipx_socket
*
sk
;
ipx_socket
*
skw
;
ipx_socket
*
skm
;
if
((
sk
=
(
ipx_socket
*
)
kmalloc
(
sizeof
(
*
sk
),
GFP_KERNEL
))
==
NULL
)
return
(
-
ENOMEM
);
if
((
skw
=
(
ipx_socket
*
)
kmalloc
(
sizeof
(
*
skw
),
GFP_KERNEL
))
==
NULL
)
{
kfree_s
((
void
*
)
sk
,
sizeof
(
*
sk
));
return
(
-
ENOMEM
);
}
if
((
skm
=
(
ipx_socket
*
)
kmalloc
(
sizeof
(
*
skm
),
GFP_KERNEL
))
==
NULL
)
{
kfree_s
((
void
*
)
skw
,
sizeof
(
*
skw
));
kfree_s
((
void
*
)
sk
,
sizeof
(
*
sk
));
return
(
-
ENOMEM
);
}
ipx_do_create
(
sock
,
sk
);
sk
->
ncp
.
ncp
=
NULL
;
sk
->
ncp
.
watchdog
=
skw
;
sk
->
ncp
.
mail
=
skm
;
ipx_do_create
(
NULL
,
skw
);
skw
->
ncp
.
ncp
=
sk
;
skw
->
data_ready
=
watch_callback
;
ipx_do_create
(
NULL
,
skm
);
skm
->
ncp
.
ncp
=
sk
;
skm
->
data_ready
=
mail_callback
;
return
(
0
);
}
static
int
ipx_create
(
struct
socket
*
sock
,
int
protocol
)
{
ipx_socket
*
sk
;
switch
(
sock
->
type
)
{
case
SOCK_DGRAM
:
break
;
case
SOCK_NCP
:
return
(
ncp_create
(
sock
,
protocol
));
default:
return
(
-
ESOCKTNOSUPPORT
);
}
if
((
sk
=
(
ipx_socket
*
)
kmalloc
(
sizeof
(
*
sk
),
GFP_KERNEL
))
==
NULL
)
return
(
-
ENOMEM
);
ipx_do_create
(
sock
,
sk
);
return
(
0
);
}
...
...
@@ -633,40 +748,72 @@ static int ipx_release(struct socket *sock, struct socket *peer)
return
(
0
);
if
(
!
sk
->
dead
)
sk
->
state_change
(
sk
);
sk
->
dead
=
1
;
sock
->
data
=
NULL
;
if
(
sk
->
type
==
SOCK_NCP
)
{
sk
->
ncp
.
watchdog
->
dead
=
1
;
ipx_destroy_socket
(
sk
->
ncp
.
watchdog
);
sk
->
ncp
.
mail
->
dead
=
1
;
ipx_destroy_socket
(
sk
->
ncp
.
mail
);
if
((
sk
->
state
==
TCP_ESTABLISHED
)
||
(
sk
->
state
==
TCP_SYN_SENT
))
{
struct
ncp_request
req
;
sk
->
state
=
TCP_CLOSE_WAIT
;
ipx_do_sendto
(
sk
,
&
(
sk
->
ipx_dest_addr
),
&
req
,
sizeof
(
req
),
0
,
sk
->
ipx_type
);
}
else
{
sk
->
dead
=
1
;
if
(
sk
->
state
!=
TCP_CLOSE
)
ipx_delete_timer
(
sk
);
ipx_destroy_socket
(
sk
);
}
}
else
{
sk
->
dead
=
1
;
ipx_destroy_socket
(
sk
);
}
return
(
0
);
}
static
unsigned
short
first_free_socketnum
(
void
)
{
static
unsigned
short
socketNum
=
0x
4000
;
static
unsigned
short
socketNum
=
0x
3fff
;
while
(
ipx_find_socket
(
htons
(
socketNum
))
!=
NULL
)
if
(
socketNum
>
0x7ffc
)
socketNum
=
0x
4000
;
while
(
ipx_find_socket
(
htons
(
++
socketNum
))
!=
NULL
)
if
(
socketNum
>
0x7ffc
)
socketNum
=
0x
3fff
;
return
htons
(
socketNum
++
);
return
htons
(
socketNum
);
}
static
int
ipx_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
addr_len
)
{
ipx_socket
*
sk
;
ipx_socket
*
sk
=
(
ipx_socket
*
)
sock
->
data
;
struct
ipx_route
*
rt
;
unsigned
char
*
nodestart
;
struct
sockaddr_ipx
*
addr
=
(
struct
sockaddr_ipx
*
)
uaddr
;
sk
=
(
ipx_socket
*
)
sock
->
data
;
if
(
sk
->
zapped
==
0
)
return
(
-
EIO
);
if
(
addr_len
!=
sizeof
(
struct
sockaddr_ipx
))
return
-
EINVAL
;
if
(
addr
->
sipx_port
==
0
)
{
addr
->
sipx_port
=
first_free_socketnum
();
if
(
sk
->
type
==
SOCK_NCP
)
while
((
ipx_find_socket
(
htons
(
ntohs
(
addr
->
sipx_port
)
+
1
)))
||
(
ipx_find_socket
(
htons
(
ntohs
(
addr
->
sipx_port
)
+
2
))))
addr
->
sipx_port
=
first_free_socketnum
();
if
(
addr
->
sipx_port
==
0
)
return
-
EINVAL
;
}
...
...
@@ -685,6 +832,19 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
return
-
EADDRINUSE
;
}
if
(
sk
->
type
==
SOCK_NCP
)
{
if
((
ipx_find_socket
(
htons
(
ntohs
(
addr
->
sipx_port
)
+
1
)))
||
(
ipx_find_socket
(
htons
(
ntohs
(
addr
->
sipx_port
)
+
2
))))
{
if
(
sk
->
debug
)
printk
(
"IPX: bind failed because port %X in use.
\n
"
,
(
int
)
addr
->
sipx_port
);
return
-
EADDRINUSE
;
}
addr
->
sipx_type
=
IPX_TYPE_NCP
;
}
sk
->
ipx_source_addr
.
sock
=
addr
->
sipx_port
;
if
(
addr
->
sipx_network
==
0L
)
...
...
@@ -705,6 +865,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
}
sk
->
ipx_source_addr
.
net
=
rt
->
net
;
sk
->
ipx_type
=
addr
->
sipx_type
;
/* IPX addresses zero pad physical addresses less than 6 */
memset
(
sk
->
ipx_source_addr
.
node
,
'\0'
,
6
);
...
...
@@ -713,41 +874,102 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
ipx_insert_socket
(
sk
);
sk
->
zapped
=
0
;
if
(
sk
->
type
==
SOCK_NCP
)
{
sk
->
ncp
.
watchdog
->
ipx_source_addr
.
net
=
rt
->
net
;
sk
->
ncp
.
watchdog
->
ipx_source_addr
.
sock
=
htons
(
ntohs
(
addr
->
sipx_port
)
+
1
);
memset
(
sk
->
ncp
.
watchdog
->
ipx_source_addr
.
node
,
'\0'
,
6
);
nodestart
=
sk
->
ncp
.
watchdog
->
ipx_source_addr
.
node
+
(
6
-
rt
->
dev
->
addr_len
);
memcpy
(
nodestart
,
rt
->
dev
->
dev_addr
,
rt
->
dev
->
addr_len
);
ipx_insert_socket
(
sk
->
ncp
.
watchdog
);
sk
->
ncp
.
watchdog
->
zapped
=
0
;
sk
->
ncp
.
mail
->
ipx_source_addr
.
net
=
rt
->
net
;
sk
->
ncp
.
mail
->
ipx_source_addr
.
sock
=
htons
(
ntohs
(
addr
->
sipx_port
)
+
2
);
memset
(
sk
->
ncp
.
mail
->
ipx_source_addr
.
node
,
'\0'
,
6
);
nodestart
=
sk
->
ncp
.
mail
->
ipx_source_addr
.
node
+
(
6
-
rt
->
dev
->
addr_len
);
memcpy
(
nodestart
,
rt
->
dev
->
dev_addr
,
rt
->
dev
->
addr_len
);
ipx_insert_socket
(
sk
->
ncp
.
mail
);
sk
->
ncp
.
mail
->
zapped
=
0
;
sk
->
mtu
=
rt
->
dev
->
mtu
;
}
if
(
sk
->
debug
)
printk
(
"IPX: socket is bound.
\n
"
);
return
(
0
);
}
static
int
ncp_connect
(
struct
socket
*
sock
,
ipx_socket
*
sk
)
{
struct
ncp_request
req
;
int
err
;
sk
->
ncp
.
conn
=
0xffff
;
sk
->
ncp
.
seq
=
0
;
sock
->
state
=
SS_CONNECTING
;
sk
->
state
=
TCP_SYN_SENT
;
sk
->
rto
=
0
;
ipx_do_sendto
(
sk
,
&
(
sk
->
ipx_dest_addr
),
&
req
,
sizeof
(
req
),
0
,
sk
->
ipx_type
);
while
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
if
(
sk
->
err
)
{
err
=
sk
->
err
;
sk
->
err
=
0
;
return
-
err
;
}
interruptible_sleep_on
(
sk
->
sleep
);
}
return
(
0
);
}
static
int
ipx_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
addr_len
,
int
flags
)
{
ipx_socket
*
sk
=
(
ipx_socket
*
)
sock
->
data
;
struct
sockaddr_ipx
*
addr
;
struct
sockaddr_ipx
*
addr
=
(
struct
sockaddr_ipx
*
)
uaddr
;
sk
->
state
=
TCP_CLOSE
;
sock
->
state
=
SS_UNCONNECTED
;
if
(
addr_len
!=
sizeof
(
addr
))
if
(
addr_len
!=
sizeof
(
struct
sockaddr_ipx
))
return
(
-
EINVAL
);
addr
=
(
struct
sockaddr_ipx
*
)
uaddr
;
if
(
sk
->
ipx_source_addr
.
net
==
0
)
if
(
sk
->
ipx_source_addr
.
sock
==
0
)
/* put the autobinding in */
{
struct
sockaddr_ipx
uaddr
;
int
ret
;
struct
sockaddr_ipx
addr
;
uaddr
.
sipx_port
=
0
;
uaddr
.
sipx_network
=
0L
;
ret
=
ipx_bind
(
sock
,
(
struct
sockaddr
*
)
&
uaddr
,
sizeof
(
struct
sockaddr_ipx
));
addr
.
sipx_type
=
0
;
addr
.
sipx_port
=
0
;
addr
.
sipx_network
=
0L
;
ret
=
ipx_bind
(
sock
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
struct
sockaddr_ipx
));
if
(
ret
!=
0
)
return
(
ret
);
}
sk
->
ipx_dest_addr
.
net
=
addr
->
sipx_network
;
sk
->
ipx_dest_addr
.
sock
=
addr
->
sipx_port
;
memcpy
(
sk
->
ipx_dest_addr
.
node
,
addr
->
sipx_node
,
sizeof
(
sk
->
ipx_source_addr
.
node
));
if
(
ipxrtr_get_dev
(
sk
->
ipx_dest_addr
.
net
)
==
NULL
)
return
-
ENETUNREACH
;
if
(
sk
->
type
==
SOCK_NCP
)
return
(
ncp_connect
(
sock
,
sk
));
sk
->
ipx_type
=
addr
->
sipx_type
;
sock
->
state
=
SS_CONNECTED
;
sk
->
state
=
TCP_ESTABLISHED
;
return
(
0
);
...
...
@@ -770,9 +992,8 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
{
ipx_address
*
addr
;
struct
sockaddr_ipx
sipx
;
ipx_socket
*
sk
;
ipx_socket
*
sk
=
(
ipx_socket
*
)
sock
->
data
;
sk
=
(
ipx_socket
*
)
sock
->
data
;
*
uaddr_len
=
sizeof
(
struct
sockaddr_ipx
);
...
...
@@ -783,7 +1004,21 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
addr
=&
sk
->
ipx_dest_addr
;
}
else
{
if
(
sk
->
ipx_source_addr
.
sock
==
0
)
/* put the autobinding in */
{
int
ret
;
sipx
.
sipx_type
=
0
;
sipx
.
sipx_port
=
0
;
sipx
.
sipx_network
=
0L
;
ret
=
ipx_bind
(
sock
,
(
struct
sockaddr
*
)
&
sipx
,
sizeof
(
struct
sockaddr_ipx
));
if
(
ret
!=
0
)
return
(
ret
);
}
addr
=&
sk
->
ipx_source_addr
;
}
sipx
.
sipx_family
=
AF_IPX
;
sipx
.
sipx_port
=
addr
->
sock
;
...
...
@@ -793,79 +1028,484 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
return
(
0
);
}
int
ipx_rcv
(
struct
sk_buff
*
skb
,
struct
device
*
dev
,
struct
packet_type
*
pt
)
static
int
ipx_build_header
(
ipx_address
*
ipx
,
struct
sk_buff
*
skb
,
ipx_socket
*
sk
,
int
len
,
unsigned
char
type
)
{
/* NULL here for pt means the packet was looped back */
ipx_socket
*
sock
;
ipx_packet
*
ipx
;
ipx_packet
*
ipx_pack
;
ipx_route
*
rt
;
ipx_route
*
ln
;
struct
datalink_proto
*
dl
=
NULL
;
unsigned
char
IPXaddr
[
6
];
int
self_addressing
=
0
;
int
broadcast
=
0
;
ipx
=
(
ipx_packet
*
)
skb
->
h
.
raw
;
if
(
sk
->
debug
)
printk
(
"IPX: build_header: Addresses built.
\n
"
);
if
(
ipx
->
ipx_checksum
!=
IPX_NO_CHECKSUM
)
if
(
memcmp
(
&
ipx
->
node
,
&
ipx_broadcast_node
,
6
)
==
0
)
{
/* We don't do checksum options. We can't really. Novell don't seem to have documented them.
If you need them try the XNS checksum since IPX is basically XNS in disguise. It might be
the same... */
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
if
(
!
sk
->
broadcast
)
return
-
ENETUNREACH
;
broadcast
=
1
;
}
/* Too small */
if
(
htons
(
ipx
->
ipx_pktsize
)
<
sizeof
(
ipx_packet
))
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
/* Build a packet */
/* Too many hops */
if
(
ipx
->
ipx_tctrl
>
16
)
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
if
(
sk
->
debug
)
printk
(
"IPX: build_header: building packet.
\n
"
);
/* Determine what local ipx endpoint this is */
ln
=
ipxrtr_get_local_net
(
dev
,
pt
->
type
);
if
(
ln
==
NULL
)
/* Find out where this has to go */
if
(
ipx
->
net
==
0L
)
{
rt
=
ipxrtr_get_default_net
();
if
(
rt
!=
NULL
)
ipx
->
net
=
rt
->
net
;
}
else
rt
=
ipxrtr_get_dev
(
ipx
->
net
);
if
(
rt
==
NULL
)
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
return
-
ENETUNREACH
;
}
memset
(
IPXaddr
,
'\0'
,
6
);
memcpy
(
IPXaddr
+
(
6
-
dev
->
addr_len
),
dev
->
dev_addr
,
dev
->
addr_len
);
dl
=
rt
->
datalink
;
/* Not us/broadcast */
if
(
memcmp
(
IPXaddr
,
ipx
->
ipx_dest
.
node
,
6
)
!=
0
&&
memcmp
(
ipx_broadcast_node
,
ipx
->
ipx_dest
.
node
,
6
)
!=
0
)
{
/**********************************************************************************************
skb
->
mem_addr
=
skb
;
skb
->
sk
=
sk
;
skb
->
free
=
1
;
skb
->
arp
=
1
;
skb
->
tries
=
0
;
IPX router. Roughly as per the Novell spec. This doesn't handle netbios flood fill
broadcast frames. See the Novell IPX router specification for more details
(for ftp from ftp.novell.com)
if
(
sk
->
debug
)
printk
(
"Building MAC header.
\n
"
);
skb
->
dev
=
rt
->
dev
;
***********************************************************************************************/
/* Build Data Link header */
dl
->
datalink_header
(
dl
,
skb
,
(
rt
->
flags
&
IPX_RT_ROUTED
)
?
rt
->
router_node
:
ipx
->
node
);
int
incoming_size
;
int
outgoing_size
;
struct
sk_buff
*
skb2
;
int
free_it
=
0
;
/* See if we are sending to ourself */
memset
(
IPXaddr
,
'\0'
,
6
)
;
memcpy
(
IPXaddr
+
(
6
-
skb
->
dev
->
addr_len
),
skb
->
dev
->
dev_addr
,
skb
->
dev
->
addr_len
)
;
/* Rule: Don't forward packets that have exceeded the hop limit. This is fixed at 16 in IPX */
if
(
ipx
->
ipx_tctrl
==
16
)
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
self_addressing
=
!
memcmp
(
IPXaddr
,
(
rt
->
flags
&
IPX_RT_ROUTED
)
?
rt
->
router_node
:
ipx
->
node
,
6
);
ipx
->
ipx_tctrl
++
;
/* Don't forward if we don't have a route. We ought to go off and start hunting out routes but
if someone needs this _THEY_ can add it */
rt
=
ipxrtr_get_dev
(
ipx
->
ipx_dest
.
net
);
/* Now the IPX */
if
(
sk
->
debug
)
printk
(
"Building IPX Header.
\n
"
);
ipx_pack
=
(
ipx_packet
*
)
skb
->
h
.
raw
;
ipx_pack
->
ipx_checksum
=
0xFFFF
;
ipx_pack
->
ipx_pktsize
=
htons
(
len
+
sizeof
(
ipx_packet
));
ipx_pack
->
ipx_tctrl
=
0
;
ipx_pack
->
ipx_type
=
type
;
memcpy
(
&
ipx_pack
->
ipx_source
,
&
sk
->
ipx_source_addr
,
sizeof
(
ipx_pack
->
ipx_source
));
memcpy
(
&
ipx_pack
->
ipx_dest
,
ipx
,
sizeof
(
ipx_pack
->
ipx_dest
));
if
((
skb
->
dev
->
flags
&
IFF_LOOPBACK
)
||
self_addressing
)
skb
->
pkt_type
=
PACKET_HOST
;
else
if
(
broadcast
)
skb
->
pkt_type
=
PACKET_BROADCAST
;
else
skb
->
pkt_type
=
PACKET_OTHERHOST
;
return
0
;
}
static
int
ipx_xmit
(
struct
sk_buff
*
skb
)
{
struct
sk_buff
*
skb1
;
struct
device
*
dev
=
skb
->
dev
;
ipx_packet
*
ipx
=
(
ipx_packet
*
)
skb
->
h
.
raw
;
ipx_route
*
rt
;
struct
packet_type
pt
;
if
(
ipx
->
ipx_dest
.
net
==
0L
)
rt
=
ipxrtr_get_default_net
();
else
rt
=
ipxrtr_get_dev
(
ipx
->
ipx_dest
.
net
);
if
(
rt
==
NULL
)
return
-
ENETUNREACH
;
pt
.
type
=
rt
->
dlink_type
;
skb
->
tries
++
;
switch
(
skb
->
pkt_type
)
{
case
PACKET_HOST
:
if
(
!
skb
->
free
)
{
skb1
=
alloc_skb
(
skb
->
len
,
GFP_ATOMIC
);
if
(
skb1
!=
NULL
)
{
skb1
->
mem_addr
=
skb1
;
skb1
->
free
=
1
;
skb1
->
arp
=
1
;
skb1
->
len
=
skb
->
len
;
skb1
->
sk
=
NULL
;
skb1
->
h
.
raw
=
skb1
->
data
+
rt
->
datalink
->
header_length
+
dev
->
hard_header_len
;
memcpy
(
skb1
->
data
,
skb
->
data
,
skb
->
len
);
ipx_rcv
(
skb1
,
dev
,
&
pt
);
}
}
else
{
/* loop back */
skb
->
sk
->
wmem_alloc
-=
skb
->
mem_len
;
skb
->
sk
=
NULL
;
ipx_rcv
(
skb
,
dev
,
&
pt
);
}
break
;
case
PACKET_BROADCAST
:
skb1
=
alloc_skb
(
skb
->
len
,
GFP_ATOMIC
);
if
(
skb1
!=
NULL
)
{
skb1
->
mem_addr
=
skb1
;
skb1
->
free
=
1
;
skb1
->
arp
=
1
;
skb1
->
len
=
skb
->
len
;
skb1
->
sk
=
NULL
;
skb1
->
h
.
raw
=
skb1
->
data
+
rt
->
datalink
->
header_length
+
dev
->
hard_header_len
;
memcpy
(
skb1
->
data
,
skb
->
data
,
skb
->
len
);
ipx_rcv
(
skb1
,
dev
,
&
pt
);
}
default:
if
(
!
skb
->
free
)
{
skb1
=
alloc_skb
(
skb
->
len
,
GFP_ATOMIC
);
if
(
skb1
!=
NULL
)
{
skb1
->
mem_addr
=
skb1
;
skb1
->
free
=
1
;
skb1
->
arp
=
1
;
skb1
->
len
=
skb
->
len
;
skb1
->
sk
=
NULL
;
skb1
->
h
.
raw
=
skb1
->
data
+
rt
->
datalink
->
header_length
+
dev
->
hard_header_len
;
memcpy
(
skb1
->
data
,
skb
->
data
,
skb
->
len
);
}
}
else
skb1
=
skb
;
if
(
skb1
!=
NULL
)
{
if
(
skb1
->
sk
)
dev_queue_xmit
(
skb1
,
dev
,
skb
->
sk
->
priority
);
else
dev_queue_xmit
(
skb1
,
dev
,
SOPRI_NORMAL
);
}
}
return
(
0
);
}
static
int
ipx_retransmit
(
ipx_socket
*
sk
)
{
struct
sk_buff
*
skb
=
sk
->
write_queue
.
next
;
int
num
=
0
;
ipx_packet
*
ipx
;
struct
ncp_request
*
req
;
if
(
skb
==
NULL
)
return
(
num
);
if
(
skb
==
skb
->
next
)
return
(
num
);
do
{
ipx
=
(
ipx_packet
*
)
skb
->
h
.
raw
;
req
=
(
struct
ncp_request
*
)(
ipx
+
1
);
ipx_xmit
(
skb
);
num
++
;
skb
=
skb
->
next
;
}
while
(
skb
->
next
!=
sk
->
write_queue
.
next
);
return
(
num
);
}
static
void
ipx_timer
(
unsigned
long
data
)
{
ipx_socket
*
sk
=
(
ipx_socket
*
)
data
;
int
num
;
cli
();
if
(
in_bh
)
{
sk
->
timer
.
expires
=
10
;
add_timer
(
&
sk
->
timer
);
sti
();
return
;
}
sti
();
num
=
ipx_retransmit
(
sk
);
sk
->
rto
++
;
if
(
sk
->
rto
>=
MAX_TIMEOUT
)
{
struct
sk_buff
*
skb
;
while
((
skb
=
skb_dequeue
(
&
sk
->
write_queue
))
!=
NULL
)
kfree_skb
(
skb
,
FREE_WRITE
);
sk
->
err
=
ETIMEDOUT
;
sk
->
state
=
TCP_CLOSE
;
sk
->
socket
->
state
=
SS_UNCONNECTED
;
if
(
!
sk
->
dead
)
sk
->
error_report
(
sk
);
return
;
}
if
(
num
)
ipx_reset_timer
(
sk
,
NCP_TIMEOUT
);
return
;
}
static
void
ipx_delete_timer
(
ipx_socket
*
sk
)
{
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
del_timer
(
&
sk
->
timer
);
restore_flags
(
flags
);
}
static
void
ipx_add_timer
(
ipx_socket
*
sk
,
int
len
)
{
init_timer
(
&
sk
->
timer
);
sk
->
timer
.
data
=
(
unsigned
long
)
sk
;
sk
->
timer
.
function
=
&
ipx_timer
;
sk
->
timer
.
expires
=
len
;
add_timer
(
&
sk
->
timer
);
}
static
void
ipx_reset_timer
(
ipx_socket
*
sk
,
int
len
)
{
ipx_delete_timer
(
sk
);
sk
->
timer
.
data
=
(
unsigned
long
)
sk
;
sk
->
timer
.
function
=
&
ipx_timer
;
sk
->
timer
.
expires
=
len
;
add_timer
(
&
sk
->
timer
);
}
static
struct
sk_buff
*
find_req
(
ipx_socket
*
sk
,
unsigned
char
seq
)
{
ipx_packet
*
ipx
;
struct
ncp_request
*
req
;
struct
sk_buff
*
skb
=
sk
->
write_queue
.
next
;
if
(
skb
==
NULL
)
return
(
NULL
);
if
(
skb
==
skb
->
next
)
return
(
NULL
);
do
{
ipx
=
(
ipx_packet
*
)
skb
->
h
.
raw
;
req
=
(
struct
ncp_request
*
)(
ipx
+
1
);
if
(
req
->
seq
==
seq
)
{
skb_unlink
(
skb
);
return
(
skb
);
}
skb
=
skb
->
next
;
}
while
(
skb
->
next
!=
sk
->
write_queue
.
next
);
return
(
NULL
);
}
static
int
ncp_rcv
(
ipx_socket
*
sk
,
struct
sk_buff
*
skb
)
{
ipx_packet
*
ipx
=
(
ipx_packet
*
)
skb
->
h
.
raw
;
struct
ncp_reply
*
rep
=
(
struct
ncp_reply
*
)(
ipx
+
1
);
struct
ncp_request_sf
*
req
;
struct
sk_buff
*
skb1
;
if
(
rep
->
p_type
!=
NCP_REPLY
)
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
skb1
=
find_req
(
sk
,
rep
->
seq
);
if
(
skb1
==
NULL
)
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
if
(
&
sk
->
write_queue
==
sk
->
write_queue
.
next
)
{
sk
->
rto
=
0
;
ipx_delete_timer
(
sk
);
}
ipx
=
(
ipx_packet
*
)
skb1
->
h
.
raw
;
req
=
(
struct
ncp_request_sf
*
)(
ipx
+
1
);
switch
(
sk
->
state
)
{
case
TCP_CLOSE_WAIT
:
kfree_skb
(
skb
,
FREE_READ
);
sk
->
socket
->
data
=
NULL
;
sk
->
state
=
TCP_CLOSE
;
if
(
!
sk
->
dead
)
sk
->
state_change
(
sk
);
sk
->
dead
=
1
;
if
(
&
sk
->
write_queue
!=
sk
->
write_queue
.
next
)
ipx_delete_timer
(
sk
);
ipx_destroy_socket
(
sk
);
break
;
case
TCP_SYN_SENT
:
if
((
rep
->
f_stat
==
0
)
&&
(
rep
->
c_stat
==
0
))
{
sk
->
state
=
TCP_ESTABLISHED
;
sk
->
socket
->
state
=
SS_CONNECTED
;
sk
->
ncp
.
conn
=
rep
->
c_low
+
(
rep
->
c_high
*
0xff
);
if
(
!
sk
->
dead
)
sk
->
state_change
(
sk
);
}
else
{
sk
->
state
=
TCP_CLOSE
;
sk
->
socket
->
state
=
SS_UNCONNECTED
;
sk
->
err
=
ECONNREFUSED
;
if
(
&
sk
->
write_queue
!=
sk
->
write_queue
.
next
)
ipx_delete_timer
(
sk
);
if
(
!
sk
->
dead
)
sk
->
error_report
(
sk
);
}
kfree_skb
(
skb
,
FREE_READ
);
break
;
default:
if
((
req
->
func
==
0x15
)
&&
(
req
->
s_func
==
0x01
))
{
char
*
data
=
(
char
*
)(
rep
+
1
);
int
len
=
(
int
)
*
data
;
if
(
len
!=
0
)
{
memcpy
(
data
,
data
+
1
,
len
);
*
(
data
+
len
)
=
'\0'
;
printk
(
"
\007
%s
\n
"
,
data
);
}
kfree_skb
(
skb
,
FREE_READ
);
}
else
{
sk
->
rmem_alloc
+=
skb
->
mem_len
;
skb
->
sk
=
sk
;
skb_queue_tail
(
&
sk
->
receive_queue
,
skb
);
if
(
!
sk
->
dead
)
sk
->
data_ready
(
sk
,
skb
->
len
);
}
}
kfree_skb
(
skb1
,
FREE_WRITE
);
return
(
0
);
}
int
ipx_rcv
(
struct
sk_buff
*
skb
,
struct
device
*
dev
,
struct
packet_type
*
pt
)
{
/* NULL here for pt means the packet was looped back */
ipx_socket
*
sock
;
ipx_packet
*
ipx
;
ipx_route
*
rt
;
ipx_route
*
ln
;
unsigned
char
IPXaddr
[
6
];
ipx
=
(
ipx_packet
*
)
skb
->
h
.
raw
;
if
(
ipx
->
ipx_checksum
!=
IPX_NO_CHECKSUM
)
{
/* We don't do checksum options. We can't really. Novell don't seem to have documented them.
If you need them try the XNS checksum since IPX is basically XNS in disguise. It might be
the same... */
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
/* Too small */
if
(
htons
(
ipx
->
ipx_pktsize
)
<
sizeof
(
ipx_packet
))
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
/* Too many hops */
if
(
ipx
->
ipx_tctrl
>
16
)
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
/* Determine what local ipx endpoint this is */
ln
=
ipxrtr_get_local_net
(
dev
,
pt
->
type
);
if
(
ln
==
NULL
)
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
memset
(
IPXaddr
,
'\0'
,
6
);
memcpy
(
IPXaddr
+
(
6
-
dev
->
addr_len
),
dev
->
dev_addr
,
dev
->
addr_len
);
/* Not us/broadcast */
if
(
memcmp
(
IPXaddr
,
ipx
->
ipx_dest
.
node
,
6
)
!=
0
&&
memcmp
(
ipx_broadcast_node
,
ipx
->
ipx_dest
.
node
,
6
)
!=
0
)
{
/**********************************************************************************************
IPX router. Roughly as per the Novell spec. This doesn't handle netbios flood fill
broadcast frames. See the Novell IPX router specification for more details
(for ftp from ftp.novell.com)
***********************************************************************************************/
int
incoming_size
;
int
outgoing_size
;
struct
sk_buff
*
skb2
;
int
free_it
=
0
;
/* Rule: Don't forward packets that have exceeded the hop limit. This is fixed at 16 in IPX */
if
(
ipx
->
ipx_tctrl
==
16
)
{
kfree_skb
(
skb
,
FREE_READ
);
return
(
0
);
}
ipx
->
ipx_tctrl
++
;
/* Don't forward if we don't have a route. We ought to go off and start hunting out routes but
if someone needs this _THEY_ can add it */
rt
=
ipxrtr_get_dev
(
ipx
->
ipx_dest
.
net
);
if
(
rt
==
NULL
)
/* Unlike IP we can send on the interface we received. Eg doing DIX/802.3 conversion */
{
kfree_skb
(
skb
,
FREE_READ
);
...
...
@@ -943,6 +1583,9 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
return
(
0
);
}
if
(
sock
->
type
==
SOCK_NCP
)
return
(
ncp_rcv
(
sock
,
skb
));
sock
->
rmem_alloc
+=
skb
->
mem_len
;
skb
->
sk
=
sock
;
...
...
@@ -952,65 +1595,27 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
return
(
0
);
}
static
int
ipx_
sendto
(
struct
socket
*
sock
,
void
*
ubuf
,
int
len
,
int
noblock
,
unsigned
flags
,
struct
sockaddr
*
usip
,
int
addr_len
)
static
int
ipx_
do_sendto
(
ipx_socket
*
sk
,
ipx_address
*
ipx
,
void
*
ubuf
,
int
len
,
int
flag
,
unsigned
char
type
)
{
ipx_socket
*
sk
=
(
ipx_socket
*
)
sock
->
data
;
struct
sockaddr_ipx
*
usipx
=
(
struct
sockaddr_ipx
*
)
usip
;
struct
sockaddr_ipx
local_sipx
;
struct
sk_buff
*
skb
;
struct
device
*
dev
;
struct
ipx_packet
*
ipx
;
ipx_packet
*
ipx_pack
;
int
size
;
ipx_route
*
rt
;
struct
datalink_proto
*
dl
=
NULL
;
unsigned
char
IPXaddr
[
6
];
int
self_addressing
=
0
;
int
broadcast
=
0
;
if
(
flags
)
return
-
EINVAL
;
if
(
usipx
)
{
if
(
sk
->
ipx_source_addr
.
net
==
0
)
/* put the autobinding in */
{
struct
sockaddr_ipx
uaddr
;
int
ret
;
uaddr
.
sipx_port
=
0
;
uaddr
.
sipx_network
=
0L
;
ret
=
ipx_bind
(
sock
,
(
struct
sockaddr
*
)
&
uaddr
,
sizeof
(
struct
sockaddr_ipx
));
if
(
ret
!=
0
)
return
(
ret
);
}
if
(
addr_len
<
sizeof
(
*
usipx
))
return
(
-
EINVAL
);
if
(
usipx
->
sipx_family
!=
AF_IPX
)
return
-
EINVAL
;
if
(
htons
(
usipx
->
sipx_port
)
<
0x4000
&&
!
suser
())
return
-
EPERM
;
}
else
{
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
return
-
ENOTCONN
;
usipx
=&
local_sipx
;
usipx
->
sipx_family
=
AF_IPX
;
usipx
->
sipx_port
=
sk
->
ipx_dest_addr
.
sock
;
usipx
->
sipx_network
=
sk
->
ipx_dest_addr
.
net
;
memcpy
(
usipx
->
sipx_node
,
sk
->
ipx_dest_addr
.
node
,
sizeof
(
usipx
->
sipx_node
));
}
if
(
sk
->
debug
)
printk
(
"IPX: sendto: Addresses built.
\n
"
);
if
(
memcmp
(
&
usipx
->
sipx_node
,
&
ipx_broadcast_node
,
6
)
==
0
)
if
((
sk
->
type
==
SOCK_NCP
)
&&
(
len
<
sizeof
(
struct
ncp_request
)))
return
-
EINVAL
;
if
(
memcmp
(
&
ipx
->
node
,
&
ipx_broadcast_node
,
6
)
==
0
)
{
if
(
!
sk
->
broadcast
)
return
-
ENETUNREACH
;
broadcast
=
1
;
}
/* Build a packet */
...
...
@@ -1021,12 +1626,12 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
size
=
sizeof
(
ipx_packet
)
+
len
;
/* For mac headers */
/* Find out where this has to go */
if
(
usipx
->
sipx_network
==
0L
)
{
if
(
ipx
->
net
==
0L
)
{
rt
=
ipxrtr_get_default_net
();
if
(
rt
!=
NULL
)
usipx
->
sipx_network
=
rt
->
net
;
ipx
->
net
=
rt
->
net
;
}
else
rt
=
ipxrtr_get_dev
(
usipx
->
sipx_network
);
rt
=
ipxrtr_get_dev
(
ipx
->
net
);
if
(
rt
==
NULL
)
{
...
...
@@ -1046,87 +1651,118 @@ static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock,
return
-
EAGAIN
;
}
if
(
flag
)
skb
=
alloc_skb
(
size
,
GFP_KERNEL
);
else
skb
=
alloc_skb
(
size
,
GFP_ATOMIC
);
if
(
skb
==
NULL
)
return
-
ENOMEM
;
skb
->
mem_addr
=
skb
;
skb
->
sk
=
sk
;
skb
->
free
=
1
;
skb
->
arp
=
1
;
sk
->
wmem_alloc
+=
skb
->
mem_len
;
skb
->
len
=
size
;
sk
->
wmem_alloc
+=
skb
->
mem_len
;
ipx_build_header
(
ipx
,
skb
,
sk
,
len
,
type
)
;
if
(
sk
->
debug
)
printk
(
"Building MAC header.
\n
"
);
skb
->
dev
=
rt
->
dev
;
ipx_pack
=
(
ipx_packet
*
)(
skb
->
h
.
raw
);
/* Build Data Link header */
dl
->
datalink_header
(
dl
,
skb
,
(
rt
->
flags
&
IPX_RT_ROUTED
)
?
rt
->
router_node
:
usipx
->
sipx_node
);
/* User data follows immediately after the IPX data */
if
(
flag
)
memcpy_fromfs
((
char
*
)(
ipx_pack
+
1
),
ubuf
,
len
);
else
memcpy
((
char
*
)(
ipx_pack
+
1
),
ubuf
,
len
);
/* See if we are sending to ourself */
memset
(
IPXaddr
,
'\0'
,
6
);
memcpy
(
IPXaddr
+
(
6
-
skb
->
dev
->
addr_len
),
skb
->
dev
->
dev_addr
,
skb
->
dev
->
addr_len
);
if
(
sk
->
type
==
SOCK_NCP
)
{
struct
ncp_request
*
req
=
(
struct
ncp_request
*
)(
ipx_pack
+
1
);
self_addressing
=
!
memcmp
(
IPXaddr
,
(
rt
->
flags
&
IPX_RT_ROUTED
)
?
rt
->
router_node
:
usipx
->
sipx_node
,
6
);
switch
(
sk
->
state
)
{
case
TCP_SYN_SENT
:
req
->
p_type
=
NCP_OPEN
;
break
;
case
TCP_CLOSE_WAIT
:
req
->
p_type
=
NCP_CLOSE
;
break
;
default:
req
->
p_type
=
NCP_REQUEST
;
}
req
->
c_low
=
(
sk
->
ncp
.
conn
)
&
0xff
;
req
->
c_high
=
(
sk
->
ncp
.
conn
>>
8
)
&
0xff
;
req
->
seq
=
(
sk
->
ncp
.
seq
)
++
;
req
->
task
=
1
;
skb
->
free
=
0
;
if
(
&
sk
->
write_queue
==
sk
->
write_queue
.
next
)
ipx_add_timer
(
sk
,
NCP_TIMEOUT
);
else
ipx_reset_timer
(
sk
,
NCP_TIMEOUT
);
skb_queue_tail
(
&
sk
->
write_queue
,
skb
);
}
/* Now the IPX */
if
(
sk
->
debug
)
printk
(
"Building IPX Header.
\n
"
);
ipx
=
(
ipx_packet
*
)
skb
->
h
.
raw
;
ipx
->
ipx_checksum
=
0xFFFF
;
ipx
->
ipx_pktsize
=
htons
(
len
+
sizeof
(
ipx_packet
));
ipx
->
ipx_tctrl
=
0
;
ipx
->
ipx_type
=
usipx
->
sipx_type
;
memcpy
(
&
ipx
->
ipx_source
,
&
sk
->
ipx_source_addr
,
sizeof
(
ipx
->
ipx_source
));
ipx
->
ipx_dest
.
net
=
usipx
->
sipx_network
;
memcpy
(
ipx
->
ipx_dest
.
node
,
usipx
->
sipx_node
,
sizeof
(
ipx
->
ipx_dest
.
node
));
ipx
->
ipx_dest
.
sock
=
usipx
->
sipx_port
;
if
(
sk
->
debug
)
printk
(
"IPX: Appending user data.
\n
"
);
/* User data follows immediately after the IPX data */
memcpy_fromfs
((
char
*
)(
ipx
+
1
),
ubuf
,
len
);
if
(
sk
->
debug
)
printk
(
"IPX: Transmitting buffer
\n
"
);
if
((
dev
->
flags
&
IFF_LOOPBACK
)
||
self_addressing
)
{
struct
packet_type
pt
;
/* loop back */
pt
.
type
=
rt
->
dlink_type
;
sk
->
wmem_alloc
-=
skb
->
mem_len
;
skb
->
sk
=
NULL
;
ipx_rcv
(
skb
,
dev
,
&
pt
);
}
else
{
if
(
broadcast
)
{
struct
packet_type
pt
;
struct
sk_buff
*
skb2
;
ipx_xmit
(
skb
);
/* loop back */
pt
.
type
=
rt
->
dlink_type
;
return
len
;
}
skb2
=
alloc_skb
(
skb
->
len
,
GFP_ATOMIC
);
skb2
->
mem_addr
=
skb2
;
skb2
->
free
=
1
;
skb2
->
arp
=
1
;
skb2
->
len
=
skb
->
len
;
skb2
->
sk
=
NULL
;
skb2
->
h
.
raw
=
skb2
->
data
+
rt
->
datalink
->
header_length
+
dev
->
hard_header_len
;
memcpy
(
skb2
->
data
,
skb
->
data
,
skb
->
len
);
ipx_rcv
(
skb2
,
dev
,
&
pt
);
static
int
ipx_sendto
(
struct
socket
*
sock
,
void
*
ubuf
,
int
len
,
int
noblock
,
unsigned
flags
,
struct
sockaddr
*
usip
,
int
addr_len
)
{
ipx_socket
*
sk
=
(
ipx_socket
*
)
sock
->
data
;
ipx_address
ipx
;
struct
sockaddr_ipx
*
usipx
=
(
struct
sockaddr_ipx
*
)
usip
;
struct
sockaddr_ipx
local_sipx
;
if
(
flags
)
return
-
EINVAL
;
if
(
usipx
)
{
if
(
sk
->
type
==
SOCK_NCP
)
return
-
EINVAL
;
if
(
sk
->
ipx_source_addr
.
sock
==
0
)
/* put the autobinding in */
{
int
ret
;
local_sipx
.
sipx_type
=
0
;
local_sipx
.
sipx_port
=
0
;
local_sipx
.
sipx_network
=
0L
;
ret
=
ipx_bind
(
sock
,
(
struct
sockaddr
*
)
&
local_sipx
,
sizeof
(
struct
sockaddr_ipx
));
if
(
ret
!=
0
)
return
(
ret
);
}
dev_queue_xmit
(
skb
,
dev
,
SOPRI_NORMAL
);
if
(
addr_len
<
sizeof
(
*
usipx
))
return
(
-
EINVAL
);
if
(
usipx
->
sipx_family
!=
AF_IPX
)
return
-
EINVAL
;
if
(
htons
(
usipx
->
sipx_port
)
<
0x4000
&&
!
suser
())
return
-
EPERM
;
ipx
.
net
=
usipx
->
sipx_network
;
ipx
.
sock
=
usipx
->
sipx_port
;
memcpy
(
ipx
.
node
,
usipx
->
sipx_node
,
sizeof
(
ipx
.
node
));
return
(
ipx_do_sendto
(
sk
,
&
ipx
,
ubuf
,
len
,
1
,
usipx
->
sipx_type
));
}
else
{
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
return
-
ENOTCONN
;
return
(
ipx_do_sendto
(
sk
,
&
(
sk
->
ipx_dest_addr
),
ubuf
,
len
,
1
,
sk
->
ipx_type
));
}
return
len
;
}
static
int
ipx_send
(
struct
socket
*
sock
,
void
*
ubuf
,
int
size
,
int
noblock
,
unsigned
flags
)
{
return
ipx_sendto
(
sock
,
ubuf
,
size
,
noblock
,
flags
,
NULL
,
0
);
...
...
@@ -1170,12 +1806,14 @@ static int ipx_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
sipx
->
sipx_type
=
ipx
->
ipx_type
;
}
skb_free_datagram
(
skb
);
return
(
copied
);
}
static
int
ipx_write
(
struct
socket
*
sock
,
char
*
ubuf
,
int
size
,
int
noblock
)
{
return
ipx_send
(
sock
,
ubuf
,
size
,
noblock
,
0
);
}
...
...
net/inet/ncp.h
0 → 100644
View file @
74beaae0
/*
*
* Kernel support for NCP
*
* Mark Evans 1994
*
*/
#ifndef _NCP_H
#define _NCP_H
#include <linux/ncp.h>
struct
ncp_info
{
unsigned
short
conn
;
/* connection number */
unsigned
char
seq
;
/* sequence number */
ipx_socket
*
ncp
;
/* ncp socket */
ipx_socket
*
watchdog
;
/* watchdog socket */
ipx_socket
*
mail
;
/* mail socket */
};
#define NCP_TIMEOUT (3*HZ)
#define MAX_TIMEOUT 15
#endif
/* _NCP_H */
net/inet/sock.h
View file @
74beaae0
...
...
@@ -41,6 +41,7 @@
#endif
#ifdef CONFIG_IPX
#include "ipx.h"
#include "ncp.h"
#endif
#define SOCK_ARRAY_SIZE 64
...
...
@@ -137,6 +138,7 @@ struct sock {
#ifdef CONFIG_IPX
ipx_address
ipx_source_addr
,
ipx_dest_addr
;
unsigned
short
ipx_type
;
struct
ncp_info
ncp
;
#endif
#ifdef CONFIG_AX25
/* Really we want to add a per protocol private area */
...
...
net/socket.c
View file @
74beaae0
...
...
@@ -592,7 +592,8 @@ static int sock_socket(int family, int type, int protocol)
if
((
type
!=
SOCK_STREAM
&&
type
!=
SOCK_DGRAM
&&
type
!=
SOCK_SEQPACKET
&&
type
!=
SOCK_RAW
&&
type
!=
SOCK_PACKET
)
||
protocol
<
0
)
type
!=
SOCK_PACKET
&&
type
!=
SOCK_NCP
)
||
protocol
<
0
)
return
(
-
EINVAL
);
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment