Subversion Repositories Kolibri OS

Rev

Rev 4423 | Rev 5565 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4423 Rev 5201
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
5
;;                                                                 ;;
6
;;  IPv4.INC                                                       ;;
6
;;  IPv4.INC                                                       ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
8
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
9
;;                                                                 ;;
9
;;                                                                 ;;
10
;;  Based on the work of [Johnny_B] and [smb]                      ;;
10
;;  Based on the work of [Johnny_B] and [smb]                      ;;
11
;;                                                                 ;;
11
;;                                                                 ;;
12
;;    Written by hidnplayr@kolibrios.org                           ;;
12
;;    Written by hidnplayr@kolibrios.org                           ;;
13
;;                                                                 ;;
13
;;                                                                 ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
15
;;             Version 2, June 1991                                ;;
15
;;             Version 2, June 1991                                ;;
16
;;                                                                 ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18
 
18
 
19
$Revision: 3515 $
19
$Revision: 3515 $
20
 
20
 
21
IPv4_MAX_FRAGMENTS              = 64
21
IPv4_MAX_FRAGMENTS              = 64
22
IPv4_MAX_ROUTES                 = 64
22
IPv4_MAX_ROUTES                 = 64
23
 
23
 
24
IPv4_ROUTE_FLAG_UP              = 1 shl 0
24
IPv4_ROUTE_FLAG_UP              = 1 shl 0
25
IPv4_ROUTE_FLAG_GATEWAY         = 1 shl 1
25
IPv4_ROUTE_FLAG_GATEWAY         = 1 shl 1
26
IPv4_ROUTE_FLAG_HOST            = 1 shl 2
26
IPv4_ROUTE_FLAG_HOST            = 1 shl 2
27
IPv4_ROUTE_FLAG_D               = 1 shl 3       ; Route was created by a redirect
27
IPv4_ROUTE_FLAG_D               = 1 shl 3       ; Route was created by a redirect
28
IPv4_ROUTE_FLAG_M               = 1 shl 4       ; Route was modified by a redirect
28
IPv4_ROUTE_FLAG_M               = 1 shl 4       ; Route was modified by a redirect
29
 
29
 
30
struct  IPv4_header
30
struct  IPv4_header
31
 
31
 
32
        VersionAndIHL           db ?    ; Version[0-3 bits] and IHL(header length)[4-7 bits]
32
        VersionAndIHL           db ?    ; Version[0-3 bits] and IHL(header length)[4-7 bits]
33
        TypeOfService           db ?    ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
33
        TypeOfService           db ?    ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
34
        TotalLength             dw ?
34
        TotalLength             dw ?
35
        Identification          dw ?
35
        Identification          dw ?
36
        FlagsAndFragmentOffset  dw ?    ; Flags[0-2] and FragmentOffset[3-15]
36
        FlagsAndFragmentOffset  dw ?    ; Flags[0-2] and FragmentOffset[3-15]
37
        TimeToLive              db ?    ;
37
        TimeToLive              db ?    ;
38
        Protocol                db ?
38
        Protocol                db ?
39
        HeaderChecksum          dw ?
39
        HeaderChecksum          dw ?
40
        SourceAddress           dd ?
40
        SourceAddress           dd ?
41
        DestinationAddress      dd ?
41
        DestinationAddress      dd ?
42
 
42
 
43
ends
43
ends
44
 
44
 
45
struct  IPv4_FRAGMENT_slot
45
struct  IPv4_FRAGMENT_slot
46
 
46
 
47
        ttl                     dw ?    ; Time to live for this entry, 0 for empty slot's
47
        ttl                     dw ?    ; Time to live for this entry, 0 for empty slot's
48
        id                      dw ?    ; Identification field from IP header
48
        id                      dw ?    ; Identification field from IP header
49
        SrcIP                   dd ?    ; .. from IP header
49
        SrcIP                   dd ?    ; .. from IP header
50
        DstIP                   dd ?    ; .. from IP header
50
        DstIP                   dd ?    ; .. from IP header
51
        ptr                     dd ?    ; Pointer to first packet
51
        ptr                     dd ?    ; Pointer to first packet
52
 
52
 
53
ends
53
ends
54
 
54
 
55
struct  IPv4_FRAGMENT_entry             ; This structure will replace the ethernet header in fragmented ip packets
55
struct  IPv4_FRAGMENT_entry             ; This structure will replace the ethernet header in fragmented ip packets
56
 
56
 
57
        PrevPtr                 dd ?    ; Pointer to previous fragment entry  (-1 for first packet)
57
        PrevPtr                 dd ?    ; Pointer to previous fragment entry  (-1 for first packet)
58
        NextPtr                 dd ?    ; Pointer to next fragment entry (-1 for last packet)
58
        NextPtr                 dd ?    ; Pointer to next fragment entry (-1 for last packet)
59
        Owner                   dd ?    ; Pointer to structure of driver
59
        Owner                   dd ?    ; Pointer to structure of driver
60
                                rb 2    ; to match ethernet header size         ;;; FIXME
60
                                rb 2    ; to match ethernet header size         ;;; FIXME
61
                                        ; Ip header begins here (we will need the IP header to re-construct the complete packet)
61
                                        ; Ip header begins here (we will need the IP header to re-construct the complete packet)
62
ends
62
ends
63
 
63
 
64
struct  IPv4_ROUTE
64
struct  IPv4_ROUTE
65
 
65
 
66
        Destination             dd ?
66
        Destination             dd ?
67
        Gateway                 dd ?
67
        Gateway                 dd ?
68
        Flags                   dd ?
68
        Flags                   dd ?
69
        Use                     dd ?
69
        Use                     dd ?
70
        Interface               dd ?
70
        Interface               dd ?
71
 
71
 
72
ends
72
ends
73
 
73
 
74
 
74
 
75
uglobal
75
uglobal
76
align 4
76
align 4
77
 
77
 
78
        IP_LIST                 rd NET_DEVICES_MAX
78
        IP_LIST                 rd NET_DEVICES_MAX
79
        SUBNET_LIST             rd NET_DEVICES_MAX
79
        SUBNET_LIST             rd NET_DEVICES_MAX
80
        DNS_LIST                rd NET_DEVICES_MAX
80
        DNS_LIST                rd NET_DEVICES_MAX
81
        GATEWAY_LIST            rd NET_DEVICES_MAX
81
        GATEWAY_LIST            rd NET_DEVICES_MAX
82
        BROADCAST_LIST          rd NET_DEVICES_MAX
82
        BROADCAST_LIST          rd NET_DEVICES_MAX
83
 
83
 
84
        IPv4_packets_tx         rd NET_DEVICES_MAX
84
        IPv4_packets_tx         rd NET_DEVICES_MAX
85
        IPv4_packets_rx         rd NET_DEVICES_MAX
85
        IPv4_packets_rx         rd NET_DEVICES_MAX
86
        IPv4_packets_dumped     rd NET_DEVICES_MAX
86
        IPv4_packets_dumped     rd NET_DEVICES_MAX
87
 
87
 
88
        IPv4_FRAGMENT_LIST      rb IPv4_MAX_FRAGMENTS * sizeof.IPv4_FRAGMENT_slot
88
        IPv4_FRAGMENT_LIST      rb IPv4_MAX_FRAGMENTS * sizeof.IPv4_FRAGMENT_slot
89
 
89
 
90
        IPv4_ROUTES             rd IPv4_MAX_ROUTES * sizeof.IPv4_ROUTE
90
        IPv4_ROUTES             rd IPv4_MAX_ROUTES * sizeof.IPv4_ROUTE
91
 
91
 
92
endg
92
endg
93
 
93
 
94
 
94
 
95
;-----------------------------------------------------------------
95
;-----------------------------------------------------------------
96
;
96
;
97
; IPv4_init
97
; IPv4_init
98
;
98
;
99
;  This function resets all IP variables
99
;  This function resets all IP variables
100
;
100
;
101
;-----------------------------------------------------------------
101
;-----------------------------------------------------------------
102
macro   IPv4_init {
102
macro   IPv4_init {
103
 
103
 
104
        xor     eax, eax
104
        xor     eax, eax
105
        mov     edi, IP_LIST
105
        mov     edi, IP_LIST
106
        mov     ecx, 7*NET_DEVICES_MAX + (sizeof.IPv4_FRAGMENT_slot*IPv4_MAX_FRAGMENTS)/4
106
        mov     ecx, 7*NET_DEVICES_MAX + (sizeof.IPv4_FRAGMENT_slot*IPv4_MAX_FRAGMENTS)/4
107
        rep stosd
107
        rep stosd
108
 
108
 
109
}
109
}
110
 
110
 
111
 
111
 
112
;-----------------------------------------------------------------
112
;-----------------------------------------------------------------
113
;
113
;
114
; Decrease TimeToLive of all fragment slots
114
; Decrease TimeToLive of all fragment slots
115
;
115
;
116
;-----------------------------------------------------------------
116
;-----------------------------------------------------------------
117
macro IPv4_decrease_fragment_ttls {
117
macro IPv4_decrease_fragment_ttls {
118
 
118
 
119
local   .loop, .next
119
local   .loop, .next
120
 
120
 
121
        mov     esi, IPv4_FRAGMENT_LIST
121
        mov     esi, IPv4_FRAGMENT_LIST
122
        mov     ecx, IPv4_MAX_FRAGMENTS
122
        mov     ecx, IPv4_MAX_FRAGMENTS
123
  .loop:
123
  .loop:
124
        cmp     [esi + IPv4_FRAGMENT_slot.ttl], 0
124
        cmp     [esi + IPv4_FRAGMENT_slot.ttl], 0
125
        je      .next
125
        je      .next
126
        dec     [esi + IPv4_FRAGMENT_slot.ttl]
126
        dec     [esi + IPv4_FRAGMENT_slot.ttl]
127
        jz      .died
127
        jz      .died
128
  .next:
128
  .next:
129
        add     esi, sizeof.IPv4_FRAGMENT_slot
129
        add     esi, sizeof.IPv4_FRAGMENT_slot
130
        dec     ecx
130
        dec     ecx
131
        jnz     .loop
131
        jnz     .loop
132
        jmp     .done
132
        jmp     .done
133
 
133
 
134
  .died:
134
  .died:
135
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4 Fragment slot timed-out!\n"
135
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4 Fragment slot timed-out!\n"
136
;;; TODO: clear all entry's of timed-out slot
136
;;; TODO: clear all entry's of timed-out slot
137
        jmp     .next
137
        jmp     .next
138
 
138
 
139
  .done:
139
  .done:
140
}
140
}
141
 
141
 
142
 
142
 
143
 
143
 
144
macro IPv4_checksum ptr {
144
macro IPv4_checksum ptr {
145
 
145
 
146
; This is the fast procedure to create or check an IP header without options
146
; This is the fast procedure to create or check an IP header without options
147
; To create a new checksum, the checksum field must be set to 0 before computation
147
; To create a new checksum, the checksum field must be set to 0 before computation
148
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
148
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
149
 
149
 
150
        push    ebx
150
        push    ebx
151
        xor     ebx, ebx
151
        xor     ebx, ebx
152
        add     bl, [ptr+1]
152
        add     bl, [ptr+1]
153
        adc     bh, [ptr+0]
153
        adc     bh, [ptr+0]
154
 
154
 
155
        adc     bl, [ptr+3]
155
        adc     bl, [ptr+3]
156
        adc     bh, [ptr+2]
156
        adc     bh, [ptr+2]
157
 
157
 
158
        adc     bl, [ptr+5]
158
        adc     bl, [ptr+5]
159
        adc     bh, [ptr+4]
159
        adc     bh, [ptr+4]
160
 
160
 
161
        adc     bl, [ptr+7]
161
        adc     bl, [ptr+7]
162
        adc     bh, [ptr+6]
162
        adc     bh, [ptr+6]
163
 
163
 
164
        adc     bl, [ptr+9]
164
        adc     bl, [ptr+9]
165
        adc     bh, [ptr+8]
165
        adc     bh, [ptr+8]
166
 
166
 
167
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
167
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
168
 
168
 
169
        adc     bl, [ptr+13]
169
        adc     bl, [ptr+13]
170
        adc     bh, [ptr+12]
170
        adc     bh, [ptr+12]
171
 
171
 
172
        adc     bl, [ptr+15]
172
        adc     bl, [ptr+15]
173
        adc     bh, [ptr+14]
173
        adc     bh, [ptr+14]
174
 
174
 
175
        adc     bl, [ptr+17]
175
        adc     bl, [ptr+17]
176
        adc     bh, [ptr+16]
176
        adc     bh, [ptr+16]
177
 
177
 
178
        adc     bl, [ptr+19]
178
        adc     bl, [ptr+19]
179
        adc     bh, [ptr+18]
179
        adc     bh, [ptr+18]
180
 
180
 
181
        adc     ebx, 0
181
        adc     ebx, 0
182
 
182
 
183
        push    ecx
183
        push    ecx
184
        mov     ecx, ebx
184
        mov     ecx, ebx
185
        shr     ecx, 16
185
        shr     ecx, 16
186
        and     ebx, 0xffff
186
        and     ebx, 0xffff
187
        add     ebx, ecx
187
        add     ebx, ecx
188
 
188
 
189
        mov     ecx, ebx
189
        mov     ecx, ebx
190
        shr     ecx, 16
190
        shr     ecx, 16
191
        add     ebx, ecx
191
        add     ebx, ecx
192
 
192
 
193
        not     bx
193
        not     bx
194
        jnz     .not_zero
194
        jnz     .not_zero
195
        dec     bx
195
        dec     bx
196
  .not_zero:
196
  .not_zero:
197
        xchg    bl, bh
197
        xchg    bl, bh
198
        pop     ecx
198
        pop     ecx
199
 
199
 
200
        neg     word [ptr+10]           ; zero will stay zero so we just get the checksum
200
        neg     word [ptr+10]           ; zero will stay zero so we just get the checksum
201
        add     word [ptr+10], bx       ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
201
        add     word [ptr+10], bx       ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
202
        pop     ebx
202
        pop     ebx
203
 
203
 
204
}
204
}
205
 
205
 
206
 
206
 
207
 
207
 
208
;-----------------------------------------------------------------
208
;-----------------------------------------------------------------
209
;
209
;
210
; IPv4_input:
210
; IPv4_input:
211
;
211
;
212
;  Will check if IPv4 Packet isnt damaged
212
;  Will check if IPv4 Packet isnt damaged
213
;  and call appropriate handler. (TCP/UDP/ICMP/..)
213
;  and call appropriate handler. (TCP/UDP/ICMP/..)
214
;
214
;
215
;  It will also re-construct fragmented packets
215
;  It will also re-construct fragmented packets
216
;
216
;
217
;  IN:  Pointer to buffer in [esp]
217
;  IN:  Pointer to buffer in [esp]
218
;       size of buffer in [esp+4]
218
;       size of buffer in [esp+4]
219
;       pointer to device struct in ebx
219
;       pointer to device struct in ebx
220
;       pointer to IPv4 header in edx
220
;       pointer to IPv4 header in edx
221
;       size of IPv4 packet in ecx
221
;       size of IPv4 packet in ecx
222
;  OUT: /
222
;  OUT: /
223
;
223
;
224
;-----------------------------------------------------------------
224
;-----------------------------------------------------------------
225
align 4
225
align 4
226
IPv4_input:                                                     ; TODO: add IPv4 raw sockets support
226
IPv4_input:                                                     ; TODO: add IPv4 raw sockets support
227
 
227
 
228
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input, packet from: %u.%u.%u.%u ",\
228
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input, packet from: %u.%u.%u.%u ",\
229
        [edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
229
        [edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
230
        [edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
230
        [edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
231
        DEBUGF  DEBUG_NETWORK_VERBOSE, "to: %u.%u.%u.%u\n",\
231
        DEBUGF  DEBUG_NETWORK_VERBOSE, "to: %u.%u.%u.%u\n",\
232
        [edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
232
        [edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
233
        [edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
233
        [edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
234
 
234
 
235
;-------------------------------
235
;-------------------------------
236
; re-calculate the checksum
236
; re-calculate the checksum
237
 
237
 
238
        IPv4_checksum edx
238
        IPv4_checksum edx
239
        jnz     .dump                                           ; if checksum isn't valid then dump packet
239
        jnz     .dump                                           ; if checksum isn't valid then dump packet
240
 
240
 
241
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n"
241
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n"
242
 
242
 
243
;-----------------------------------
243
;-----------------------------------
244
; Check if destination IP is correct
244
; Check if destination IP is correct
245
 
245
 
246
        call    NET_ptr_to_num4
246
        call    NET_ptr_to_num4
247
 
247
 
248
        ; check if it matches local ip (Using RFC1122 strong end system model)
248
        ; check if it matches local ip (Using RFC1122 strong end system model)
249
 
249
 
250
        mov     eax, [edx + IPv4_header.DestinationAddress]
250
        mov     eax, [edx + IPv4_header.DestinationAddress]
251
        cmp     eax, [IP_LIST + edi]
251
        cmp     eax, [IP_LIST + edi]
252
        je      .ip_ok
252
        je      .ip_ok
253
 
253
 
254
        ; check for broadcast (IP or (not SUBNET))
254
        ; check for broadcast (IP or (not SUBNET))
255
 
255
 
256
        cmp     eax, [BROADCAST_LIST + edi]
256
        cmp     eax, [BROADCAST_LIST + edi]
257
        je      .ip_ok
257
        je      .ip_ok
258
 
258
 
259
        ; or a special broadcast (255.255.255.255)
259
        ; or a special broadcast (255.255.255.255)
260
 
260
 
261
        cmp     eax, 0xffffffff
261
        cmp     eax, 0xffffffff
262
        je      .ip_ok
262
        je      .ip_ok
263
 
263
 
264
        ; maybe it's a multicast (224.0.0.0/4)
264
        ; maybe it's a multicast (224.0.0.0/4)
265
 
265
 
266
        and     eax, 0x0fffffff
266
        and     eax, 0x0fffffff
267
        cmp     eax, 224
267
        cmp     eax, 224
268
        je      .ip_ok
268
        je      .ip_ok
269
 
269
 
270
        ; or a loopback address (127.0.0.0/8)
-
 
271
 
270
        ; maybe we just dont have an IP yet and should accept everything on the IP level
272
        and     eax, 0x00ffffff
271
 
273
        cmp     eax, 127
272
        cmp     [IP_LIST + edi], 0
274
        je      .ip_ok
273
        je      .ip_ok
275
 
274
 
276
        ; or it's just not meant for us.. :(
275
        ; or it's just not meant for us.. :(
277
 
276
 
278
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Destination address does not match!\n"
277
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Destination address does not match!\n"
279
        jmp     .dump
278
        jmp     .dump
280
 
279
 
281
;------------------------
280
;------------------------
282
; Now we can update stats
281
; Now we can update stats
283
 
282
 
284
  .ip_ok:
283
  .ip_ok:
285
        inc     [IPv4_packets_rx + edi]
284
        inc     [IPv4_packets_rx + edi]
286
 
285
 
287
;----------------------------------
286
;----------------------------------
288
; Check if the packet is fragmented
287
; Check if the packet is fragmented
289
 
288
 
290
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 1 shl 5     ; Is 'more fragments' flag set ?
289
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 1 shl 5     ; Is 'more fragments' flag set ?
291
        jnz     .has_fragments                                          ; If so, we definately have a fragmented packet
290
        jnz     .has_fragments                                          ; If so, we definately have a fragmented packet
292
 
291
 
293
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 0xff1f      ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
292
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 0xff1f      ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
294
        jnz     .is_last_fragment
293
        jnz     .is_last_fragment
295
 
294
 
296
;-------------------------------------------------------------------
295
;-------------------------------------------------------------------
297
; No, it's just a regular IP packet, pass it to the higher protocols
296
; No, it's just a regular IP packet, pass it to the higher protocols
298
 
297
 
299
  .handle_it:                                                   ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
298
  .handle_it:                                                   ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
300
 
299
 
301
        movzx   esi, [edx + IPv4_header.VersionAndIHL]          ; Calculate Header length by using IHL field
300
        movzx   esi, [edx + IPv4_header.VersionAndIHL]          ; Calculate Header length by using IHL field
302
        and     esi, 0x0000000f                                 ;
301
        and     esi, 0x0000000f                                 ;
303
        shl     esi, 2                                          ;
302
        shl     esi, 2                                          ;
304
 
303
 
305
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
304
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
306
        xchg    cl, ch                                          ;
305
        xchg    cl, ch                                          ;
307
        sub     ecx, esi                                        ;
306
        sub     ecx, esi                                        ;
308
 
307
 
309
        lea     edi, [edx + IPv4_header.SourceAddress]          ; make edi ptr to source and dest IPv4 address
308
        lea     edi, [edx + IPv4_header.SourceAddress]          ; make edi ptr to source and dest IPv4 address
310
        mov     al, [edx + IPv4_header.Protocol]
309
        mov     al, [edx + IPv4_header.Protocol]
311
        add     esi, edx                                        ; make esi ptr to data
310
        add     esi, edx                                        ; make esi ptr to data
312
 
311
 
313
        cmp     al, IP_PROTO_TCP
312
        cmp     al, IP_PROTO_TCP
314
        je      TCP_input
313
        je      TCP_input
315
 
314
 
316
        cmp     al, IP_PROTO_UDP
315
        cmp     al, IP_PROTO_UDP
317
        je      UDP_input
316
        je      UDP_input
318
 
317
 
319
        cmp     al, IP_PROTO_ICMP
318
        cmp     al, IP_PROTO_ICMP
320
        je      ICMP_input
319
        je      ICMP_input
321
 
320
 
322
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
321
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
323
 
322
 
324
  .dump:
323
  .dump:
325
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
324
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
326
        inc     [IPv4_packets_dumped]                           ; FIXME: use correct interface
325
        inc     [IPv4_packets_dumped]                           ; FIXME: use correct interface
327
        call    NET_packet_free
326
        call    NET_packet_free
328
        add     esp, 4                                          ; pop (balance stack)
327
        add     esp, 4                                          ; pop (balance stack)
329
        ret
328
        ret
330
 
329
 
331
 
330
 
332
;---------------------------
331
;---------------------------
333
; Fragmented packet handler
332
; Fragmented packet handler
334
 
333
 
335
 
334
 
336
  .has_fragments:
335
  .has_fragments:
337
        movzx   eax, [edx + IPv4_header.FlagsAndFragmentOffset]
336
        movzx   eax, [edx + IPv4_header.FlagsAndFragmentOffset]
338
        xchg    al, ah
337
        xchg    al, ah
339
        shl     ax, 3
338
        shl     ax, 3
340
 
339
 
341
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x ptr=0x%x\n", ax, [edx + IPv4_header.Identification]:4, edx
340
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x ptr=0x%x\n", ax, [edx + IPv4_header.Identification]:4, edx
342
 
341
 
343
        test    ax, ax                                          ; Is this the first packet of the fragment?
342
        test    ax, ax                                          ; Is this the first packet of the fragment?
344
        jz      .is_first_fragment
343
        jz      .is_first_fragment
345
 
344
 
346
 
345
 
347
;-------------------------------------------------------
346
;-------------------------------------------------------
348
; We have a fragmented IP packet, but it's not the first
347
; We have a fragmented IP packet, but it's not the first
349
 
348
 
350
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Middle fragment packet received!\n"
349
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Middle fragment packet received!\n"
351
 
350
 
352
        call    IPv4_find_fragment_slot
351
        call    IPv4_find_fragment_slot
353
        cmp     esi, -1
352
        cmp     esi, -1
354
        je      .dump
353
        je      .dump
355
 
354
 
356
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; Reset the ttl
355
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; Reset the ttl
357
        mov     esi, [esi + IPv4_FRAGMENT_slot.ptr]
356
        mov     esi, [esi + IPv4_FRAGMENT_slot.ptr]
358
        or      edi, -1
357
        or      edi, -1
359
  .find_last_entry:                                             ; The following routine will try to find the last entry
358
  .find_last_entry:                                             ; The following routine will try to find the last entry
360
        cmp     edi, [esi + IPv4_FRAGMENT_entry.PrevPtr]
359
        cmp     edi, [esi + IPv4_FRAGMENT_entry.PrevPtr]
361
        jne     .destroy_slot                                   ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
360
        jne     .destroy_slot                                   ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
362
        mov     edi, esi
361
        mov     edi, esi
363
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
362
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
364
        cmp     esi, -1
363
        cmp     esi, -1
365
        jne     .find_last_entry
364
        jne     .find_last_entry
366
                                                                ; We found the last entry (pointer is now in edi)
365
                                                                ; We found the last entry (pointer is now in edi)
367
                                                                ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
366
                                                                ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
368
 
367
 
369
        pop     eax                                             ; pointer to packet
368
        pop     eax                                             ; pointer to packet
370
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], eax        ; update pointer of previous entry to the new entry
369
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], eax        ; update pointer of previous entry to the new entry
371
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
370
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
372
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], edi
371
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], edi
373
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
372
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
374
 
373
 
375
        add     esp, 4
374
        add     esp, 4
376
        ret
375
        ret
377
 
376
 
378
 
377
 
379
;------------------------------------
378
;------------------------------------
380
; We have received the first fragment
379
; We have received the first fragment
381
 
380
 
382
  .is_first_fragment:
381
  .is_first_fragment:
383
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n"
382
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n"
384
                                                                ; try to locate a free slot..
383
                                                                ; try to locate a free slot..
385
        mov     ecx, IPv4_MAX_FRAGMENTS
384
        mov     ecx, IPv4_MAX_FRAGMENTS
386
        mov     esi, IPv4_FRAGMENT_LIST
385
        mov     esi, IPv4_FRAGMENT_LIST
387
  .find_free_slot:
386
  .find_free_slot:
388
        cmp     word [esi + IPv4_FRAGMENT_slot.ttl], 0
387
        cmp     word [esi + IPv4_FRAGMENT_slot.ttl], 0
389
        je      .found_free_slot
388
        je      .found_free_slot
390
        add     esi, sizeof.IPv4_FRAGMENT_slot
389
        add     esi, sizeof.IPv4_FRAGMENT_slot
391
        loop    .find_free_slot
390
        loop    .find_free_slot
392
        jmp     .dump                                           ; If no free slot was found, dump the packet
391
        jmp     .dump                                           ; If no free slot was found, dump the packet
393
 
392
 
394
  .found_free_slot:                                             ; We found a free slot, let's fill in the FRAGMENT_slot structure
393
  .found_free_slot:                                             ; We found a free slot, let's fill in the FRAGMENT_slot structure
395
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; RFC recommends 15 secs as ttl
394
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; RFC recommends 15 secs as ttl
396
        mov     ax, [edx + IPv4_header.Identification]
395
        mov     ax, [edx + IPv4_header.Identification]
397
        mov     [esi + IPv4_FRAGMENT_slot.id], ax
396
        mov     [esi + IPv4_FRAGMENT_slot.id], ax
398
        mov     eax, [edx + IPv4_header.SourceAddress]
397
        mov     eax, [edx + IPv4_header.SourceAddress]
399
        mov     [esi + IPv4_FRAGMENT_slot.SrcIP], eax
398
        mov     [esi + IPv4_FRAGMENT_slot.SrcIP], eax
400
        mov     eax, [edx + IPv4_header.DestinationAddress]
399
        mov     eax, [edx + IPv4_header.DestinationAddress]
401
        mov     [esi + IPv4_FRAGMENT_slot.DstIP], eax
400
        mov     [esi + IPv4_FRAGMENT_slot.DstIP], eax
402
        pop     eax
401
        pop     eax
403
        mov     [esi + IPv4_FRAGMENT_slot.ptr], eax
402
        mov     [esi + IPv4_FRAGMENT_slot.ptr], eax
404
                                                                ; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
403
                                                                ; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
405
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
404
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
406
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], -1
405
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], -1
407
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
406
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
408
 
407
 
409
        add     esp, 4                                          ; balance stack and exit
408
        add     esp, 4                                          ; balance stack and exit
410
        ret
409
        ret
411
 
410
 
412
 
411
 
413
;-----------------------------------
412
;-----------------------------------
414
; We have received the last fragment
413
; We have received the last fragment
415
 
414
 
416
  .is_last_fragment:
415
  .is_last_fragment:
417
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Last fragment packet received!\n"
416
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Last fragment packet received!\n"
418
 
417
 
419
        call    IPv4_find_fragment_slot
418
        call    IPv4_find_fragment_slot
420
        cmp     esi, -1
419
        cmp     esi, -1
421
        je      .dump
420
        je      .dump
422
 
421
 
423
        mov     esi, [esi + IPv4_FRAGMENT_slot.ptr]                     ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
422
        mov     esi, [esi + IPv4_FRAGMENT_slot.ptr]                     ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
424
        push    esi
423
        push    esi
425
        xor     eax, eax
424
        xor     eax, eax
426
        or      edi, -1
425
        or      edi, -1
427
 
426
 
428
  .count_bytes:
427
  .count_bytes:
429
        cmp     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
428
        cmp     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
430
        jne     .destroy_slot_pop                                                       ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
429
        jne     .destroy_slot_pop                                                       ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
431
        mov     cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]        ; Add total length
430
        mov     cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]        ; Add total length
432
        xchg    cl, ch
431
        xchg    cl, ch
433
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
432
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
434
        add     ax, cx
433
        add     ax, cx
435
        movzx   cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]      ; Sub Header length
434
        movzx   cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]      ; Sub Header length
436
        and     cx, 0x000F
435
        and     cx, 0x000F
437
        shl     cx, 2
436
        shl     cx, 2
438
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx
437
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx
439
        sub     ax, cx
438
        sub     ax, cx
440
        mov     edi, esi
439
        mov     edi, esi
441
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
440
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
442
        cmp     esi, -1
441
        cmp     esi, -1
443
        jne     .count_bytes
442
        jne     .count_bytes
444
 
443
 
445
        mov     esi, [esp+4]
444
        mov     esi, [esp+4]
446
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], esi                                ; Add this packet to the chain, this simplifies the following code
445
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], esi                                ; Add this packet to the chain, this simplifies the following code
447
        mov     [esi + IPv4_FRAGMENT_entry.NextPtr], -1
446
        mov     [esi + IPv4_FRAGMENT_entry.NextPtr], -1
448
        mov     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
447
        mov     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
449
        mov     [esi + IPv4_FRAGMENT_entry.Owner], ebx
448
        mov     [esi + IPv4_FRAGMENT_entry.Owner], ebx
450
 
449
 
451
        mov     cx, [edx + IPv4_header.TotalLength]                                     ; Note: This time we dont substract Header length
450
        mov     cx, [edx + IPv4_header.TotalLength]                                     ; Note: This time we dont substract Header length
452
        xchg    cl, ch
451
        xchg    cl, ch
453
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
452
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
454
        add     ax, cx
453
        add     ax, cx
455
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Received data size=%u\n", eax
454
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Received data size=%u\n", eax
456
 
455
 
457
        push    eax
456
        push    eax
458
        mov     ax, [edx + IPv4_header.FlagsAndFragmentOffset]
457
        mov     ax, [edx + IPv4_header.FlagsAndFragmentOffset]
459
        xchg    al, ah
458
        xchg    al, ah
460
        shl     ax, 3
459
        shl     ax, 3
461
        add     cx, ax
460
        add     cx, ax
462
        pop     eax
461
        pop     eax
463
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Fragment size=%u\n", ecx
462
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Fragment size=%u\n", ecx
464
 
463
 
465
        cmp     ax, cx
464
        cmp     ax, cx
466
        jne     .destroy_slot_pop
465
        jne     .destroy_slot_pop
467
 
466
 
468
        push    eax
467
        push    eax
469
        push    eax
468
        push    eax
470
        call    kernel_alloc
469
        call    kernel_alloc
471
        test    eax, eax
470
        test    eax, eax
472
        je      .destroy_slot_pop                                                       ; If we dont have enough space to allocate the buffer, discard all packets in slot
471
        je      .destroy_slot_pop                                                       ; If we dont have enough space to allocate the buffer, discard all packets in slot
473
        mov     edx, [esp+4]                                                            ; Get pointer to first fragment entry back in edx
472
        mov     edx, [esp+4]                                                            ; Get pointer to first fragment entry back in edx
474
 
473
 
475
  .rebuild_packet_loop:
474
  .rebuild_packet_loop:
476
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
475
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
477
        xchg    cl, ch                                                                  ;  intel byte order
476
        xchg    cl, ch                                                                  ;  intel byte order
478
        shl     cx, 3                                                                   ;   multiply by 8 and clear first 3 bits
477
        shl     cx, 3                                                                   ;   multiply by 8 and clear first 3 bits
479
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx
478
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx
480
 
479
 
481
        lea     edi, [eax + ecx]                                                        ; Notice that edi will be equal to eax for first fragment
480
        lea     edi, [eax + ecx]                                                        ; Notice that edi will be equal to eax for first fragment
482
        movzx   ebx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]     ; Find header size (in ebx) of fragment
481
        movzx   ebx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]     ; Find header size (in ebx) of fragment
483
        and     bx, 0x000F                                                              ;
482
        and     bx, 0x000F                                                              ;
484
        shl     bx, 2                                                                   ;
483
        shl     bx, 2                                                                   ;
485
 
484
 
486
        lea     esi, [edx + sizeof.IPv4_FRAGMENT_entry]                                 ; Set esi to the correct begin of fragment
485
        lea     esi, [edx + sizeof.IPv4_FRAGMENT_entry]                                 ; Set esi to the correct begin of fragment
487
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]       ; Calculate total length of fragment
486
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]       ; Calculate total length of fragment
488
        xchg    cl, ch                                                                  ;  intel byte order
487
        xchg    cl, ch                                                                  ;  intel byte order
489
 
488
 
490
        cmp     edi, eax                                                                ; Is this packet the first fragment ?
489
        cmp     edi, eax                                                                ; Is this packet the first fragment ?
491
        je      .first_fragment
490
        je      .first_fragment
492
        sub     cx, bx                                                                  ; If not, dont copy the header
491
        sub     cx, bx                                                                  ; If not, dont copy the header
493
        add     esi, ebx                                                                ;
492
        add     esi, ebx                                                                ;
494
  .first_fragment:
493
  .first_fragment:
495
 
494
 
496
 
495
 
497
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Copying %u bytes from 0x%x to 0x%x\n", ecx, esi, edi
496
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Copying %u bytes from 0x%x to 0x%x\n", ecx, esi, edi
498
        push    cx                                                                      ; First copy dword-wise, then byte-wise
497
        push    cx                                                                      ; First copy dword-wise, then byte-wise
499
        shr     cx, 2                                                                   ;
498
        shr     cx, 2                                                                   ;
500
        rep movsd                                                                       ;
499
        rep movsd                                                                       ;
501
        pop     cx                                                                      ;
500
        pop     cx                                                                      ;
502
        and     cx, 3                                                                   ;
501
        and     cx, 3                                                                   ;
503
        rep movsb                                                                       ;
502
        rep movsb                                                                       ;
504
 
503
 
505
        push    eax
504
        push    eax
506
        push    [edx + IPv4_FRAGMENT_entry.Owner]                                       ; we need to remeber the owner, in case this is the last packet
505
        push    [edx + IPv4_FRAGMENT_entry.Owner]                                       ; we need to remeber the owner, in case this is the last packet
507
        push    [edx + IPv4_FRAGMENT_entry.NextPtr]                                     ; Set edx to the next pointer
506
        push    [edx + IPv4_FRAGMENT_entry.NextPtr]                                     ; Set edx to the next pointer
508
        push    edx                                                                     ; Push pointer to fragment onto stack
507
        push    edx                                                                     ; Push pointer to fragment onto stack
509
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Next Fragment: 0x%x\n", edx
508
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Next Fragment: 0x%x\n", edx
510
        call    NET_packet_free                                                         ; free the previous fragment buffer (this uses the value from stack)
509
        call    NET_packet_free                                                         ; free the previous fragment buffer (this uses the value from stack)
511
        pop     edx ebx eax
510
        pop     edx ebx eax
512
        cmp     edx, -1                                                                 ; Check if it is last fragment in chain
511
        cmp     edx, -1                                                                 ; Check if it is last fragment in chain
513
        jne     .rebuild_packet_loop
512
        jne     .rebuild_packet_loop
514
 
513
 
515
        pop     ecx
514
        pop     ecx
516
        xchg    cl, ch
515
        xchg    cl, ch
517
        mov     edx, eax
516
        mov     edx, eax
518
        mov     [edx + IPv4_header.TotalLength], cx
517
        mov     [edx + IPv4_header.TotalLength], cx
519
        add     esp, 12
518
        add     esp, 12
520
        xchg    cl, ch
519
        xchg    cl, ch
521
        push    ecx edx                 ; size and pointer
520
        push    ecx edx                 ; size and pointer
522
        jmp     .handle_it              ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
521
        jmp     .handle_it              ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
523
 
522
 
524
  .destroy_slot_pop:
523
  .destroy_slot_pop:
525
        add     esp, 4
524
        add     esp, 4
526
  .destroy_slot:
525
  .destroy_slot:
527
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Destroy fragment slot!\n"
526
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Destroy fragment slot!\n"
528
        ; TODO!
527
        ; TODO!
529
        jmp     .dump
528
        jmp     .dump
530
 
529
 
531
 
530
 
532
 
531
 
533
 
532
 
534
 
533
 
535
;-----------------------------------------------------------------
534
;-----------------------------------------------------------------
536
;
535
;
537
; find fragment slot
536
; find fragment slot
538
;
537
;
539
; IN: pointer to fragmented packet in edx
538
; IN: pointer to fragmented packet in edx
540
; OUT: pointer to slot in esi, -1 on error
539
; OUT: pointer to slot in esi, -1 on error
541
;
540
;
542
;-----------------------------------------------------------------
541
;-----------------------------------------------------------------
543
align 4
542
align 4
544
IPv4_find_fragment_slot:
543
IPv4_find_fragment_slot:
545
 
544
 
546
;;; TODO: the RFC says we should check protocol number too
545
;;; TODO: the RFC says we should check protocol number too
547
 
546
 
548
        push    eax ebx ecx edx
547
        push    eax ebx ecx edx
549
        mov     ax, [edx + IPv4_header.Identification]
548
        mov     ax, [edx + IPv4_header.Identification]
550
        mov     ecx, IPv4_MAX_FRAGMENTS
549
        mov     ecx, IPv4_MAX_FRAGMENTS
551
        mov     esi, IPv4_FRAGMENT_LIST
550
        mov     esi, IPv4_FRAGMENT_LIST
552
        mov     ebx, [edx + IPv4_header.SourceAddress]
551
        mov     ebx, [edx + IPv4_header.SourceAddress]
553
        mov     edx, [edx + IPv4_header.DestinationAddress]
552
        mov     edx, [edx + IPv4_header.DestinationAddress]
554
  .find_slot:
553
  .find_slot:
555
        cmp     [esi + IPv4_FRAGMENT_slot.id], ax
554
        cmp     [esi + IPv4_FRAGMENT_slot.id], ax
556
        jne     .try_next
555
        jne     .try_next
557
        cmp     [esi + IPv4_FRAGMENT_slot.SrcIP], ebx
556
        cmp     [esi + IPv4_FRAGMENT_slot.SrcIP], ebx
558
        jne     .try_next
557
        jne     .try_next
559
        cmp     [esi + IPv4_FRAGMENT_slot.DstIP], edx
558
        cmp     [esi + IPv4_FRAGMENT_slot.DstIP], edx
560
        je      .found_slot
559
        je      .found_slot
561
  .try_next:
560
  .try_next:
562
        add     esi, sizeof.IPv4_FRAGMENT_slot
561
        add     esi, sizeof.IPv4_FRAGMENT_slot
563
        loop    .find_slot
562
        loop    .find_slot
564
 
563
 
565
        or      esi, -1
564
        or      esi, -1
566
  .found_slot:
565
  .found_slot:
567
        pop     edx ecx ebx eax
566
        pop     edx ecx ebx eax
568
        ret
567
        ret
569
 
568
 
570
 
569
 
571
;------------------------------------------------------------------
570
;------------------------------------------------------------------
572
;
571
;
573
; IPv4_output
572
; IPv4_output
574
;
573
;
575
; IN:   eax = Destination IP
574
; IN:   eax = Destination IP
576
;       ecx = data length
575
;       ecx = data length
577
;       edx = Source IP
576
;       edx = Source IP
578
;       di  = TTL shl 8 + protocol
577
;       di  = TTL shl 8 + protocol
579
;
578
;
580
; OUT:  eax = pointer to buffer start
579
; OUT:  eax = pointer to buffer start / 0 on error
581
;       ebx = pointer to device struct (needed for sending procedure)
580
;       ebx = device ptr (send packet through this device)
582
;       ecx = unchanged (packet size of embedded data)
581
;       ecx = data length
583
;       edx = size of complete buffer
582
;       edx = size of complete frame
584
;       edi = pointer to start of data (0 on error)
583
;       edi = start of IPv4 payload
585
;
584
;
586
;------------------------------------------------------------------
585
;------------------------------------------------------------------
587
align 4
586
align 4
588
IPv4_output:
587
IPv4_output:
589
 
588
 
590
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u ip=0x%x\n", ecx, eax
589
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u ip=0x%x\n", ecx, eax
591
 
590
 
592
        cmp     ecx, 65500              ; Max IPv4 packet size
591
        cmp     ecx, 65500              ; Max IPv4 packet size
593
        ja      .too_large
592
        ja      .too_large
594
 
593
 
595
        push    ecx di eax
594
        push    ecx di eax
596
        call    IPv4_route              ; outputs device number in edi, dest ip in eax, source IP in edx
595
        call    IPv4_route              ; outputs device number in edi, dest ip in eax, source IP in edx
597
        push    edx
596
        push    edx
598
 
-
 
599
        test    edi, edi
597
        test    edi, edi
600
        jz      .loopback
598
        jz      .loopback
601
 
599
 
602
        call    ARP_IP_to_MAC
600
        call    ARP_IP_to_MAC
603
        test    eax, 0xffff0000         ; error bits
601
        test    eax, 0xffff0000         ; error bits
604
        jnz     .arp_error
602
        jnz     .arp_error
605
        push    ebx                     ; push the mac onto the stack
603
        push    ebx                     ; push the mac onto the stack
606
        push    ax
604
        push    ax
607
 
605
 
608
        inc     [IPv4_packets_tx + edi]   ; update stats
606
        inc     [IPv4_packets_tx + edi]   ; update stats
-
 
607
 
609
 
608
        mov     ax, ETHER_PROTO_IPv4
610
        mov     ebx, [NET_DRV_LIST + edi]
-
 
611
        lea     eax, [ebx + ETH_DEVICE.mac]
-
 
612
        mov     edx, esp
609
        mov     ebx, [NET_DRV_LIST + edi]
613
        mov     ecx, [esp + 6 + 8 + 2]
610
        mov     ecx, [esp + 6 + 8 + 2]
614
        add     ecx, sizeof.IPv4_header
611
        add     ecx, sizeof.IPv4_header
615
        mov     di, ETHER_PROTO_IPv4
612
        mov     edx, esp
616
        call    ETH_output
613
        call    ETH_output
617
        jz      .eth_error
614
        jz      .eth_error
618
        add     esp, 6                  ; pop the mac out of the stack
615
        add     esp, 6                  ; pop the mac out of the stack
619
 
616
 
620
  .continue:
617
  .continue:
621
        xchg    cl, ch                                  ; internet byte order
618
        xchg    cl, ch                                  ; internet byte order
622
        mov     [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
619
        mov     [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
623
        mov     [edi + IPv4_header.TypeOfService], 0    ; nothing special, just plain ip packet
620
        mov     [edi + IPv4_header.TypeOfService], 0    ; nothing special, just plain ip packet
624
        mov     [edi + IPv4_header.TotalLength], cx
621
        mov     [edi + IPv4_header.TotalLength], cx
625
        mov     [edi + IPv4_header.Identification], 0   ; fragment id: FIXME
622
        mov     [edi + IPv4_header.Identification], 0   ; fragment id: FIXME
626
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], 0
623
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], 0
627
 
624
 
628
        mov     [edi + IPv4_header.HeaderChecksum], 0
625
        mov     [edi + IPv4_header.HeaderChecksum], 0
629
        popd    [edi + IPv4_header.SourceAddress]
626
        popd    [edi + IPv4_header.SourceAddress]
630
        popd    [edi + IPv4_header.DestinationAddress]
627
        popd    [edi + IPv4_header.DestinationAddress]
631
 
628
 
632
        pop     word[edi + IPv4_header.TimeToLive]      ; ttl shl 8 + protocol
629
        pop     word[edi + IPv4_header.TimeToLive]      ; ttl shl 8 + protocol
633
;               [edi + IPv4_header.Protocol]
630
;               [edi + IPv4_header.Protocol]
634
 
631
 
635
        pop     ecx
632
        pop     ecx
636
 
633
 
637
        IPv4_checksum edi
634
        IPv4_checksum edi
638
        add     edi, sizeof.IPv4_header
635
        add     edi, sizeof.IPv4_header
639
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: success!\n"
636
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: success!\n"
640
        ret
637
        ret
641
 
638
 
642
  .eth_error:
639
  .eth_error:
643
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ethernet error\n"
640
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ethernet error\n"
644
        add     esp, 3*4+2+6
641
        add     esp, 3*4+2+6
645
        xor     edi, edi
642
        xor     eax, eax
646
        ret
643
        ret
647
 
644
 
648
  .arp_error:
645
  .arp_error:
649
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
646
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
650
        add     esp, 3*4+2
647
        add     esp, 3*4+2
651
        xor     edi, edi
648
        xor     eax, eax
652
        ret
649
        ret
653
 
650
 
654
  .too_large:
651
  .too_large:
655
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n"
652
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n"
656
        xor     edi, edi
653
        xor     eax, eax
657
        ret
654
        ret
658
 
655
 
659
  .loopback:
656
  .loopback:
660
        mov     dword [esp + 2], eax            ; change source IP to dest IP
657
        mov     dword [esp + 2], eax            ; change source IP to dest IP
661
        mov     ecx, [esp + 10]
658
        mov     ecx, [esp + 10]
662
        add     ecx, sizeof.IPv4_header
659
        add     ecx, sizeof.IPv4_header
663
        mov     edi, AF_INET4
660
        mov     edi, AF_INET4
664
        call    LOOP_output
661
        call    LOOP_output
665
        jmp     .continue
662
        jmp     .continue
666
 
663
 
667
 
664
 
668
 
665
 
669
 
666
 
670
;------------------------------------------------------------------
667
;------------------------------------------------------------------
671
;
668
;
672
; IPv4_output_raw
669
; IPv4_output_raw
673
;
670
;
674
; IN: eax = socket ptr
671
; IN: eax = socket ptr
675
;     ecx = data length
672
;     ecx = data length
676
;     esi = data ptr
673
;     esi = data ptr
677
;
674
;
678
; OUT: /
675
; OUT: eax = -1 on error
679
;
676
;
680
;------------------------------------------------------------------
677
;------------------------------------------------------------------
681
align 4
678
align 4
682
IPv4_output_raw:
679
IPv4_output_raw:
683
 
680
 
684
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
681
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
685
 
682
 
686
        cmp     ecx, 1480               ;;;;; FIXME
683
        cmp     ecx, 1480               ;;;;; FIXME
687
        ja      .too_large
684
        ja      .too_large
688
 
685
 
689
        sub     esp, 8
686
        sub     esp, 8
690
        push    esi eax
687
        push    esi eax
691
 
688
 
692
        call    IPv4_route
689
        call    IPv4_route
693
        call    ARP_IP_to_MAC
690
        call    ARP_IP_to_MAC
694
 
691
 
695
        test    eax, 0xffff0000         ; error bits
692
        test    eax, 0xffff0000         ; error bits
696
        jnz     .arp_error
693
        jnz     .arp_error
697
 
694
 
698
        push    ebx                     ; push the mac
695
        push    ebx                     ; push the mac
699
        push    ax
696
        push    ax
700
 
697
 
701
        inc     [IPv4_packets_tx + 4*edi]
698
        inc     [IPv4_packets_tx + 4*edi]
-
 
699
        mov     ax, ETHER_PROTO_IPv4
702
        mov     ebx, [NET_DRV_LIST + 4*edi]
700
        mov     ebx, [NET_DRV_LIST + 4*edi]
703
        lea     eax, [ebx + ETH_DEVICE.mac]
-
 
704
        mov     edx, esp
-
 
705
        mov     ecx, [esp + 6 + 4]
701
        mov     ecx, [esp + 6 + 4]
706
        add     ecx, sizeof.IPv4_header
702
        add     ecx, sizeof.IPv4_header
707
        mov     di, ETHER_PROTO_IPv4
703
        mov     edx, esp
708
        call    ETH_output
704
        call    ETH_output
709
        jz      .error
705
        jz      .error
710
 
-
 
711
        add     esp, 6  ; pop the mac
706
        add     esp, 6  ; pop the mac
712
 
707
 
713
        mov     dword[esp+4+4], edx
708
        mov     dword[esp+4+4], edx
714
        mov     dword[esp+4+4+4], eax
709
        mov     dword[esp+4+4+4], eax
715
 
710
 
716
        pop     eax esi
711
        pop     eax esi
717
;; todo: check socket options if we should add header, or just compute checksum
712
;; todo: check socket options if we should add header, or just compute checksum
718
 
713
 
719
        push    edi ecx
714
        push    edi ecx
720
        rep movsb
715
        rep movsb
721
        pop     ecx edi
716
        pop     ecx edi
722
 
717
 
723
;        [edi + IPv4_header.VersionAndIHL]              ; IPv4, normal length (no Optional header)
718
;        [edi + IPv4_header.VersionAndIHL]              ; IPv4, normal length (no Optional header)
724
;        [edi + IPv4_header.TypeOfService]              ; nothing special, just plain ip packet
719
;        [edi + IPv4_header.TypeOfService]              ; nothing special, just plain ip packet
725
;        [edi + IPv4_header.TotalLength]
720
;        [edi + IPv4_header.TotalLength]
726
;        [edi + IPv4_header.TotalLength]                ; internet byte order
721
;        [edi + IPv4_header.TotalLength]                ; internet byte order
727
;        [edi + IPv4_header.FlagsAndFragmentOffset]
722
;        [edi + IPv4_header.FlagsAndFragmentOffset]
728
 
723
 
729
        mov     [edi + IPv4_header.HeaderChecksum], 0
724
        mov     [edi + IPv4_header.HeaderChecksum], 0
730
 
725
 
731
;        [edi + IPv4_header.TimeToLive]                 ; ttl shl 8 + protocol
726
;        [edi + IPv4_header.TimeToLive]                 ; ttl shl 8 + protocol
732
;        [edi + IPv4_header.Protocol]
727
;        [edi + IPv4_header.Protocol]
733
;        [edi + IPv4_header.Identification]             ; fragment id
728
;        [edi + IPv4_header.Identification]             ; fragment id
734
;        [edi + IPv4_header.SourceAddress]
729
;        [edi + IPv4_header.SourceAddress]
735
;        [edi + IPv4_header.DestinationAddress]
730
;        [edi + IPv4_header.DestinationAddress]
736
 
731
 
737
        IPv4_checksum edi                       ;;;; todo: checksum for IP packet with options!
732
        IPv4_checksum edi                       ;;;; todo: checksum for IP packet with options!
738
        add     edi, sizeof.IPv4_header
733
        add     edi, sizeof.IPv4_header
739
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
734
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
740
        call    [ebx + NET_DEVICE.transmit]
735
        call    [ebx + NET_DEVICE.transmit]
741
        ret
736
        ret
742
 
737
 
743
  .error:
738
  .error:
744
        add     esp, 6
739
        add     esp, 6
745
  .arp_error:
740
  .arp_error:
746
        add     esp, 8+4+4
741
        add     esp, 8+4+4
747
  .too_large:
742
  .too_large:
748
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
743
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
749
        sub     edi, edi
744
        or      eax, -1
750
        ret
745
        ret
751
 
746
 
752
 
747
 
753
;--------------------------------------------------------
748
;--------------------------------------------------------
754
;
749
;
755
;
750
;
756
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
751
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
757
;     dword [esp+4] = buffer size
752
;     dword [esp+4] = buffer size
758
;     esi = pointer to ip header in that buffer
753
;     esi = pointer to ip header in that buffer
759
;     ecx = max size of fragments
754
;     ecx = max size of fragments
760
;
755
;
761
; OUT: /
756
; OUT: /
762
;
757
;
763
;--------------------------------------------------------
758
;--------------------------------------------------------
764
 
759
 
765
align 4
760
align 4
766
IPv4_fragment:
761
IPv4_fragment:
767
 
762
 
768
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
763
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
769
 
764
 
770
        and     ecx, not 111b   ; align 4
765
        and     ecx, not 111b   ; align 4
771
 
766
 
772
        cmp     ecx, sizeof.IPv4_header + 8     ; must be able to put at least 8 bytes
767
        cmp     ecx, sizeof.IPv4_header + 8     ; must be able to put at least 8 bytes
773
        jb      .err2
768
        jb      .err2
774
 
769
 
775
        push    esi ecx
770
        push    esi ecx
776
        mov     eax, [esi + IPv4_header.DestinationAddress]
771
        mov     eax, [esi + IPv4_header.DestinationAddress]
777
        call    ARP_IP_to_MAC
772
        call    ARP_IP_to_MAC
778
        pop     ecx esi
773
        pop     ecx esi
779
        cmp     eax, -1
774
        cmp     eax, -1
780
        jz      .err2
775
        jz      .err2
781
 
776
 
782
        push    ebx
777
        push    ebx
783
        push    ax
778
        push    ax
784
 
779
 
785
        mov     ebx, [NET_DRV_LIST]
780
        mov     ebx, [NET_DRV_LIST]
786
        lea     eax, [ebx + ETH_DEVICE.mac]
781
        lea     eax, [ebx + ETH_DEVICE.mac]
787
        push    eax
782
        push    eax
788
 
783
 
789
 
784
 
790
        push    esi                             ; ptr to ip header
785
        push    esi                             ; ptr to ip header
791
        sub     ecx, sizeof.IPv4_header         ; substract header size
786
        sub     ecx, sizeof.IPv4_header         ; substract header size
792
        push    ecx                             ; max data size
787
        push    ecx                             ; max data size
793
        push    dword 0                         ; offset
788
        push    dword 0                         ; offset
794
 
789
 
795
  .new_fragment:
790
  .new_fragment:
796
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
791
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
797
 
-
 
798
 
792
 
799
        mov     eax, [esp + 3*4]
793
        mov     ax, ETHER_PROTO_IPv4
800
        lea     ebx, [esp + 4*4]
-
 
801
        mov     di , ETHER_PROTO_IPv4
794
        lea     ebx, [esp + 4*4]
802
        call    ETH_output
-
 
803
 
-
 
804
        cmp     edi, -1
795
        call    ETH_output
805
        jz      .err
796
        jz      .err
806
 
797
 
807
; copy header
798
; copy header
808
        mov     esi, [esp + 2*4]
799
        mov     esi, [esp + 2*4]
809
        mov     ecx, 5  ; 5 dwords: TODO: use IHL field of the header!
800
        mov     ecx, 5  ; 5 dwords: TODO: use IHL field of the header!
810
        rep movsd
801
        rep movsd
811
 
802
 
812
; copy data
803
; copy data
813
        mov     esi, [esp + 2*4]
804
        mov     esi, [esp + 2*4]
814
        add     esi, sizeof.IPv4_header
805
        add     esi, sizeof.IPv4_header
815
        add     esi, [esp]      ; offset
806
        add     esi, [esp]      ; offset
816
 
807
 
817
        mov     ecx, [esp + 1*4]
808
        mov     ecx, [esp + 1*4]
818
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx
809
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx
819
        rep movsb
810
        rep movsb
820
 
811
 
821
; now, correct header
812
; now, correct header
822
        mov     ecx, [esp + 1*4]
813
        mov     ecx, [esp + 1*4]
823
        add     ecx, sizeof.IPv4_header
814
        add     ecx, sizeof.IPv4_header
824
        xchg    cl, ch
815
        xchg    cl, ch
825
        mov     [edi + IPv4_header.TotalLength], cx
816
        mov     [edi + IPv4_header.TotalLength], cx
826
 
817
 
827
        mov     ecx, [esp]              ; offset
818
        mov     ecx, [esp]              ; offset
828
        xchg    cl, ch
819
        xchg    cl, ch
829
 
820
 
830
;        cmp     dword[esp + 4*4], 0     ; last fragment?;<<<<<<
821
;        cmp     dword[esp + 4*4], 0     ; last fragment?;<<<<<<
831
;        je      .last_fragment
822
;        je      .last_fragment
832
        or      cx, 1 shl 2             ; more fragments
823
        or      cx, 1 shl 2             ; more fragments
833
;  .last_fragment:
824
;  .last_fragment:
834
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], cx
825
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], cx
835
 
826
 
836
        mov     [edi + IPv4_header.HeaderChecksum], 0
827
        mov     [edi + IPv4_header.HeaderChecksum], 0
837
 
828
 
838
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
829
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
839
        mov     ecx, [esp + 1*4]
830
        mov     ecx, [esp + 1*4]
840
 
831
 
841
        push    edx eax
832
        push    edx eax
842
        IPv4_checksum edi
833
        IPv4_checksum edi
843
 
834
 
844
        call    [ebx + NET_DEVICE.transmit]
835
        call    [ebx + NET_DEVICE.transmit]
845
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
836
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
846
 
837
 
847
        mov     ecx, [esp+4]
838
        mov     ecx, [esp+4]
848
        add     [esp], ecx
839
        add     [esp], ecx
849
 
840
 
850
        mov     ecx, [esp+3*4+6+4]      ; ptr to begin of buff
841
        mov     ecx, [esp+3*4+6+4]      ; ptr to begin of buff
851
        add     ecx, [esp+3*4+6+4+4]    ; buff size
842
        add     ecx, [esp+3*4+6+4+4]    ; buff size
852
        sub     ecx, [esp+2*4]          ; ptr to ip header
843
        sub     ecx, [esp+2*4]          ; ptr to ip header
853
        add     ecx, [esp]              ; offset
844
        add     ecx, [esp]              ; offset
854
 
845
 
855
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: %u bytes remaining\n", ecx
846
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: %u bytes remaining\n", ecx
856
 
847
 
857
        cmp     ecx, [esp+1*4]
848
        cmp     ecx, [esp+1*4]
858
        jae     .new_fragment
849
        jae     .new_fragment
859
 
850
 
860
        mov     [esp+4], ecx            ; set fragment size to remaining packet size
851
        mov     [esp+4], ecx            ; set fragment size to remaining packet size
861
        jmp     .new_fragment
852
        jmp     .new_fragment
862
 
853
 
863
      .err:
854
      .err:
864
        DEBUGF  DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
855
        DEBUGF  DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
865
      .done:
856
      .done:
866
        add     esp, 12 + 4 + 6
857
        add     esp, 12 + 4 + 6
867
      .err2:
858
      .err2:
868
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: dumping\n"
859
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: dumping\n"
869
        call    NET_packet_free
860
        call    NET_packet_free
870
        add     esp, 4
861
        add     esp, 4
871
 
862
 
872
        ret
863
        ret
873
 
864
 
874
 
865
 
875
 
866
 
876
;---------------------------------------------------------------------------
867
;---------------------------------------------------------------------------
877
;
868
;
878
; IPv4_route
869
; IPv4_route
879
;
870
;
880
; IN:   eax = Destination IP
871
; IN:   eax = Destination IP
881
;       edx = Source IP
872
;       edx = Source IP
882
; OUT:  eax = Destination IP (or gateway IP)
873
; OUT:  eax = Destination IP (or gateway IP)
883
;       edx = Source IP
874
;       edx = Source IP
884
;       edi = device number*4
875
;       edi = device number*4
885
; DESTROYED:
876
; DESTROYED:
886
;       ecx
877
;       ecx
887
;
878
;
888
;---------------------------------------------------------------------------
879
;---------------------------------------------------------------------------
889
align 4
880
align 4
890
IPv4_route:     ; TODO: return error if no valid route found
881
IPv4_route:     ; TODO: return error if no valid route found
891
 
882
 
892
        cmp     eax, 0xffffffff
883
        cmp     eax, 0xffffffff
893
        je      .broadcast
884
        je      .broadcast
894
 
885
 
895
        xor     edi, edi
886
        xor     edi, edi
896
  .loop:
887
  .loop:
897
        mov     ebx, [IP_LIST + edi]
888
        mov     ebx, [IP_LIST + edi]
898
        and     ebx, [SUBNET_LIST + edi]
889
        and     ebx, [SUBNET_LIST + edi]
899
        jz      .next
890
        jz      .next
900
        mov     ecx, eax
891
        mov     ecx, eax
901
        and     ecx, [SUBNET_LIST + edi]
892
        and     ecx, [SUBNET_LIST + edi]
902
        cmp     ebx, ecx
893
        cmp     ebx, ecx
903
        je      .got_it
894
        je      .got_it
904
  .next:
895
  .next:
905
        add     edi, 4
896
        add     edi, 4
906
        cmp     edi, 4*NET_DEVICES_MAX
897
        cmp     edi, 4*NET_DEVICES_MAX
907
        jb      .loop
898
        jb      .loop
908
 
899
 
909
        mov     eax, [GATEWAY_LIST + 4]         ; TODO: let user (or a user space daemon) configure default route
900
        mov     eax, [GATEWAY_LIST + 4]         ; TODO: let user (or a user space daemon) configure default route
910
  .broadcast:
901
  .broadcast:
911
        mov     edi, 4                          ; TODO: same as above
902
        mov     edi, 4                          ; TODO: same as above
912
  .got_it:
903
  .got_it:
913
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
904
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
914
        test    edx, edx
905
        test    edx, edx
915
        jnz     @f
906
        jnz     @f
916
        mov     edx, [IP_LIST + edi]
907
        mov     edx, [IP_LIST + edi]
917
  @@:
908
  @@:
918
 
909
 
919
        ret
910
        ret
920
 
911
 
921
 
912
 
922
 
913
 
923
;---------------------------------------------------------------------------
914
;---------------------------------------------------------------------------
924
;
915
;
925
; IPv4_get_frgmnt_num
916
; IPv4_get_frgmnt_num
926
;
917
;
927
; IN: /
918
; IN: /
928
; OUT: fragment number in ax
919
; OUT: fragment number in ax
929
;
920
;
930
;---------------------------------------------------------------------------
921
;---------------------------------------------------------------------------
931
align 4
922
align 4
932
IPv4_get_frgmnt_num:
923
IPv4_get_frgmnt_num:
933
        xor     ax, ax  ;;; TODO: replace this with real code
924
        xor     ax, ax  ;;; TODO: replace this with real code
934
 
925
 
935
        ret
926
        ret
936
 
927
 
937
 
928
 
938
;-----------------------------------------------------------------
929
;-----------------------------------------------------------------
939
;
930
;
940
; IPv4_connect
931
; IPv4_connect
941
;
932
;
942
;   IN: eax = socket pointer
933
;   IN: eax = socket pointer
943
;  OUT: eax = 0 ok / -1 error
934
;  OUT: eax = 0 ok / -1 error
944
;       ebx = error code
935
;       ebx = error code
945
;
936
;
946
;-------------------------
937
;-------------------------
947
align 4
938
align 4
948
IPv4_connect:
939
IPv4_connect:
949
 
940
 
950
        push    eax edx
941
        push    eax edx
951
        lea     ecx, [eax + SOCKET.mutex]
942
        lea     ecx, [eax + SOCKET.mutex]
952
        call    mutex_lock
943
        call    mutex_lock
953
        pop     edx eax
944
        pop     edx eax
954
 
945
 
955
; Fill in local IP
946
; Fill in local IP
956
        cmp     [eax + IP_SOCKET.LocalIP], 0
947
        cmp     [eax + IP_SOCKET.LocalIP], 0
957
        jne     @f
948
        jne     @f
958
        push    [IP_LIST + 4]                                   ; FIXME: use correct local IP
949
        push    [IP_LIST + 4]                                   ; FIXME: use correct local IP
959
        pop     [eax + IP_SOCKET.LocalIP]
950
        pop     [eax + IP_SOCKET.LocalIP]
960
 
951
 
961
; Fill in remote IP
952
; Fill in remote IP
962
        pushd   [edx + 4]
953
        pushd   [edx + 4]
963
        pop     [eax + IP_SOCKET.RemoteIP]
954
        pop     [eax + IP_SOCKET.RemoteIP]
964
 
955
 
965
; Set up data receiving queue
956
; Set up data receiving queue
966
        push    eax
957
        push    eax
967
        init_queue (eax + SOCKET_QUEUE_LOCATION)
958
        init_queue (eax + SOCKET_QUEUE_LOCATION)
968
        pop     eax
959
        pop     eax
969
 
960
 
970
        lea     ecx, [eax + SOCKET.mutex]
961
        lea     ecx, [eax + SOCKET.mutex]
971
        call    mutex_unlock
962
        call    mutex_unlock
972
 
963
 
973
        xor     eax, eax
964
        xor     eax, eax
974
        ret
965
        ret
975
 
966
 
976
 
967
 
977
;---------------------------------------------------------------------------
968
;---------------------------------------------------------------------------
978
;
969
;
979
; IPv4_API
970
; IPv4_API
980
;
971
;
981
; This function is called by system function 75
972
; This function is called by system function 75
982
;
973
;
983
; IN:  subfunction number in bl
974
; IN:  subfunction number in bl
984
;      device number in bh
975
;      device number in bh
985
;      ecx, edx, .. depends on subfunction
976
;      ecx, edx, .. depends on subfunction
986
;
977
;
987
; OUT:
978
; OUT:
988
;
979
;
989
;---------------------------------------------------------------------------
980
;---------------------------------------------------------------------------
990
align 4
981
align 4
991
IPv4_api:
982
IPv4_api:
992
 
983
 
993
        movzx   eax, bh
984
        movzx   eax, bh
994
        shl     eax, 2
985
        shl     eax, 2
995
 
986
 
996
        and     ebx, 0x000000ff
987
        and     ebx, 0x000000ff
997
        cmp     ebx, .number
988
        cmp     ebx, .number
998
        ja      .error
989
        ja      .error
999
        jmp     dword [.table + 4*ebx]
990
        jmp     dword [.table + 4*ebx]
1000
 
991
 
1001
  .table:
992
  .table:
1002
        dd      .packets_tx     ; 0
993
        dd      .packets_tx     ; 0
1003
        dd      .packets_rx     ; 1
994
        dd      .packets_rx     ; 1
1004
        dd      .read_ip        ; 2
995
        dd      .read_ip        ; 2
1005
        dd      .write_ip       ; 3
996
        dd      .write_ip       ; 3
1006
        dd      .read_dns       ; 4
997
        dd      .read_dns       ; 4
1007
        dd      .write_dns      ; 5
998
        dd      .write_dns      ; 5
1008
        dd      .read_subnet    ; 6
999
        dd      .read_subnet    ; 6
1009
        dd      .write_subnet   ; 7
1000
        dd      .write_subnet   ; 7
1010
        dd      .read_gateway   ; 8
1001
        dd      .read_gateway   ; 8
1011
        dd      .write_gateway  ; 9
1002
        dd      .write_gateway  ; 9
1012
  .number = ($ - .table) / 4 - 1
1003
  .number = ($ - .table) / 4 - 1
1013
 
1004
 
1014
  .error:
1005
  .error:
1015
        mov     eax, -1
1006
        mov     eax, -1
1016
        ret
1007
        ret
1017
 
1008
 
1018
  .packets_tx:
1009
  .packets_tx:
1019
        mov     eax, [IPv4_packets_tx + eax]
1010
        mov     eax, [IPv4_packets_tx + eax]
1020
        ret
1011
        ret
1021
 
1012
 
1022
  .packets_rx:
1013
  .packets_rx:
1023
        mov     eax, [IPv4_packets_rx + eax]
1014
        mov     eax, [IPv4_packets_rx + eax]
1024
        ret
1015
        ret
1025
 
1016
 
1026
  .read_ip:
1017
  .read_ip:
1027
        mov     eax, [IP_LIST + eax]
1018
        mov     eax, [IP_LIST + eax]
1028
        ret
1019
        ret
1029
 
1020
 
1030
  .write_ip:
1021
  .write_ip:
1031
        mov     [IP_LIST + eax], ecx
1022
        mov     [IP_LIST + eax], ecx
1032
        mov     edi, eax                        ; device number, we'll need it for ARP
1023
        mov     edi, eax                        ; device number, we'll need it for ARP
1033
 
1024
 
1034
        ; pre-calculate the local broadcast address
1025
        ; pre-calculate the local broadcast address
1035
        mov     ebx, [SUBNET_LIST + eax]
1026
        mov     ebx, [SUBNET_LIST + eax]
1036
        not     ebx
1027
        not     ebx
1037
        or      ebx, ecx
1028
        or      ebx, ecx
1038
        mov     [BROADCAST_LIST + eax], ebx
1029
        mov     [BROADCAST_LIST + eax], ebx
1039
 
1030
 
1040
        mov     ebx, [NET_DRV_LIST + eax]
1031
        mov     ebx, [NET_DRV_LIST + eax]
1041
        mov     eax, [IP_LIST + eax]
1032
        mov     eax, [IP_LIST + eax]
1042
        call    ARP_output_request              ; now send a gratuitous ARP
1033
        call    ARP_output_request              ; now send a gratuitous ARP
1043
 
1034
 
1044
        call    NET_send_event
1035
        call    NET_send_event
1045
        xor     eax, eax
1036
        xor     eax, eax
1046
        ret
1037
        ret
1047
 
1038
 
1048
  .read_dns:
1039
  .read_dns:
1049
        mov     eax, [DNS_LIST + eax]
1040
        mov     eax, [DNS_LIST + eax]
1050
        ret
1041
        ret
1051
 
1042
 
1052
  .write_dns:
1043
  .write_dns:
1053
        mov     [DNS_LIST + eax], ecx
1044
        mov     [DNS_LIST + eax], ecx
1054
        call    NET_send_event
1045
        call    NET_send_event
1055
        xor     eax, eax
1046
        xor     eax, eax
1056
        ret
1047
        ret
1057
 
1048
 
1058
  .read_subnet:
1049
  .read_subnet:
1059
        mov     eax, [SUBNET_LIST + eax]
1050
        mov     eax, [SUBNET_LIST + eax]
1060
        ret
1051
        ret
1061
 
1052
 
1062
  .write_subnet:
1053
  .write_subnet:
1063
        mov     [SUBNET_LIST + eax], ecx
1054
        mov     [SUBNET_LIST + eax], ecx
1064
 
1055
 
1065
        ; pre-calculate the local broadcast address
1056
        ; pre-calculate the local broadcast address
1066
        mov     ebx, [IP_LIST + eax]
1057
        mov     ebx, [IP_LIST + eax]
1067
        not     ecx
1058
        not     ecx
1068
        or      ecx, ebx
1059
        or      ecx, ebx
1069
        mov     [BROADCAST_LIST + eax], ecx
1060
        mov     [BROADCAST_LIST + eax], ecx
1070
 
1061
 
1071
        call    NET_send_event
1062
        call    NET_send_event
1072
        xor     eax, eax
1063
        xor     eax, eax
1073
        ret
1064
        ret
1074
 
1065
 
1075
  .read_gateway:
1066
  .read_gateway:
1076
        mov     eax, [GATEWAY_LIST + eax]
1067
        mov     eax, [GATEWAY_LIST + eax]
1077
        ret
1068
        ret
1078
 
1069
 
1079
  .write_gateway:
1070
  .write_gateway:
1080
        mov     [GATEWAY_LIST + eax], ecx
1071
        mov     [GATEWAY_LIST + eax], ecx
1081
 
1072
 
1082
        call    NET_send_event
1073
        call    NET_send_event
1083
        xor     eax, eax
1074
        xor     eax, eax
1084
        ret
1075
        ret
1085
 
1076
 
1086
>
1077
>
1087
 
1078
 
1088
>
1079
>
1089
 
1080
 
1090
>
1081
>
1091
 
1082
 
1092
>
1083
>
1093
 
1084
 
1094
>
1085
>
1095
 
1086
 
1096
>
1087
>
1097
 
1088
 
1098
>
1089
>
1099
 
1090
 
1100
>
1091
>
1101
 
1092
 
1102
>
1093
>
1103
 
1094
 
1104
>
1095
>
1105
 
1096
 
1106
>
1097
>
1107
 
1098
 
1108
>
1099
>
1109
 
1100
 
1110
>
1101
>
1111
 
1102
 
1112
>
1103
>
1113
 
1104
 
1114
>
1105
>
1115
 
1106
 
1116
>
1107
>
1117
 
1108
 
1118
>
1109
>
1119
 
1110
 
1120
>
1111
>
1121
 
1112
 
1122
>
1113
>
1123
 
1114
 
1124
>
1115
>
1125
 
1116
 
1126
>
1117
>
1127
 
1118
 
1128
>
1119
>
1129
 
1120
 
1130
>
1121
>
1131
 
1122
 
1132
>
1123
>
1133
 
1124
 
1134
>
1125
>
1135
 
1126
 
1136
>
1127
>
1137
 
1128
 
1138
>
1129
>
1139
 
1130
 
1140
>
1131
>
1141
 
1132
 
1142
>
1133
>
1143
;>
1134
;>
1144
;>
1135
;>
1145
;>
1136
;>
1146
;>
1137
;>
1147
;>
1138
;>
1148
;>
1139
;>