~mirabilos/aranym/trunk

« back to all changes in this revision

Viewing changes to src/Unix/MacOSX/ethernet_macosx.cpp

  • Committer: philipp
  • Date: 2013-04-19 21:20:45 UTC
  • Revision ID: philipp-20130419212045-vulhgvccb5nxi7mi
Fixed memory leak on Atari side caused by BPF ethernet driver

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
 
57
57
#define ETH_HELPER "bpf_helper"
58
58
 
59
 
/* BPF filter program:
60
 
 -allow all ARP messages
61
 
 -allow only IP messages for specific IP address
62
 
 */
63
 
#define ETHERTYPE_IP    0x800
64
 
#define ETHERTYPE_ARP   0x806
65
 
#define IP_ADDR_PLH             0xAAAAAAAA
66
 
 
 
59
// BPF filter program to ensure only ethernet packets are processed which are destined to Atari MAC
67
60
struct bpf_insn ip_filter[] = {
68
 
        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),                 //      ld  P[12:2]
69
 
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 5),//      jeq 0x800, IP, NOK
70
 
        BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 26),                 // IP:  ld  P[26:4]
71
 
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IP_ADDR_PLH, 2, 0), //      jeq IP_ADDR, OK, 0
72
 
        BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 30),                 //      ld  P[30:4]
73
 
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IP_ADDR_PLH, 0, 1), //      jeq IP_ADDR, OK, NOK
 
61
        BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 0),                  //      ld  P[0:4]
 
62
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xAAAAAAAA, 0, 3),      //              jeq destMAC, CONT, NOK
 
63
        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 4),                  // CONT:ld  P[4:2]
 
64
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xAAAA, 0, 1),          //              jeq destMAC, OK, NOK
74
65
        BPF_STMT(BPF_RET+BPF_K, (u_int)-1),                 // OK:  ret -1
75
 
        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),                 // NOK: ld  P[12:2]
76
 
        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_ARP, 0, 1),//     jeq 0x806, 0, NOK
77
 
        BPF_STMT(BPF_RET+BPF_K, (u_int)-1),                 //      ret -1
78
66
        BPF_STMT(BPF_RET+BPF_K, 0),                         // NOK: ret 0
79
67
};
80
68
 
141
129
                        ip->dst_ip[0], ip->dst_ip[1], ip->dst_ip[2], ip->dst_ip[3],
142
130
                        ip->proto_type, ip->tot_len[0], ip->tot_len[1], tot_len, tot_len - sizeof(ip_packet)+1);
143
131
                
144
 
                for (unsigned char *ptr=&ip->data; ptr<(unsigned char*)&ip->data+tot_len; ptr++)
145
 
                        bug(">%*s\n",  tot_len-(sizeof(ip_packet)-1), &ip->data);
 
132
//              for (unsigned char *ptr=&ip->data; ptr<(unsigned char*)&ip->data+tot_len; ptr++)
 
133
//                      bug(">%*s\n",  tot_len-(sizeof(ip_packet)-1), &ip->data);
146
134
        }
147
135
}
148
136
 
272
260
                return false;
273
261
        }
274
262
        
275
 
        if (strstr(type, "nofilter") == NULL )
 
263
        // convert and validate MAC address from configuration
 
264
        // default MAC Address is just made up
 
265
        uint8 mac_addr[6] = {'\0','A','E','T','H', '0'+ethX };
 
266
        
 
267
        // convert user-defined MAC Address from string to 6 bytes array
 
268
        char *mac_text = bx_options.ethernet[ethX].mac_addr;
 
269
        bool format_OK = false;
 
270
        if (strlen(mac_text) == 2*6+5 && (mac_text[2] == ':' || mac_text[2] == '-')) {
 
271
                mac_text[2] = mac_text[5] = mac_text[8] = mac_text[11] = mac_text[14] = ':';
 
272
                int md[6] = {0, 0, 0, 0, 0, 0};
 
273
                int matched = sscanf(mac_text, "%02x:%02x:%02x:%02x:%02x:%02x",
 
274
                                                         &md[0], &md[1], &md[2], &md[3], &md[4], &md[5]);
 
275
                if (matched == 6) {
 
276
                        for(int i=0; i<6; i++)
 
277
                                mac_addr[i] = md[i];
 
278
                        format_OK = true;
 
279
                }
 
280
        }
 
281
        if (!format_OK) {
 
282
                panicbug("BPF(%d): Invalid MAC address: %s", ethX, mac_text);
 
283
                ::close(fd);
 
284
                return false;
 
285
        }
 
286
        
 
287
        // modify filter program to use specified IP address
 
288
        D(bug("BPF(%d): setting filter program for MAC address %s", ethX, mac_text));
 
289
        
 
290
        ip_filter[1].k = (mac_addr[0]<<24) | (mac_addr[1]<<16) | (mac_addr[2]<<8) | mac_addr[3];
 
291
        ip_filter[3].k = (mac_addr[4]<<8) | mac_addr[5];
 
292
        
 
293
        // Enable filter program
 
294
        if(ioctl(fd, BIOCSETF, &filter) == -1)
276
295
        {
277
 
                // convert and validate specified IP address
278
 
                in_addr_t ip_addr = inet_addr(bx_options.ethernet[ethX].ip_atari);
279
 
                if (ip_addr == INADDR_NONE) {
280
 
                        panicbug("BPF(%d): Invalid IP address specified: %s", ethX, bx_options.ethernet[ethX].ip_atari);
281
 
                        ::close(fd);
282
 
                        return false;
283
 
                }
284
 
                
285
 
                // modify filter program to use specified IP address
286
 
                D(bug("BPF(%d): setting filter program for IP address %s", ethX, bx_options.ethernet[ethX].ip_atari));
287
 
                
288
 
                ip_filter[3].k = ip_addr;
289
 
                ip_filter[5].k = ip_addr;
290
 
                
291
 
                // Enable filter program
292
 
                if(ioctl(fd, BIOCSETF, &filter) == -1)
293
 
                {
294
 
                        panicbug("BPF(%d): Unable to load filter program: %s", ethX, strerror(errno));
295
 
                        ::close(fd);
296
 
                        return false;
297
 
                }
298
 
                bug("BPF(%d): IP filter program loaded", ethX);
299
 
        }
300
 
        else {
301
 
                bug("BPF(%d): IP filter program skipped", ethX);
302
 
        }
 
296
                panicbug("BPF(%d): Unable to load filter program: %s", ethX, strerror(errno));
 
297
                ::close(fd);
 
298
                return false;
 
299
        }
 
300
        bug("BPF(%d): MAC filter program load", ethX);
303
301
        
304
302
        return true;
305
303
}