Subversion Repositories Kolibri OS

Rev

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

Rev 5522 Rev 5584
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2015. 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: 5522 $
19
$Revision: 5584 $
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
        ; maybe we just dont have an IP yet and should accept everything on the IP level
270
        ; maybe we just dont have an IP yet and should accept everything on the IP level
271
 
271
 
272
        cmp     [IP_LIST + edi], 0
272
        cmp     [IP_LIST + edi], 0
273
        je      .ip_ok
273
        je      .ip_ok
274
 
274
 
275
        ; or it's just not meant for us.. :(
275
        ; or it's just not meant for us.. :(
276
 
276
 
277
        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"
278
        jmp     .dump
278
        jmp     .dump
279
 
279
 
280
;------------------------
280
;------------------------
281
; Now we can update stats
281
; Now we can update stats
282
 
282
 
283
  .ip_ok:
283
  .ip_ok:
284
        inc     [IPv4_packets_rx + edi]
284
        inc     [IPv4_packets_rx + edi]
285
 
285
 
286
;----------------------------------
286
;----------------------------------
287
; Check if the packet is fragmented
287
; Check if the packet is fragmented
288
 
288
 
289
        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 ?
290
        jnz     .has_fragments                                          ; If so, we definately have a fragmented packet
290
        jnz     .has_fragments                                          ; If so, we definately have a fragmented packet
291
 
291
 
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
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
293
        jnz     .is_last_fragment
293
        jnz     .is_last_fragment
294
 
294
 
295
;-------------------------------------------------------------------
295
;-------------------------------------------------------------------
296
; 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
297
 
297
 
298
  .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
299
 
299
 
300
        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
301
        and     esi, 0x0000000f                                 ;
301
        and     esi, 0x0000000f                                 ;
302
        shl     esi, 2                                          ;
302
        shl     esi, 2                                          ;
303
 
303
 
304
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
304
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
305
        xchg    cl, ch                                          ;
305
        xchg    cl, ch                                          ;
306
        sub     ecx, esi                                        ;
306
        sub     ecx, esi                                        ;
307
 
307
 
308
        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
309
        mov     al, [edx + IPv4_header.Protocol]
309
        mov     al, [edx + IPv4_header.Protocol]
310
        add     esi, edx                                        ; make esi ptr to data
310
        add     esi, edx                                        ; make esi ptr to data
311
 
311
 
312
        cmp     al, IP_PROTO_TCP
312
        cmp     al, IP_PROTO_TCP
313
        je      TCP_input
313
        je      TCP_input
314
 
314
 
315
        cmp     al, IP_PROTO_UDP
315
        cmp     al, IP_PROTO_UDP
316
        je      UDP_input
316
        je      UDP_input
317
 
317
 
318
        cmp     al, IP_PROTO_ICMP
318
        cmp     al, IP_PROTO_ICMP
319
        je      ICMP_input
319
        je      ICMP_input
320
 
320
 
321
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
321
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
322
 
322
 
323
  .dump:
323
  .dump:
324
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
324
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
325
        inc     [IPv4_packets_dumped]                           ; FIXME: use correct interface
325
        inc     [IPv4_packets_dumped]                           ; FIXME: use correct interface
326
        call    NET_BUFF_free
326
        call    NET_BUFF_free
327
        ret
327
        ret
328
 
328
 
329
 
329
 
330
;---------------------------
330
;---------------------------
331
; Fragmented packet handler
331
; Fragmented packet handler
332
 
332
 
333
 
333
 
334
  .has_fragments:
334
  .has_fragments:
335
        movzx   eax, [edx + IPv4_header.FlagsAndFragmentOffset]
335
        movzx   eax, [edx + IPv4_header.FlagsAndFragmentOffset]
336
        xchg    al, ah
336
        xchg    al, ah
337
        shl     ax, 3
337
        shl     ax, 3
338
 
338
 
339
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x ptr=0x%x\n", ax, [edx + IPv4_header.Identification]:4, edx
339
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x ptr=0x%x\n", ax, [edx + IPv4_header.Identification]:4, edx
340
 
340
 
341
        test    ax, ax                                          ; Is this the first packet of the fragment?
341
        test    ax, ax                                          ; Is this the first packet of the fragment?
342
        jz      .is_first_fragment
342
        jz      .is_first_fragment
343
 
343
 
344
 
344
 
345
;-------------------------------------------------------
345
;-------------------------------------------------------
346
; We have a fragmented IP packet, but it's not the first
346
; We have a fragmented IP packet, but it's not the first
347
 
347
 
348
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Middle fragment packet received!\n"
348
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Middle fragment packet received!\n"
349
 
349
 
350
        call    IPv4_find_fragment_slot
350
        call    IPv4_find_fragment_slot
351
        cmp     esi, -1
351
        cmp     esi, -1
352
        je      .dump
352
        je      .dump
353
 
353
 
354
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; Reset the ttl
354
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; Reset the ttl
355
        mov     esi, [esi + IPv4_FRAGMENT_slot.ptr]
355
        mov     esi, [esi + IPv4_FRAGMENT_slot.ptr]
356
        or      edi, -1
356
        or      edi, -1
357
  .find_last_entry:                                             ; The following routine will try to find the last entry
357
  .find_last_entry:                                             ; The following routine will try to find the last entry
358
        cmp     edi, [esi + IPv4_FRAGMENT_entry.PrevPtr]
358
        cmp     edi, [esi + IPv4_FRAGMENT_entry.PrevPtr]
359
        jne     .destroy_slot                                   ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
359
        jne     .destroy_slot                                   ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
360
        mov     edi, esi
360
        mov     edi, esi
361
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
361
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
362
        cmp     esi, -1
362
        cmp     esi, -1
363
        jne     .find_last_entry
363
        jne     .find_last_entry
364
                                                                ; We found the last entry (pointer is now in edi)
364
                                                                ; We found the last entry (pointer is now in edi)
365
                                                                ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
365
                                                                ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
366
 
366
 
367
        pop     eax                                             ; pointer to packet
367
        pop     eax                                             ; pointer to packet
368
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], eax        ; update pointer of previous entry to the new entry
368
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], eax        ; update pointer of previous entry to the new entry
369
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
369
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
370
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], edi
370
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], edi
371
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
371
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
372
 
372
 
373
        ret
373
        ret
374
 
374
 
375
 
375
 
376
;------------------------------------
376
;------------------------------------
377
; We have received the first fragment
377
; We have received the first fragment
378
 
378
 
379
  .is_first_fragment:
379
  .is_first_fragment:
380
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n"
380
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n"
381
                                                                ; try to locate a free slot..
381
                                                                ; try to locate a free slot..
382
        mov     ecx, IPv4_MAX_FRAGMENTS
382
        mov     ecx, IPv4_MAX_FRAGMENTS
383
        mov     esi, IPv4_FRAGMENT_LIST
383
        mov     esi, IPv4_FRAGMENT_LIST
384
  .find_free_slot:
384
  .find_free_slot:
385
        cmp     word [esi + IPv4_FRAGMENT_slot.ttl], 0
385
        cmp     word [esi + IPv4_FRAGMENT_slot.ttl], 0
386
        je      .found_free_slot
386
        je      .found_free_slot
387
        add     esi, sizeof.IPv4_FRAGMENT_slot
387
        add     esi, sizeof.IPv4_FRAGMENT_slot
388
        loop    .find_free_slot
388
        loop    .find_free_slot
389
        jmp     .dump                                           ; If no free slot was found, dump the packet
389
        jmp     .dump                                           ; If no free slot was found, dump the packet
390
 
390
 
391
  .found_free_slot:                                             ; We found a free slot, let's fill in the FRAGMENT_slot structure
391
  .found_free_slot:                                             ; We found a free slot, let's fill in the FRAGMENT_slot structure
392
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; RFC recommends 15 secs as ttl
392
        mov     [esi + IPv4_FRAGMENT_slot.ttl], 15              ; RFC recommends 15 secs as ttl
393
        mov     ax, [edx + IPv4_header.Identification]
393
        mov     ax, [edx + IPv4_header.Identification]
394
        mov     [esi + IPv4_FRAGMENT_slot.id], ax
394
        mov     [esi + IPv4_FRAGMENT_slot.id], ax
395
        mov     eax, [edx + IPv4_header.SourceAddress]
395
        mov     eax, [edx + IPv4_header.SourceAddress]
396
        mov     [esi + IPv4_FRAGMENT_slot.SrcIP], eax
396
        mov     [esi + IPv4_FRAGMENT_slot.SrcIP], eax
397
        mov     eax, [edx + IPv4_header.DestinationAddress]
397
        mov     eax, [edx + IPv4_header.DestinationAddress]
398
        mov     [esi + IPv4_FRAGMENT_slot.DstIP], eax
398
        mov     [esi + IPv4_FRAGMENT_slot.DstIP], eax
399
        pop     eax
399
        pop     eax
400
        mov     [esi + IPv4_FRAGMENT_slot.ptr], eax
400
        mov     [esi + IPv4_FRAGMENT_slot.ptr], eax
401
                                                                ; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
401
                                                                ; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
402
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
402
        mov     [eax + IPv4_FRAGMENT_entry.NextPtr], -1
403
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], -1
403
        mov     [eax + IPv4_FRAGMENT_entry.PrevPtr], -1
404
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
404
        mov     [eax + IPv4_FRAGMENT_entry.Owner], ebx
405
 
405
 
406
        ret
406
        ret
407
 
407
 
408
 
408
 
409
;-----------------------------------
409
;-----------------------------------
410
; We have received the last fragment
410
; We have received the last fragment
411
 
411
 
412
  .is_last_fragment:
412
  .is_last_fragment:
413
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Last fragment packet received!\n"
413
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Last fragment packet received!\n"
414
 
414
 
415
        call    IPv4_find_fragment_slot
415
        call    IPv4_find_fragment_slot
416
        cmp     esi, -1
416
        cmp     esi, -1
417
        je      .dump
417
        je      .dump
418
 
418
 
419
        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
419
        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
420
        push    esi
420
        push    esi
421
        xor     eax, eax
421
        xor     eax, eax
422
        or      edi, -1
422
        or      edi, -1
423
 
423
 
424
  .count_bytes:
424
  .count_bytes:
425
        cmp     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
425
        cmp     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
426
        jne     .destroy_slot_pop                                                       ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
426
        jne     .destroy_slot_pop                                                       ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
427
        mov     cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]        ; Add total length
427
        mov     cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]        ; Add total length
428
        xchg    cl, ch
428
        xchg    cl, ch
429
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
429
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
430
        add     ax, cx
430
        add     ax, cx
431
        movzx   cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]      ; Sub Header length
431
        movzx   cx, [esi + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]      ; Sub Header length
432
        and     cx, 0x000F
432
        and     cx, 0x000F
433
        shl     cx, 2
433
        shl     cx, 2
434
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx
434
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx
435
        sub     ax, cx
435
        sub     ax, cx
436
        mov     edi, esi
436
        mov     edi, esi
437
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
437
        mov     esi, [esi + IPv4_FRAGMENT_entry.NextPtr]
438
        cmp     esi, -1
438
        cmp     esi, -1
439
        jne     .count_bytes
439
        jne     .count_bytes
440
 
440
 
441
        mov     esi, [esp+4]
441
        mov     esi, [esp+4]
442
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], esi                                ; Add this packet to the chain, this simplifies the following code
442
        mov     [edi + IPv4_FRAGMENT_entry.NextPtr], esi                                ; Add this packet to the chain, this simplifies the following code
443
        mov     [esi + IPv4_FRAGMENT_entry.NextPtr], -1
443
        mov     [esi + IPv4_FRAGMENT_entry.NextPtr], -1
444
        mov     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
444
        mov     [esi + IPv4_FRAGMENT_entry.PrevPtr], edi
445
        mov     [esi + IPv4_FRAGMENT_entry.Owner], ebx
445
        mov     [esi + IPv4_FRAGMENT_entry.Owner], ebx
446
 
446
 
447
        mov     cx, [edx + IPv4_header.TotalLength]                                     ; Note: This time we dont substract Header length
447
        mov     cx, [edx + IPv4_header.TotalLength]                                     ; Note: This time we dont substract Header length
448
        xchg    cl, ch
448
        xchg    cl, ch
449
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
449
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
450
        add     ax, cx
450
        add     ax, cx
451
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Received data size=%u\n", eax
451
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Received data size=%u\n", eax
452
 
452
 
453
        push    eax
453
        push    eax
454
        mov     ax, [edx + IPv4_header.FlagsAndFragmentOffset]
454
        mov     ax, [edx + IPv4_header.FlagsAndFragmentOffset]
455
        xchg    al, ah
455
        xchg    al, ah
456
        shl     ax, 3
456
        shl     ax, 3
457
        add     cx, ax
457
        add     cx, ax
458
        pop     eax
458
        pop     eax
459
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Fragment size=%u\n", ecx
459
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Fragment size=%u\n", ecx
460
 
460
 
461
        cmp     ax, cx
461
        cmp     ax, cx
462
        jne     .destroy_slot_pop
462
        jne     .destroy_slot_pop
463
 
463
 
464
        push    eax
464
        push    eax
465
        push    eax
465
        push    eax
466
        call    kernel_alloc
466
        call    kernel_alloc
467
        test    eax, eax
467
        test    eax, eax
468
        je      .destroy_slot_pop                                                       ; If we dont have enough space to allocate the buffer, discard all packets in slot
468
        je      .destroy_slot_pop                                                       ; If we dont have enough space to allocate the buffer, discard all packets in slot
469
        mov     edx, [esp+4]                                                            ; Get pointer to first fragment entry back in edx
469
        mov     edx, [esp+4]                                                            ; Get pointer to first fragment entry back in edx
470
 
470
 
471
  .rebuild_packet_loop:
471
  .rebuild_packet_loop:
472
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
472
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
473
        xchg    cl, ch                                                                  ;  intel byte order
473
        xchg    cl, ch                                                                  ;  intel byte order
474
        shl     cx, 3                                                                   ;   multiply by 8 and clear first 3 bits
474
        shl     cx, 3                                                                   ;   multiply by 8 and clear first 3 bits
475
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx
475
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx
476
 
476
 
477
        lea     edi, [eax + ecx]                                                        ; Notice that edi will be equal to eax for first fragment
477
        lea     edi, [eax + ecx]                                                        ; Notice that edi will be equal to eax for first fragment
478
        movzx   ebx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]     ; Find header size (in ebx) of fragment
478
        movzx   ebx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.VersionAndIHL]     ; Find header size (in ebx) of fragment
479
        and     bx, 0x000F                                                              ;
479
        and     bx, 0x000F                                                              ;
480
        shl     bx, 2                                                                   ;
480
        shl     bx, 2                                                                   ;
481
 
481
 
482
        lea     esi, [edx + sizeof.IPv4_FRAGMENT_entry]                                 ; Set esi to the correct begin of fragment
482
        lea     esi, [edx + sizeof.IPv4_FRAGMENT_entry]                                 ; Set esi to the correct begin of fragment
483
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]       ; Calculate total length of fragment
483
        movzx   ecx, [edx + sizeof.IPv4_FRAGMENT_entry + IPv4_header.TotalLength]       ; Calculate total length of fragment
484
        xchg    cl, ch                                                                  ;  intel byte order
484
        xchg    cl, ch                                                                  ;  intel byte order
485
 
485
 
486
        cmp     edi, eax                                                                ; Is this packet the first fragment ?
486
        cmp     edi, eax                                                                ; Is this packet the first fragment ?
487
        je      .first_fragment
487
        je      .first_fragment
488
        sub     cx, bx                                                                  ; If not, dont copy the header
488
        sub     cx, bx                                                                  ; If not, dont copy the header
489
        add     esi, ebx                                                                ;
489
        add     esi, ebx                                                                ;
490
  .first_fragment:
490
  .first_fragment:
491
 
491
 
492
 
492
 
493
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Copying %u bytes from 0x%x to 0x%x\n", ecx, esi, edi
493
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Copying %u bytes from 0x%x to 0x%x\n", ecx, esi, edi
494
        push    cx                                                                      ; First copy dword-wise, then byte-wise
494
        push    cx                                                                      ; First copy dword-wise, then byte-wise
495
        shr     cx, 2                                                                   ;
495
        shr     cx, 2                                                                   ;
496
        rep movsd                                                                       ;
496
        rep movsd                                                                       ;
497
        pop     cx                                                                      ;
497
        pop     cx                                                                      ;
498
        and     cx, 3                                                                   ;
498
        and     cx, 3                                                                   ;
499
        rep movsb                                                                       ;
499
        rep movsb                                                                       ;
500
 
500
 
501
        push    eax
501
        push    eax
502
        push    [edx + IPv4_FRAGMENT_entry.Owner]                                       ; we need to remeber the owner, in case this is the last packet
502
        push    [edx + IPv4_FRAGMENT_entry.Owner]                                       ; we need to remeber the owner, in case this is the last packet
503
        push    [edx + IPv4_FRAGMENT_entry.NextPtr]                                     ; Set edx to the next pointer
503
        push    [edx + IPv4_FRAGMENT_entry.NextPtr]                                     ; Set edx to the next pointer
504
        push    edx                                                                     ; Push pointer to fragment onto stack
504
        push    edx                                                                     ; Push pointer to fragment onto stack
505
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Next Fragment: 0x%x\n", edx
505
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Next Fragment: 0x%x\n", edx
506
        call    NET_BUFF_free                                                          ; free the previous fragment buffer (this uses the value from stack)
506
        call    NET_BUFF_free                                                          ; free the previous fragment buffer (this uses the value from stack)
507
        pop     edx ebx eax
507
        pop     edx ebx eax
508
        cmp     edx, -1                                                                 ; Check if it is last fragment in chain
508
        cmp     edx, -1                                                                 ; Check if it is last fragment in chain
509
        jne     .rebuild_packet_loop
509
        jne     .rebuild_packet_loop
510
 
510
 
511
        pop     ecx
511
        pop     ecx
512
        xchg    cl, ch
512
        xchg    cl, ch
513
        mov     edx, eax
513
        mov     edx, eax
514
        mov     [edx + IPv4_header.TotalLength], cx
514
        mov     [edx + IPv4_header.TotalLength], cx
515
        add     esp, 12
515
        add     esp, 12
516
        xchg    cl, ch
516
        xchg    cl, ch
517
        push    ecx edx                 ; size and pointer
517
        push    ecx edx                 ; size and pointer
518
        jmp     .handle_it              ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
518
        jmp     .handle_it              ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
519
 
519
 
520
  .destroy_slot_pop:
520
  .destroy_slot_pop:
521
        add     esp, 4
521
        add     esp, 4
522
  .destroy_slot:
522
  .destroy_slot:
523
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Destroy fragment slot!\n"
523
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Destroy fragment slot!\n"
524
        ; TODO!
524
        ; TODO!
525
        jmp     .dump
525
        jmp     .dump
526
 
526
 
527
 
527
 
528
 
528
 
529
 
529
 
530
 
530
 
531
;-----------------------------------------------------------------
531
;-----------------------------------------------------------------
532
;
532
;
533
; find fragment slot
533
; find fragment slot
534
;
534
;
535
; IN: pointer to fragmented packet in edx
535
; IN: pointer to fragmented packet in edx
536
; OUT: pointer to slot in esi, -1 on error
536
; OUT: pointer to slot in esi, -1 on error
537
;
537
;
538
;-----------------------------------------------------------------
538
;-----------------------------------------------------------------
539
align 4
539
align 4
540
IPv4_find_fragment_slot:
540
IPv4_find_fragment_slot:
541
 
541
 
542
;;; TODO: the RFC says we should check protocol number too
542
;;; TODO: the RFC says we should check protocol number too
543
 
543
 
544
        push    eax ebx ecx edx
544
        push    eax ebx ecx edx
545
        mov     ax, [edx + IPv4_header.Identification]
545
        mov     ax, [edx + IPv4_header.Identification]
546
        mov     ecx, IPv4_MAX_FRAGMENTS
546
        mov     ecx, IPv4_MAX_FRAGMENTS
547
        mov     esi, IPv4_FRAGMENT_LIST
547
        mov     esi, IPv4_FRAGMENT_LIST
548
        mov     ebx, [edx + IPv4_header.SourceAddress]
548
        mov     ebx, [edx + IPv4_header.SourceAddress]
549
        mov     edx, [edx + IPv4_header.DestinationAddress]
549
        mov     edx, [edx + IPv4_header.DestinationAddress]
550
  .find_slot:
550
  .find_slot:
551
        cmp     [esi + IPv4_FRAGMENT_slot.id], ax
551
        cmp     [esi + IPv4_FRAGMENT_slot.id], ax
552
        jne     .try_next
552
        jne     .try_next
553
        cmp     [esi + IPv4_FRAGMENT_slot.SrcIP], ebx
553
        cmp     [esi + IPv4_FRAGMENT_slot.SrcIP], ebx
554
        jne     .try_next
554
        jne     .try_next
555
        cmp     [esi + IPv4_FRAGMENT_slot.DstIP], edx
555
        cmp     [esi + IPv4_FRAGMENT_slot.DstIP], edx
556
        je      .found_slot
556
        je      .found_slot
557
  .try_next:
557
  .try_next:
558
        add     esi, sizeof.IPv4_FRAGMENT_slot
558
        add     esi, sizeof.IPv4_FRAGMENT_slot
559
        loop    .find_slot
559
        loop    .find_slot
560
 
560
 
561
        or      esi, -1
561
        or      esi, -1
562
  .found_slot:
562
  .found_slot:
563
        pop     edx ecx ebx eax
563
        pop     edx ecx ebx eax
564
        ret
564
        ret
565
 
565
 
566
 
566
 
567
;------------------------------------------------------------------
567
;------------------------------------------------------------------
568
;
568
;
569
; IPv4_output
569
; IPv4_output
570
;
570
;
571
; IN:   eax = Destination IP
571
; IN:   eax = Destination IP
-
 
572
;       ebx = device ptr (or 0 to let IP layer decide)
572
;       ecx = data length
573
;       ecx = data length
573
;       edx = Source IP
574
;       edx = Source IP
574
;        di = TTL shl 8 + protocol
575
;        di = TTL shl 8 + protocol
575
;
576
;
576
; OUT:  eax = pointer to buffer start / 0 on error
577
; OUT:  eax = pointer to buffer start / 0 on error
577
;       ebx = device ptr (send packet through this device)
578
;       ebx = device ptr (send packet through this device)
578
;       ecx = data length
579
;       ecx = data length
579
;       edx = size of complete frame
580
;       edx = size of complete frame
580
;       edi = start of IPv4 payload
581
;       edi = start of IPv4 payload
581
;
582
;
582
;------------------------------------------------------------------
583
;------------------------------------------------------------------
583
align 4
584
align 4
584
IPv4_output:
585
IPv4_output:
585
 
586
 
586
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u ip=0x%x\n", ecx, eax
587
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u ip=0x%x\n", ecx, eax
587
 
588
 
588
        cmp     ecx, 65500              ; Max IPv4 packet size
589
        cmp     ecx, 65500              ; Max IPv4 packet size
589
        ja      .too_large
590
        ja      .too_large
590
 
591
 
591
        push    ecx di eax
592
        push    ecx di eax
592
        call    IPv4_route              ; outputs device number in edi, dest ip in eax, source IP in edx
593
        call    IPv4_route              ; outputs device number in edi, dest ip in eax, source IP in edx
593
        push    edx
594
        push    edx
594
        test    edi, edi
595
        test    edi, edi
595
        jz      .loopback
596
        jz      .loopback
596
 
597
 
597
        call    ARP_IP_to_MAC
598
        call    ARP_IP_to_MAC
598
        test    eax, 0xffff0000         ; error bits
599
        test    eax, 0xffff0000         ; error bits
599
        jnz     .arp_error
600
        jnz     .arp_error
600
        push    ebx                     ; push the mac onto the stack
601
        push    ebx                     ; push the mac onto the stack
601
        push    ax
602
        push    ax
602
 
603
 
603
        inc     [IPv4_packets_tx + edi]   ; update stats
604
        inc     [IPv4_packets_tx + edi]   ; update stats
604
 
605
 
605
        mov     ax, ETHER_PROTO_IPv4
606
        mov     ax, ETHER_PROTO_IPv4
606
        mov     ebx, [NET_DRV_LIST + edi]
607
        mov     ebx, [NET_DRV_LIST + edi]
607
        mov     ecx, [esp + 6 + 8 + 2]
608
        mov     ecx, [esp + 6 + 8 + 2]
608
        add     ecx, sizeof.IPv4_header
609
        add     ecx, sizeof.IPv4_header
609
        mov     edx, esp
610
        mov     edx, esp
610
        call    ETH_output
611
        call    ETH_output
611
        jz      .eth_error
612
        jz      .eth_error
612
        add     esp, 6                  ; pop the mac out of the stack
613
        add     esp, 6                  ; pop the mac out of the stack
613
 
614
 
614
  .continue:
615
  .continue:
615
        xchg    cl, ch                                  ; internet byte order
616
        xchg    cl, ch                                  ; internet byte order
616
        mov     [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
617
        mov     [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
617
        mov     [edi + IPv4_header.TypeOfService], 0    ; nothing special, just plain ip packet
618
        mov     [edi + IPv4_header.TypeOfService], 0    ; nothing special, just plain ip packet
618
        mov     [edi + IPv4_header.TotalLength], cx
619
        mov     [edi + IPv4_header.TotalLength], cx
619
        mov     [edi + IPv4_header.Identification], 0   ; fragment id: FIXME
620
        mov     [edi + IPv4_header.Identification], 0   ; fragment id: FIXME
620
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], 0
621
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], 0
621
 
622
 
622
        mov     [edi + IPv4_header.HeaderChecksum], 0
623
        mov     [edi + IPv4_header.HeaderChecksum], 0
623
        popd    [edi + IPv4_header.SourceAddress]
624
        popd    [edi + IPv4_header.SourceAddress]
624
        popd    [edi + IPv4_header.DestinationAddress]
625
        popd    [edi + IPv4_header.DestinationAddress]
625
 
626
 
626
        pop     word[edi + IPv4_header.TimeToLive]      ; ttl shl 8 + protocol
627
        pop     word[edi + IPv4_header.TimeToLive]      ; ttl shl 8 + protocol
627
;               [edi + IPv4_header.Protocol]
628
;               [edi + IPv4_header.Protocol]
628
 
629
 
629
        pop     ecx
630
        pop     ecx
630
 
631
 
631
        IPv4_checksum edi
632
        IPv4_checksum edi
632
        add     edi, sizeof.IPv4_header
633
        add     edi, sizeof.IPv4_header
633
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: success!\n"
634
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: success!\n"
634
        ret
635
        ret
635
 
636
 
636
  .eth_error:
637
  .eth_error:
637
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ethernet error\n"
638
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ethernet error\n"
638
        add     esp, 3*4+2+6
639
        add     esp, 3*4+2+6
639
        xor     eax, eax
640
        xor     eax, eax
640
        ret
641
        ret
641
 
642
 
642
  .arp_error:
643
  .arp_error:
643
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
644
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
644
        add     esp, 3*4+2
645
        add     esp, 3*4+2
645
        xor     eax, eax
646
        xor     eax, eax
646
        ret
647
        ret
647
 
648
 
648
  .too_large:
649
  .too_large:
649
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n"
650
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n"
650
        xor     eax, eax
651
        xor     eax, eax
651
        ret
652
        ret
652
 
653
 
653
  .loopback:
654
  .loopback:
654
        mov     dword [esp], eax                        ; set source IP to dest IP
655
        mov     dword [esp], eax                        ; set source IP to dest IP
655
        mov     ecx, [esp + 10]
656
        mov     ecx, [esp + 10]
656
        add     ecx, sizeof.IPv4_header
657
        add     ecx, sizeof.IPv4_header
657
        mov     edi, AF_INET4
658
        mov     edi, AF_INET4
658
        call    LOOP_output
659
        call    LOOP_output
659
        jmp     .continue
660
        jmp     .continue
660
 
661
 
661
 
662
 
662
 
663
 
663
 
664
 
664
;------------------------------------------------------------------
665
;------------------------------------------------------------------
665
;
666
;
666
; IPv4_output_raw
667
; IPv4_output_raw
667
;
668
;
668
; IN: eax = socket ptr
669
; IN: eax = socket ptr
669
;     ecx = data length
670
;     ecx = data length
670
;     esi = data ptr
671
;     esi = data ptr
671
;
672
;
672
; OUT: eax = -1 on error
673
; OUT: eax = -1 on error
673
;
674
;
674
;------------------------------------------------------------------
675
;------------------------------------------------------------------
675
align 4
676
align 4
676
IPv4_output_raw:
677
IPv4_output_raw:
677
 
678
 
678
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
679
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
679
 
680
 
680
        cmp     ecx, 1480               ;;;;; FIXME
681
        cmp     ecx, 1480               ;;;;; FIXME
681
        ja      .too_large
682
        ja      .too_large
682
 
683
 
683
        sub     esp, 8
684
        sub     esp, 8
684
        push    esi eax
685
        push    esi eax
685
 
686
 
686
        call    IPv4_route
687
        call    IPv4_route
687
        call    ARP_IP_to_MAC
688
        call    ARP_IP_to_MAC
688
 
689
 
689
        test    eax, 0xffff0000         ; error bits
690
        test    eax, 0xffff0000         ; error bits
690
        jnz     .arp_error
691
        jnz     .arp_error
691
 
692
 
692
        push    ebx                     ; push the mac
693
        push    ebx                     ; push the mac
693
        push    ax
694
        push    ax
694
 
695
 
695
        inc     [IPv4_packets_tx + 4*edi]
696
        inc     [IPv4_packets_tx + 4*edi]
696
        mov     ax, ETHER_PROTO_IPv4
697
        mov     ax, ETHER_PROTO_IPv4
697
        mov     ebx, [NET_DRV_LIST + 4*edi]
698
        mov     ebx, [NET_DRV_LIST + 4*edi]
698
        mov     ecx, [esp + 6 + 4]
699
        mov     ecx, [esp + 6 + 4]
699
        add     ecx, sizeof.IPv4_header
700
        add     ecx, sizeof.IPv4_header
700
        mov     edx, esp
701
        mov     edx, esp
701
        call    ETH_output
702
        call    ETH_output
702
        jz      .error
703
        jz      .error
703
        add     esp, 6  ; pop the mac
704
        add     esp, 6  ; pop the mac
704
 
705
 
705
        mov     dword[esp+4+4], edx
706
        mov     dword[esp+4+4], edx
706
        mov     dword[esp+4+4+4], eax
707
        mov     dword[esp+4+4+4], eax
707
 
708
 
708
        pop     eax esi
709
        pop     eax esi
709
;; todo: check socket options if we should add header, or just compute checksum
710
;; todo: check socket options if we should add header, or just compute checksum
710
 
711
 
711
        push    edi ecx
712
        push    edi ecx
712
        rep movsb
713
        rep movsb
713
        pop     ecx edi
714
        pop     ecx edi
714
 
715
 
715
;        [edi + IPv4_header.VersionAndIHL]              ; IPv4, normal length (no Optional header)
716
;        [edi + IPv4_header.VersionAndIHL]              ; IPv4, normal length (no Optional header)
716
;        [edi + IPv4_header.TypeOfService]              ; nothing special, just plain ip packet
717
;        [edi + IPv4_header.TypeOfService]              ; nothing special, just plain ip packet
717
;        [edi + IPv4_header.TotalLength]
718
;        [edi + IPv4_header.TotalLength]
718
;        [edi + IPv4_header.TotalLength]                ; internet byte order
719
;        [edi + IPv4_header.TotalLength]                ; internet byte order
719
;        [edi + IPv4_header.FlagsAndFragmentOffset]
720
;        [edi + IPv4_header.FlagsAndFragmentOffset]
720
 
721
 
721
        mov     [edi + IPv4_header.HeaderChecksum], 0
722
        mov     [edi + IPv4_header.HeaderChecksum], 0
722
 
723
 
723
;        [edi + IPv4_header.TimeToLive]                 ; ttl shl 8 + protocol
724
;        [edi + IPv4_header.TimeToLive]                 ; ttl shl 8 + protocol
724
;        [edi + IPv4_header.Protocol]
725
;        [edi + IPv4_header.Protocol]
725
;        [edi + IPv4_header.Identification]             ; fragment id
726
;        [edi + IPv4_header.Identification]             ; fragment id
726
;        [edi + IPv4_header.SourceAddress]
727
;        [edi + IPv4_header.SourceAddress]
727
;        [edi + IPv4_header.DestinationAddress]
728
;        [edi + IPv4_header.DestinationAddress]
728
 
729
 
729
        IPv4_checksum edi                       ;;;; todo: checksum for IP packet with options!
730
        IPv4_checksum edi                       ;;;; todo: checksum for IP packet with options!
730
        add     edi, sizeof.IPv4_header
731
        add     edi, sizeof.IPv4_header
731
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
732
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
732
        call    [ebx + NET_DEVICE.transmit]
733
        call    [ebx + NET_DEVICE.transmit]
733
        ret
734
        ret
734
 
735
 
735
  .error:
736
  .error:
736
        add     esp, 6
737
        add     esp, 6
737
  .arp_error:
738
  .arp_error:
738
        add     esp, 8+4+4
739
        add     esp, 8+4+4
739
  .too_large:
740
  .too_large:
740
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
741
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
741
        or      eax, -1
742
        or      eax, -1
742
        ret
743
        ret
743
 
744
 
744
 
745
 
745
;--------------------------------------------------------
746
;--------------------------------------------------------
746
;
747
;
747
;
748
;
748
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
749
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
749
;     esi = pointer to ip header in that buffer
750
;     esi = pointer to ip header in that buffer
750
;     ecx = max size of fragments
751
;     ecx = max size of fragments
751
;
752
;
752
; OUT: /
753
; OUT: /
753
;
754
;
754
;--------------------------------------------------------
755
;--------------------------------------------------------
755
 
756
 
756
align 4
757
align 4
757
IPv4_fragment:
758
IPv4_fragment:
758
 
759
 
759
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
760
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
760
 
761
 
761
        and     ecx, not 111b   ; align 4
762
        and     ecx, not 111b   ; align 4
762
 
763
 
763
        cmp     ecx, sizeof.IPv4_header + 8     ; must be able to put at least 8 bytes
764
        cmp     ecx, sizeof.IPv4_header + 8     ; must be able to put at least 8 bytes
764
        jb      .err2
765
        jb      .err2
765
 
766
 
766
        push    esi ecx
767
        push    esi ecx
767
        mov     eax, [esi + IPv4_header.DestinationAddress]
768
        mov     eax, [esi + IPv4_header.DestinationAddress]
768
        call    ARP_IP_to_MAC
769
        call    ARP_IP_to_MAC
769
        pop     ecx esi
770
        pop     ecx esi
770
        cmp     eax, -1
771
        cmp     eax, -1
771
        jz      .err2
772
        jz      .err2
772
 
773
 
773
        push    ebx
774
        push    ebx
774
        push    ax
775
        push    ax
775
 
776
 
776
        mov     ebx, [NET_DRV_LIST]
777
        mov     ebx, [NET_DRV_LIST]
777
        lea     eax, [ebx + ETH_DEVICE.mac]
778
        lea     eax, [ebx + ETH_DEVICE.mac]
778
        push    eax
779
        push    eax
779
 
780
 
780
 
781
 
781
        push    esi                             ; ptr to ip header
782
        push    esi                             ; ptr to ip header
782
        sub     ecx, sizeof.IPv4_header         ; substract header size
783
        sub     ecx, sizeof.IPv4_header         ; substract header size
783
        push    ecx                             ; max data size
784
        push    ecx                             ; max data size
784
        push    dword 0                         ; offset
785
        push    dword 0                         ; offset
785
 
786
 
786
  .new_fragment:
787
  .new_fragment:
787
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
788
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
788
 
789
 
789
        mov     ax, ETHER_PROTO_IPv4
790
        mov     ax, ETHER_PROTO_IPv4
790
        lea     ebx, [esp + 4*4]
791
        lea     ebx, [esp + 4*4]
791
        call    ETH_output
792
        call    ETH_output
792
        jz      .err
793
        jz      .err
793
 
794
 
794
; copy header
795
; copy header
795
        mov     esi, [esp + 2*4]
796
        mov     esi, [esp + 2*4]
796
        mov     ecx, 5  ; 5 dwords: TODO: use IHL field of the header!
797
        mov     ecx, 5  ; 5 dwords: TODO: use IHL field of the header!
797
        rep movsd
798
        rep movsd
798
 
799
 
799
; copy data
800
; copy data
800
        mov     esi, [esp + 2*4]
801
        mov     esi, [esp + 2*4]
801
        add     esi, sizeof.IPv4_header
802
        add     esi, sizeof.IPv4_header
802
        add     esi, [esp]      ; offset
803
        add     esi, [esp]      ; offset
803
 
804
 
804
        mov     ecx, [esp + 1*4]
805
        mov     ecx, [esp + 1*4]
805
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx
806
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx
806
        rep movsb
807
        rep movsb
807
 
808
 
808
; now, correct header
809
; now, correct header
809
        mov     ecx, [esp + 1*4]
810
        mov     ecx, [esp + 1*4]
810
        add     ecx, sizeof.IPv4_header
811
        add     ecx, sizeof.IPv4_header
811
        xchg    cl, ch
812
        xchg    cl, ch
812
        mov     [edi + IPv4_header.TotalLength], cx
813
        mov     [edi + IPv4_header.TotalLength], cx
813
 
814
 
814
        mov     ecx, [esp]              ; offset
815
        mov     ecx, [esp]              ; offset
815
        xchg    cl, ch
816
        xchg    cl, ch
816
 
817
 
817
;        cmp     dword[esp + 4*4], 0     ; last fragment?;<<<<<<
818
;        cmp     dword[esp + 4*4], 0     ; last fragment?;<<<<<<
818
;        je      .last_fragment
819
;        je      .last_fragment
819
        or      cx, 1 shl 2             ; more fragments
820
        or      cx, 1 shl 2             ; more fragments
820
;  .last_fragment:
821
;  .last_fragment:
821
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], cx
822
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], cx
822
 
823
 
823
        mov     [edi + IPv4_header.HeaderChecksum], 0
824
        mov     [edi + IPv4_header.HeaderChecksum], 0
824
 
825
 
825
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
826
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
826
        mov     ecx, [esp + 1*4]
827
        mov     ecx, [esp + 1*4]
827
 
828
 
828
        push    edx eax
829
        push    edx eax
829
        IPv4_checksum edi
830
        IPv4_checksum edi
830
 
831
 
831
        call    [ebx + NET_DEVICE.transmit]
832
        call    [ebx + NET_DEVICE.transmit]
832
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
833
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
833
 
834
 
834
        mov     ecx, [esp+4]
835
        mov     ecx, [esp+4]
835
        add     [esp], ecx
836
        add     [esp], ecx
836
 
837
 
837
        mov     ecx, [esp+3*4+6+4]      ; ptr to begin of buff
838
        mov     ecx, [esp+3*4+6+4]      ; ptr to begin of buff
838
        add     ecx, [esp+3*4+6+4+4]    ; buff size
839
        add     ecx, [esp+3*4+6+4+4]    ; buff size
839
        sub     ecx, [esp+2*4]          ; ptr to ip header
840
        sub     ecx, [esp+2*4]          ; ptr to ip header
840
        add     ecx, [esp]              ; offset
841
        add     ecx, [esp]              ; offset
841
 
842
 
842
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: %u bytes remaining\n", ecx
843
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: %u bytes remaining\n", ecx
843
 
844
 
844
        cmp     ecx, [esp+1*4]
845
        cmp     ecx, [esp+1*4]
845
        jae     .new_fragment
846
        jae     .new_fragment
846
 
847
 
847
        mov     [esp+4], ecx            ; set fragment size to remaining packet size
848
        mov     [esp+4], ecx            ; set fragment size to remaining packet size
848
        jmp     .new_fragment
849
        jmp     .new_fragment
849
 
850
 
850
      .err:
851
      .err:
851
        DEBUGF  DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
852
        DEBUGF  DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
852
      .done:
853
      .done:
853
        add     esp, 12 + 4 + 6
854
        add     esp, 12 + 4 + 6
854
      .err2:
855
      .err2:
855
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: dumping\n"
856
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: dumping\n"
856
        call    NET_BUFF_free
857
        call    NET_BUFF_free
857
        ret
858
        ret
858
 
859
 
859
 
860
 
860
 
861
 
861
;---------------------------------------------------------------------------
862
;---------------------------------------------------------------------------
862
;
863
;
863
; IPv4_route
864
; IPv4_route
864
;
865
;
865
; IN:   eax = Destination IP
866
; IN:   eax = Destination IP
-
 
867
;       ebx = outgoing device / 0
866
;       edx = Source IP
868
;       edx = Source IP
867
; OUT:  eax = Destination IP (or gateway IP)
869
; OUT:  eax = Destination IP (or gateway IP)
868
;       edx = Source IP
870
;       edx = Source IP
869
;       edi = device number*4
871
;       edi = device number*4
870
; DESTROYED:
872
; DESTROYED:
871
;       ecx
873
;       ecx
872
;
874
;
873
;---------------------------------------------------------------------------
875
;---------------------------------------------------------------------------
874
align 4
876
align 4
875
IPv4_route:     ; TODO: return error if no valid route found
877
IPv4_route:     ; TODO: return error if no valid route found
-
 
878
 
-
 
879
        test    ebx, ebx
-
 
880
        jnz     .got_device
876
 
881
 
877
        cmp     eax, 0xffffffff
882
        cmp     eax, 0xffffffff
878
        je      .broadcast
883
        je      .broadcast
879
 
884
 
880
        xor     edi, edi
885
        xor     edi, edi
881
  .loop:
886
  .loop:
882
        mov     ebx, [IP_LIST + edi]
887
        mov     ebx, [IP_LIST + edi]
883
        and     ebx, [SUBNET_LIST + edi]
888
        and     ebx, [SUBNET_LIST + edi]
884
        jz      .next
889
        jz      .next
885
        mov     ecx, eax
890
        mov     ecx, eax
886
        and     ecx, [SUBNET_LIST + edi]
891
        and     ecx, [SUBNET_LIST + edi]
887
        cmp     ebx, ecx
892
        cmp     ebx, ecx
888
        je      .got_it
893
        je      .got_it
889
  .next:
894
  .next:
890
        add     edi, 4
895
        add     edi, 4
891
        cmp     edi, 4*NET_DEVICES_MAX
896
        cmp     edi, 4*NET_DEVICES_MAX
892
        jb      .loop
897
        jb      .loop
893
 
898
 
894
        mov     eax, [GATEWAY_LIST + 4]         ; TODO: let user (or a user space daemon) configure default route
899
        mov     eax, [GATEWAY_LIST + 4]         ; TODO: let user (or a user space daemon) configure default route
895
  .broadcast:
900
  .broadcast:
896
        mov     edi, 4                          ; TODO: same as above
901
        mov     edi, 4                          ; TODO: same as above
897
  .got_it:
902
  .got_it:
898
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
903
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
899
        test    edx, edx
904
        test    edx, edx
900
        jnz     @f
905
        jnz     @f
901
        mov     edx, [IP_LIST + edi]
906
        mov     edx, [IP_LIST + edi]
902
  @@:
907
  @@:
903
 
908
 
904
        ret
909
        ret
-
 
910
 
-
 
911
  .got_device:
-
 
912
; Validate device ptr and convert to device number
-
 
913
        call    NET_ptr_to_num4
-
 
914
        cmp     edi, -1
-
 
915
        je      .fail
-
 
916
 
-
 
917
        mov     edx, [IP_LIST + edi]            ; Source IP
-
 
918
 
-
 
919
; Check if we should route to gateway or not
-
 
920
        mov     ebx, [IP_LIST + edi]
-
 
921
        and     ebx, [SUBNET_LIST + edi]
-
 
922
        mov     ecx, eax
-
 
923
        and     ecx, [SUBNET_LIST + edi]
-
 
924
        je      @f
-
 
925
        mov     eax, [GATEWAY_LIST + edi]
-
 
926
  @@:
-
 
927
        ret
-
 
928
 
-
 
929
  .fail:
-
 
930
        ret
905
 
931
 
906
 
932
 
907
 
933
 
908
;---------------------------------------------------------------------------
934
;---------------------------------------------------------------------------
909
;
935
;
910
; IPv4_get_frgmnt_num
936
; IPv4_get_frgmnt_num
911
;
937
;
912
; IN: /
938
; IN: /
913
; OUT: fragment number in ax
939
; OUT: fragment number in ax
914
;
940
;
915
;---------------------------------------------------------------------------
941
;---------------------------------------------------------------------------
916
align 4
942
align 4
917
IPv4_get_frgmnt_num:
943
IPv4_get_frgmnt_num:
918
        xor     ax, ax  ;;; TODO: replace this with real code
944
        xor     ax, ax  ;;; TODO: replace this with real code
919
 
945
 
920
        ret
946
        ret
921
 
947
 
922
 
948
 
923
;-----------------------------------------------------------------
949
;-----------------------------------------------------------------
924
;
950
;
925
; IPv4_connect
951
; IPv4_connect
926
;
952
;
927
;   IN: eax = socket pointer
953
;   IN: eax = socket pointer
928
;  OUT: eax = 0 ok / -1 error
954
;  OUT: eax = 0 ok / -1 error
929
;       ebx = error code
955
;       ebx = error code
930
;
956
;
931
;-------------------------
957
;-------------------------
932
align 4
958
align 4
933
IPv4_connect:
959
IPv4_connect:
934
 
960
 
935
        push    eax edx
961
        push    eax edx
936
        lea     ecx, [eax + SOCKET.mutex]
962
        lea     ecx, [eax + SOCKET.mutex]
937
        call    mutex_lock
963
        call    mutex_lock
938
        pop     edx eax
964
        pop     edx eax
939
 
965
 
940
; Fill in local IP
966
; Fill in local IP
941
        cmp     [eax + IP_SOCKET.LocalIP], 0
967
        cmp     [eax + IP_SOCKET.LocalIP], 0
942
        jne     @f
968
        jne     @f
943
        push    [IP_LIST + 4]                                   ; FIXME: use correct local IP
969
        push    [IP_LIST + 4]                                   ; FIXME: use correct local IP
944
        pop     [eax + IP_SOCKET.LocalIP]
970
        pop     [eax + IP_SOCKET.LocalIP]
945
 
971
 
946
; Fill in remote IP
972
; Fill in remote IP
947
        pushd   [edx + 4]
973
        pushd   [edx + 4]
948
        pop     [eax + IP_SOCKET.RemoteIP]
974
        pop     [eax + IP_SOCKET.RemoteIP]
949
 
975
 
950
; Set up data receiving queue
976
; Set up data receiving queue
951
        push    eax
977
        push    eax
952
        init_queue (eax + SOCKET_QUEUE_LOCATION)
978
        init_queue (eax + SOCKET_QUEUE_LOCATION)
953
        pop     eax
979
        pop     eax
954
 
980
 
955
        lea     ecx, [eax + SOCKET.mutex]
981
        lea     ecx, [eax + SOCKET.mutex]
956
        call    mutex_unlock
982
        call    mutex_unlock
957
 
983
 
958
        xor     eax, eax
984
        xor     eax, eax
959
        ret
985
        ret
960
 
986
 
961
 
987
 
962
;---------------------------------------------------------------------------
988
;---------------------------------------------------------------------------
963
;
989
;
964
; IPv4_API
990
; IPv4_API
965
;
991
;
966
; This function is called by system function 75
992
; This function is called by system function 75
967
;
993
;
968
; IN:  subfunction number in bl
994
; IN:  subfunction number in bl
969
;      device number in bh
995
;      device number in bh
970
;      ecx, edx, .. depends on subfunction
996
;      ecx, edx, .. depends on subfunction
971
;
997
;
972
; OUT:
998
; OUT:
973
;
999
;
974
;---------------------------------------------------------------------------
1000
;---------------------------------------------------------------------------
975
align 4
1001
align 4
976
IPv4_api:
1002
IPv4_api:
977
 
1003
 
978
        movzx   eax, bh
1004
        movzx   eax, bh
979
        shl     eax, 2
1005
        shl     eax, 2
980
 
1006
 
981
        and     ebx, 0x000000ff
1007
        and     ebx, 0x000000ff
982
        cmp     ebx, .number
1008
        cmp     ebx, .number
983
        ja      .error
1009
        ja      .error
984
        jmp     dword [.table + 4*ebx]
1010
        jmp     dword [.table + 4*ebx]
985
 
1011
 
986
  .table:
1012
  .table:
987
        dd      .packets_tx     ; 0
1013
        dd      .packets_tx     ; 0
988
        dd      .packets_rx     ; 1
1014
        dd      .packets_rx     ; 1
989
        dd      .read_ip        ; 2
1015
        dd      .read_ip        ; 2
990
        dd      .write_ip       ; 3
1016
        dd      .write_ip       ; 3
991
        dd      .read_dns       ; 4
1017
        dd      .read_dns       ; 4
992
        dd      .write_dns      ; 5
1018
        dd      .write_dns      ; 5
993
        dd      .read_subnet    ; 6
1019
        dd      .read_subnet    ; 6
994
        dd      .write_subnet   ; 7
1020
        dd      .write_subnet   ; 7
995
        dd      .read_gateway   ; 8
1021
        dd      .read_gateway   ; 8
996
        dd      .write_gateway  ; 9
1022
        dd      .write_gateway  ; 9
997
  .number = ($ - .table) / 4 - 1
1023
  .number = ($ - .table) / 4 - 1
998
 
1024
 
999
  .error:
1025
  .error:
1000
        mov     eax, -1
1026
        mov     eax, -1
1001
        ret
1027
        ret
1002
 
1028
 
1003
  .packets_tx:
1029
  .packets_tx:
1004
        mov     eax, [IPv4_packets_tx + eax]
1030
        mov     eax, [IPv4_packets_tx + eax]
1005
        ret
1031
        ret
1006
 
1032
 
1007
  .packets_rx:
1033
  .packets_rx:
1008
        mov     eax, [IPv4_packets_rx + eax]
1034
        mov     eax, [IPv4_packets_rx + eax]
1009
        ret
1035
        ret
1010
 
1036
 
1011
  .read_ip:
1037
  .read_ip:
1012
        mov     eax, [IP_LIST + eax]
1038
        mov     eax, [IP_LIST + eax]
1013
        ret
1039
        ret
1014
 
1040
 
1015
  .write_ip:
1041
  .write_ip:
1016
        mov     [IP_LIST + eax], ecx
1042
        mov     [IP_LIST + eax], ecx
1017
        mov     edi, eax                        ; device number, we'll need it for ARP
1043
        mov     edi, eax                        ; device number, we'll need it for ARP
1018
 
1044
 
1019
        ; pre-calculate the local broadcast address
1045
        ; pre-calculate the local broadcast address
1020
        mov     ebx, [SUBNET_LIST + eax]
1046
        mov     ebx, [SUBNET_LIST + eax]
1021
        not     ebx
1047
        not     ebx
1022
        or      ebx, ecx
1048
        or      ebx, ecx
1023
        mov     [BROADCAST_LIST + eax], ebx
1049
        mov     [BROADCAST_LIST + eax], ebx
1024
 
1050
 
1025
        mov     ebx, [NET_DRV_LIST + eax]
1051
        mov     ebx, [NET_DRV_LIST + eax]
1026
        mov     eax, [IP_LIST + eax]
1052
        mov     eax, [IP_LIST + eax]
1027
        call    ARP_output_request              ; now send a gratuitous ARP
1053
        call    ARP_output_request              ; now send a gratuitous ARP
1028
 
1054
 
1029
        call    NET_send_event
1055
        call    NET_send_event
1030
        xor     eax, eax
1056
        xor     eax, eax
1031
        ret
1057
        ret
1032
 
1058
 
1033
  .read_dns:
1059
  .read_dns:
1034
        mov     eax, [DNS_LIST + eax]
1060
        mov     eax, [DNS_LIST + eax]
1035
        ret
1061
        ret
1036
 
1062
 
1037
  .write_dns:
1063
  .write_dns:
1038
        mov     [DNS_LIST + eax], ecx
1064
        mov     [DNS_LIST + eax], ecx
1039
        call    NET_send_event
1065
        call    NET_send_event
1040
        xor     eax, eax
1066
        xor     eax, eax
1041
        ret
1067
        ret
1042
 
1068
 
1043
  .read_subnet:
1069
  .read_subnet:
1044
        mov     eax, [SUBNET_LIST + eax]
1070
        mov     eax, [SUBNET_LIST + eax]
1045
        ret
1071
        ret
1046
 
1072
 
1047
  .write_subnet:
1073
  .write_subnet:
1048
        mov     [SUBNET_LIST + eax], ecx
1074
        mov     [SUBNET_LIST + eax], ecx
1049
 
1075
 
1050
        ; pre-calculate the local broadcast address
1076
        ; pre-calculate the local broadcast address
1051
        mov     ebx, [IP_LIST + eax]
1077
        mov     ebx, [IP_LIST + eax]
1052
        not     ecx
1078
        not     ecx
1053
        or      ecx, ebx
1079
        or      ecx, ebx
1054
        mov     [BROADCAST_LIST + eax], ecx
1080
        mov     [BROADCAST_LIST + eax], ecx
1055
 
1081
 
1056
        call    NET_send_event
1082
        call    NET_send_event
1057
        xor     eax, eax
1083
        xor     eax, eax
1058
        ret
1084
        ret
1059
 
1085
 
1060
  .read_gateway:
1086
  .read_gateway:
1061
        mov     eax, [GATEWAY_LIST + eax]
1087
        mov     eax, [GATEWAY_LIST + eax]
1062
        ret
1088
        ret
1063
 
1089
 
1064
  .write_gateway:
1090
  .write_gateway:
1065
        mov     [GATEWAY_LIST + eax], ecx
1091
        mov     [GATEWAY_LIST + eax], ecx
1066
 
1092
 
1067
        call    NET_send_event
1093
        call    NET_send_event
1068
        xor     eax, eax
1094
        xor     eax, eax
1069
        ret
1095
        ret
1070
 
1096
 
1071
>
1097
>
1072
 
1098
 
1073
>
1099
>
1074
 
1100
 
1075
>
1101
>
1076
 
1102
 
1077
>
1103
>
1078
 
1104
 
1079
>
1105
>
1080
 
1106
 
1081
>
1107
>
1082
 
1108
 
1083
>
1109
>
1084
 
1110
 
1085
>
1111
>
1086
 
1112
 
1087
>
1113
>
1088
 
1114
 
1089
>
1115
>
1090
 
1116
 
1091
>
1117
>
1092
 
1118
 
1093
>
1119
>
1094
 
1120
 
1095
>
1121
>
1096
 
1122
 
1097
>
1123
>
1098
 
1124
 
1099
>
1125
>
1100
 
1126
 
1101
>
1127
>
1102
 
1128
 
1103
>
1129
>
1104
 
1130
 
1105
>
1131
>
1106
 
1132
 
1107
>
1133
>
1108
 
1134
 
1109
>
1135
>
1110
 
1136
 
1111
>
1137
>
1112
 
1138
 
1113
>
1139
>
1114
 
1140
 
1115
>
1141
>
1116
 
1142
 
1117
>
1143
>
1118
 
1144
 
1119
>
1145
>
1120
 
1146
 
1121
>
1147
>
1122
 
1148
 
1123
>
1149
>
1124
 
1150
 
1125
>
1151
>
1126
 
1152
 
1127
>
1153
>
1128
;>
1154
;>
1129
;>
1155
;>
1130
;>
1156
;>
1131
;>
1157
;>
1132
;>
1158
;>
1133
;>
1159
;>