mrpd: indent (again?)
[profile/ivi/OpenAVB.git] / daemons / mrpd / mvrp.c
1 /****************************************************************************
2   Copyright (c) 2012, Intel Corporation
3   All rights reserved.
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions are met:
7
8    1. Redistributions of source code must retain the above copyright notice,
9       this list of conditions and the following disclaimer.
10
11    2. Redistributions in binary form must reproduce the above copyright
12       notice, this list of conditions and the following disclaimer in the
13       documentation and/or other materials provided with the distribution.
14
15    3. Neither the name of the Intel Corporation nor the names of its
16       contributors may be used to endorse or promote products derived from
17       this software without specific prior written permission.
18
19   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29   POSSIBILITY OF SUCH DAMAGE.
30
31 ******************************************************************************/
32 /*
33  * MVRP protocol (part of 802.1Q-2011)
34  */
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <stddef.h>
39 #include <string.h>
40
41 #include "mrpd.h"
42 #include "mrp.h"
43 #include "mvrp.h"
44
45 int mvrp_send_notifications(struct mvrp_attribute *attrib, int notify);
46 int mvrp_txpdu(void);
47
48 unsigned char MVRP_CUSTOMER_BRIDGE_ADDR[] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x21 };     /* 81-00 */
49 unsigned char MVRP_PROVIDER_BRIDGE_ADDR[] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0D };     /* 88-A8 */
50
51 extern unsigned char STATION_ADDR[];
52
53 /* global variables */
54 SOCKET mvrp_socket;
55 struct mvrp_database *MVRP_db;
56
57 /* MVRP */
58
59 struct mvrp_attribute *mvrp_lookup(struct mvrp_attribute *rattrib)
60 {
61         struct mvrp_attribute *attrib;
62
63         attrib = MVRP_db->attrib_list;
64         while (NULL != attrib) {
65                 if (attrib->attribute == rattrib->attribute)
66                         return attrib;
67                 attrib = attrib->next;
68         }
69         return NULL;
70 }
71
72 int mvrp_add(struct mvrp_attribute *rattrib)
73 {
74         struct mvrp_attribute *attrib;
75         struct mvrp_attribute *attrib_tail;
76
77         /* XXX do a lookup first to guarantee uniqueness? */
78
79         attrib_tail = attrib = MVRP_db->attrib_list;
80
81         while (NULL != attrib) {
82                 if (attrib->attribute < rattrib->attribute) {
83                         /* possible tail insertion ... */
84                         if (NULL != attrib->next) {
85                                 attrib = attrib->next;
86                                 continue;
87                         }
88                         rattrib->next = attrib->next;
89                         rattrib->prev = attrib;
90                         attrib->next = rattrib;
91                         return 0;
92
93                 } else {
94                         /* head insertion ... */
95                         rattrib->next = attrib;
96                         rattrib->prev = attrib->prev;
97                         attrib->prev = rattrib;
98                         if (NULL != rattrib->prev)
99                                 rattrib->prev->next = rattrib;
100                         else
101                                 MVRP_db->attrib_list = rattrib;
102
103                         return 0;
104                 }
105                 attrib_tail = attrib;
106                 attrib = attrib->next;
107         }
108
109         /* if we are here we didn't need to stitch in a a sorted entry
110          * so append it onto the tail (if it exists)
111          */
112
113         if (NULL == attrib_tail) {
114                 rattrib->next = NULL;
115                 rattrib->prev = NULL;
116                 MVRP_db->attrib_list = rattrib;
117         } else {
118                 rattrib->next = NULL;
119                 rattrib->prev = attrib_tail;
120                 attrib_tail->next = rattrib;
121         }
122
123         return 0;
124 }
125
126 int mvrp_merge(struct mvrp_attribute *rattrib)
127 {
128         struct mvrp_attribute *attrib;
129
130         attrib = mvrp_lookup(rattrib);
131
132         if (NULL == attrib)
133                 return -1;      /* shouldn't happen */
134
135         /* primarily we update the last mac address state for diagnostics */
136         memcpy(attrib->registrar.macaddr, rattrib->registrar.macaddr, 6);
137         return 0;
138 }
139
140 int mvrp_event(int event, struct mvrp_attribute *rattrib)
141 {
142         struct mvrp_attribute *attrib;
143         int rc;
144
145         switch (event) {
146         case MRP_EVENT_LVATIMER:
147                 mrp_jointimer_stop(&(MVRP_db->mrp_db));
148                 /* update state */
149                 attrib = MVRP_db->attrib_list;
150
151                 while (NULL != attrib) {
152                         mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TXLA);
153                         mrp_registrar_fsm(&(attrib->registrar),
154                                           &(MVRP_db->mrp_db), MRP_EVENT_TXLA);
155                         attrib = attrib->next;
156                 }
157
158                 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_LVATIMER);
159
160                 mvrp_txpdu();
161                 break;
162         case MRP_EVENT_RLA:
163                 mrp_jointimer_stop(&(MVRP_db->mrp_db));
164                 /* update state */
165                 attrib = MVRP_db->attrib_list;
166
167                 while (NULL != attrib) {
168                         mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_RLA);
169                         mrp_registrar_fsm(&(attrib->registrar),
170                                           &(MVRP_db->mrp_db), MRP_EVENT_RLA);
171                         attrib = attrib->next;
172                 }
173
174                 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_RLA);
175
176                 break;
177         case MRP_EVENT_TX:
178                 mrp_jointimer_stop(&(MVRP_db->mrp_db));
179                 attrib = MVRP_db->attrib_list;
180
181                 while (NULL != attrib) {
182                         mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TX);
183                         attrib = attrib->next;
184                 }
185
186                 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_TX);
187
188                 mvrp_txpdu();
189                 break;
190         case MRP_EVENT_LVTIMER:
191                 mrp_lvtimer_stop(&(MVRP_db->mrp_db));
192                 attrib = MVRP_db->attrib_list;
193
194                 while (NULL != attrib) {
195                         mrp_registrar_fsm(&(attrib->registrar),
196                                           &(MVRP_db->mrp_db),
197                                           MRP_EVENT_LVTIMER);
198
199                         attrib = attrib->next;
200                 }
201                 break;
202         case MRP_EVENT_PERIODIC:
203                 attrib = MVRP_db->attrib_list;
204
205                 while (NULL != attrib) {
206                         mrp_applicant_fsm(&(attrib->applicant),
207                                           MRP_EVENT_PERIODIC);
208                         attrib = attrib->next;
209                 }
210                 break;
211         case MRP_EVENT_NEW:
212         case MRP_EVENT_JOIN:
213         case MRP_EVENT_RNEW:
214         case MRP_EVENT_RJOININ:
215         case MRP_EVENT_RJOINMT:
216         case MRP_EVENT_LV:
217         case MRP_EVENT_RIN:
218         case MRP_EVENT_RMT:
219         case MRP_EVENT_RLV:
220                 mrp_jointimer_start(&(MVRP_db->mrp_db));
221                 if (NULL == rattrib)
222                         return -1;      /* XXX internal fault */
223
224                 /* update state */
225                 attrib = mvrp_lookup(rattrib);
226
227                 if (NULL == attrib) {
228                         mvrp_add(rattrib);
229                         attrib = rattrib;
230                 } else {
231                         mvrp_merge(rattrib);
232                         free(rattrib);
233                 }
234
235                 mrp_applicant_fsm(&(attrib->applicant), event);
236                 /* remap local requests into registrar events */
237                 switch (event) {
238                 case MRP_EVENT_NEW:
239                         mrp_registrar_fsm(&(attrib->registrar),
240                                           &(MVRP_db->mrp_db), MRP_EVENT_RNEW);
241                         break;
242                 case MRP_EVENT_JOIN:
243                         if (MRP_IN_STATE == attrib->registrar.mrp_state)
244                                 mrp_registrar_fsm(&(attrib->registrar),
245                                                   &(MVRP_db->mrp_db),
246                                                   MRP_EVENT_RJOININ);
247                         else
248                                 mrp_registrar_fsm(&(attrib->registrar),
249                                                   &(MVRP_db->mrp_db),
250                                                   MRP_EVENT_RJOINMT);
251                         break;
252                 case MRP_EVENT_LV:
253                         mrp_registrar_fsm(&(attrib->registrar),
254                                           &(MVRP_db->mrp_db), MRP_EVENT_RLV);
255                         break;
256                 default:
257                         rc = mrp_registrar_fsm(&(attrib->registrar),
258                                                &(MVRP_db->mrp_db), event);
259                         if (-1 == rc) {
260                                 printf
261                                     ("MVRP registrar error on attrib->attribute = %d\n",
262                                      attrib->attribute);
263                         }
264                         break;
265                 }
266                 break;
267         default:
268                 break;
269         }
270
271         /*
272          * XXX should honor the MVRP_db->mrp_db.registration and
273          * MVRP_db->mrp_db.participant controls
274          */
275
276         /* generate local notifications */
277         attrib = MVRP_db->attrib_list;
278
279         while (NULL != attrib) {
280                 if (MRP_NOTIFY_NONE != attrib->registrar.notify) {
281                         mvrp_send_notifications(attrib,
282                                                 attrib->registrar.notify);
283                         attrib->registrar.notify = MRP_NOTIFY_NONE;
284                 }
285                 attrib = attrib->next;
286         }
287
288         return 0;
289 }
290
291 struct mvrp_attribute *mvrp_alloc()
292 {
293         struct mvrp_attribute *attrib;
294
295         attrib = malloc(sizeof(struct mvrp_attribute));
296         if (NULL == attrib)
297                 return NULL;
298
299         memset(attrib, 0, sizeof(struct mvrp_attribute));
300
301         attrib->applicant.mrp_state = MRP_VO_STATE;
302         attrib->applicant.tx = 0;
303         attrib->applicant.sndmsg = MRP_SND_NULL;
304         attrib->applicant.encode = MRP_ENCODE_OPTIONAL;
305
306         attrib->registrar.mrp_state = MRP_MT_STATE;
307         attrib->registrar.notify = MRP_NOTIFY_NONE;
308
309         return attrib;
310 }
311
312 int mvrp_recv_msg(void)
313 {
314         char *msgbuf;
315         int bytes = 0;
316         eth_hdr_t *eth;
317         mrpdu_t *mrpdu;
318         mrpdu_message_t *mrpdu_msg;
319         unsigned char *mrpdu_msg_ptr;
320         unsigned char *mrpdu_msg_eof;
321         mrpdu_vectorattrib_t *mrpdu_vectorptr;
322         uint16_t numvalues;
323         uint16_t numvalues_processed;
324         int numvectorbytes;
325         uint8_t vect_3pack;
326         int vectidx;
327         int vectevt[3];
328         int vectevt_idx;
329         uint16_t vid_firstval;
330         struct mvrp_attribute *attrib;
331         int endmarks;
332
333         bytes = mrpd_recvmsgbuf(mvrp_socket, &msgbuf);
334         if (bytes <= 0)
335                 goto out;
336
337         if ((unsigned int)bytes < (sizeof(eth_hdr_t) + sizeof(mrpdu_t) +
338                                    sizeof(mrpdu_message_t)))
339                 goto out;
340
341         eth = (eth_hdr_t *) msgbuf;
342
343         /* note that MVRP frames should always arrive untagged (no vlan) */
344         if (MVRP_ETYPE != ntohs(eth->typelen))
345                 goto out;
346
347         /* XXX check dest mac address too? */
348
349         mrpdu = (mrpdu_t *) (msgbuf + sizeof(struct eth_hdr));
350
351         /*
352          * ProtocolVersion handling - a receiver must process received frames with a lesser
353          * protcol version consistent with the older protocol processing requirements (e.g. a V2
354          * agent receives a V1 message, the V1 message shoudl be parsed with V1 rules).
355          *
356          * However - if an agent receives a NEWER protocol, the agent shoudl still attempt
357          * to parse the frame. If the agent finds an AttributeType not recognized
358          * the agent discards the current message including any associated trailing vectors
359          * up to the end-mark, and resumes with the next message or until the end of the PDU
360          * is reached.
361          *
362          * If a VectorAttribute is found with an unknown Event for the Type, the specific
363          * VectorAttrute is discarded and processing continues with the next VectorAttribute.
364          */
365
366         if (MVRP_PROT_VER != mrpdu->ProtocolVersion)    /* XXX should accept ... */
367                 goto out;
368
369         mrpdu_msg_ptr = (unsigned char *)MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
370
371         mrpdu_msg_eof = (unsigned char *)mrpdu_msg_ptr;
372         mrpdu_msg_eof += bytes;
373         mrpdu_msg_eof -= sizeof(eth_hdr_t);
374         mrpdu_msg_eof -= MRPD_OFFSETOF_MRPD_GET_MRPDU_MESSAGE_LIST;
375
376         /*
377          * MVRP_VID_TYPE FirstValue is the 12 bit (2-byte) VLAN with
378          * corresponding attrib_length=2
379          *
380          * MVRP uses ThreePackedEvents for all vector encodings
381          *
382          * walk list until we run to the end of the PDU, or encounter a double end-mark
383          */
384
385         endmarks = 0;
386
387         while (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
388                 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
389                 if ((mrpdu_msg->AttributeType == 0) &&
390                     (mrpdu_msg->AttributeLength == 0)) {
391                         mrpdu_msg_ptr += 2;
392                         endmarks++;
393                         if (endmarks < 2)
394                                 continue;       /* end-mark of message-list */
395                         else
396                                 break;  /* two endmarks - end of message list */
397                 }
398
399                 endmarks = 0;
400
401                 switch (mrpdu_msg->AttributeType) {
402                 case MVRP_VID_TYPE:
403                         if (mrpdu_msg->AttributeLength != 2) {
404                                 /* we can seek for an endmark to recover .. but this version
405                                  * dumps the entire packet as malformed
406                                  */
407                                 goto out;
408                         }
409                         /* AttributeListLength not used for MVRP, hence
410                          * Data points to the beginning of the VectorAttributes
411                          */
412                         mrpdu_vectorptr =
413                             MRPD_GET_MRPDU_MESSAGE_VECTOR(mrpdu_msg, 0);
414                         mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
415
416                         while (!((mrpdu_msg_ptr[0] == 0)
417                                  && (mrpdu_msg_ptr[1] == 0))) {
418                                 numvalues =
419                                     MRPDU_VECT_NUMVALUES(ntohs
420                                                          (mrpdu_vectorptr->
421                                                           VectorHeader));
422
423                                 if (0 == numvalues)
424                                         /* Malformed - cant tell how long the trailing vectors are */
425                                         goto out;
426
427                                 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
428                                      numvalues / 3) >= mrpdu_msg_eof)
429                                         /* Malformed - runs off the end of the pdu */
430                                         goto out;
431
432                                 vid_firstval = (((uint16_t)
433                                                  mrpdu_vectorptr->
434                                                  FirstValue_VectorEvents[0]) <<
435                                                 8)
436                                     | mrpdu_vectorptr->
437                                     FirstValue_VectorEvents[1];
438
439                                 /* if not an even multiple ... */
440                                 if (numvalues != ((numvalues / 3) * 3))
441                                         numvectorbytes = (numvalues / 3) + 1;
442                                 else
443                                         numvectorbytes = (numvalues / 3);
444
445                                 for (vectidx = 2;
446                                      vectidx <= (numvectorbytes + 2);
447                                      vectidx++) {
448                                         vect_3pack =
449                                             mrpdu_vectorptr->
450                                             FirstValue_VectorEvents[vectidx];
451                                         vectevt[0] = vect_3pack / 36;
452                                         vectevt[1] =
453                                             (vect_3pack - vectevt[0] * 36) / 6;
454                                         vectevt[2] =
455                                             vect_3pack - (36 * vectevt[0]) -
456                                             (6 * vectevt[1]);
457
458                                         numvalues_processed =
459                                             (numvalues > 3 ? 3 : numvalues);
460
461                                         for (vectevt_idx = 0;
462                                              vectevt_idx < numvalues_processed;
463                                              vectevt_idx++) {
464
465                                                 if (0xFFF < vid_firstval)       /*discard junk */
466                                                         continue;
467
468                                                 attrib = mvrp_alloc();
469                                                 if (NULL == attrib)
470                                                         goto out;       /* oops - internal error */
471
472                                                 attrib->attribute =
473                                                     vid_firstval;
474                                                 vid_firstval++;
475                                                 memcpy(attrib->registrar.
476                                                        macaddr, eth->srcaddr,
477                                                        6);
478
479                                                 switch (vectevt[vectevt_idx]) {
480                                                 case MRPDU_NEW:
481                                                         mvrp_event
482                                                             (MRP_EVENT_RNEW,
483                                                              attrib);
484                                                         break;
485                                                 case MRPDU_JOININ:
486                                                         mvrp_event
487                                                             (MRP_EVENT_RJOININ,
488                                                              attrib);
489                                                         break;
490                                                 case MRPDU_IN:
491                                                         mvrp_event
492                                                             (MRP_EVENT_RIN,
493                                                              attrib);
494                                                         break;
495                                                 case MRPDU_JOINMT:
496                                                         mvrp_event
497                                                             (MRP_EVENT_RJOINMT,
498                                                              attrib);
499                                                         break;
500                                                 case MRPDU_MT:
501                                                         mvrp_event
502                                                             (MRP_EVENT_RMT,
503                                                              attrib);
504                                                         break;
505                                                 case MRPDU_LV:
506                                                         mvrp_event
507                                                             (MRP_EVENT_RLV,
508                                                              attrib);
509                                                         break;
510                                                 default:
511                                                         free(attrib);
512                                                         break;
513                                                 }
514                                         }
515                                         numvalues -= numvalues_processed;
516                                 }
517
518                                 if (MRPDU_VECT_LVA
519                                     (ntohs(mrpdu_vectorptr->VectorHeader)))
520                                         mvrp_event(MRP_EVENT_RLA, NULL);
521
522                                 /* 1 byte Type, 1 byte Len, 2 byte FirstValue, and (n) vector bytes */
523                                 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
524                                 mrpdu_msg_ptr += 4 + numvectorbytes;
525
526                                 mrpdu_vectorptr =
527                                     (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
528                         }
529                         break;
530                 default:
531                         /* unrecognized attribute type
532                          * we can seek for an endmark to recover .. but this version
533                          * dumps the entire packet as malformed
534                          */
535                         goto out;
536                 }
537         }
538
539         free(msgbuf);
540         return 0;
541  out:
542         free(msgbuf);
543
544         return -1;
545 }
546
547 int
548 mvrp_emit_vidvectors(unsigned char *msgbuf, unsigned char *msgbuf_eof,
549                      int *bytes_used, int lva)
550 {
551         mrpdu_vectorattrib_t *mrpdu_vectorptr;
552         uint16_t numvalues;
553         uint8_t vect_3pack;
554         int vectidx;
555         unsigned int vectevt[3];
556         int vectevt_idx;
557         uint16_t vid_firstval;
558         struct mvrp_attribute *attrib, *vattrib;
559         mrpdu_message_t *mrpdu_msg;
560
561         unsigned char *mrpdu_msg_ptr = msgbuf;
562         unsigned char *mrpdu_msg_eof = msgbuf_eof;
563
564         /* need at least 6 bytes for a single vector */
565         if (mrpdu_msg_ptr > (mrpdu_msg_eof - 6))
566                 goto oops;
567
568         mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
569         mrpdu_msg->AttributeType = MVRP_VID_TYPE;
570         mrpdu_msg->AttributeLength = 2;
571
572         attrib = MVRP_db->attrib_list;
573
574         mrpdu_vectorptr = MRPD_GET_MRPDU_MESSAGE_VECTOR(mrpdu_msg, 0);
575
576         while ((mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) && (NULL != attrib)) {
577
578                 if (0 == attrib->applicant.tx) {
579                         attrib = attrib->next;
580                         continue;
581                 }
582                 if (MRP_ENCODE_OPTIONAL == attrib->applicant.encode) {
583                         attrib->applicant.tx = 0;
584                         attrib = attrib->next;
585                         continue;
586                 }
587
588                 /* pointing to at least one attribute which needs to be transmitted */
589                 attrib->applicant.tx = 0;
590                 vid_firstval = attrib->attribute;
591                 mrpdu_vectorptr->FirstValue_VectorEvents[0] =
592                     (uint8_t) (attrib->attribute >> 8);
593                 mrpdu_vectorptr->FirstValue_VectorEvents[1] =
594                     (uint8_t) (attrib->attribute);
595
596                 switch (attrib->applicant.sndmsg) {
597                 case MRP_SND_IN:
598                         /*
599                          * If 'In' in indicated by the applicant attribute, the
600                          * look at the registrar state to determine whether to
601                          * send an In (if registrar is also In) or an Mt if the
602                          * registrar is either Mt or Lv.
603                          */
604                         if (MRP_IN_STATE == attrib->registrar.mrp_state)
605                                 vectevt[0] = MRPDU_IN;
606                         else
607                                 vectevt[0] = MRPDU_MT;
608                         break;
609                 case MRP_SND_NEW:
610                         vectevt[0] = MRPDU_NEW;
611                         break;
612                 case MRP_SND_LV:
613                         vectevt[0] = MRPDU_LV;
614                         break;
615                 case MRP_SND_JOIN:
616                         /* IF 'Join' in indicated by the applicant, look at
617                          * the corresponding registrar state to determine whether
618                          * to send a JoinIn (if the registar state is 'In') or
619                          * a JoinMt if the registrar state is MT or LV.
620                          */
621                         if (MRP_IN_STATE == attrib->registrar.mrp_state)
622                                 vectevt[0] = MRPDU_JOININ;
623                         else
624                                 vectevt[0] = MRPDU_JOINMT;
625                         break;
626                 default:
627                         /* huh? */
628                         goto oops;
629                         break;
630                 }
631
632                 vectevt_idx = 1;
633                 numvalues = 1;
634                 vectevt[1] = 0;
635                 vectevt[2] = 0;
636
637                 /* now attempt to vectorize contiguous other attributes
638                  * which also need to be transmitted
639                  */
640
641                 vectidx = 2;
642                 vattrib = attrib->next;
643
644                 while (NULL != vattrib) {
645                         if (0 == vattrib->applicant.tx)
646                                 break;
647
648                         vid_firstval++;
649
650                         if (vattrib->attribute != vid_firstval)
651                                 break;
652
653                         vattrib->applicant.tx = 0;
654
655                         switch (vattrib->applicant.sndmsg) {
656                         case MRP_SND_IN:
657                                 /*
658                                  * If 'In' in indicated by the applicant attribute, the
659                                  * look at the registrar state to determine whether to
660                                  * send an In (if registrar is also In) or an Mt if the
661                                  * registrar is either Mt or Lv.
662                                  */
663                                 if (MRP_IN_STATE ==
664                                     vattrib->registrar.mrp_state)
665                                         vectevt[vectevt_idx] = MRPDU_IN;
666                                 else
667                                         vectevt[vectevt_idx] = MRPDU_MT;
668                                 break;
669                         case MRP_SND_NEW:
670                                 vectevt[vectevt_idx] = MRPDU_NEW;
671                                 break;
672                         case MRP_SND_LV:
673                                 vectevt[vectevt_idx] = MRPDU_LV;
674                                 break;
675                         case MRP_SND_JOIN:
676                                 /* IF 'Join' in indicated by the applicant, look at
677                                  * the corresponding registrar state to determine whether
678                                  * to send a JoinIn (if the registar state is 'In') or
679                                  * a JoinMt if the registrar state is MT or LV.
680                                  */
681                                 if (MRP_IN_STATE == attrib->registrar.mrp_state)
682                                         vectevt[vectevt_idx] = MRPDU_JOININ;
683                                 else
684                                         vectevt[vectevt_idx] = MRPDU_JOINMT;
685                                 break;
686                         default:
687                                 /* huh? */
688                                 goto oops;
689                                 break;
690                         }
691
692                         vectevt_idx++;
693                         numvalues++;
694
695                         if (vectevt_idx > 2) {
696                                 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
697                                                                 vectevt[1],
698                                                                 vectevt[2]);
699
700                                 mrpdu_vectorptr->FirstValue_VectorEvents
701                                     [vectidx] = vect_3pack;
702                                 vectidx++;
703                                 vectevt[0] = 0;
704                                 vectevt[1] = 0;
705                                 vectevt[2] = 0;
706                                 vectevt_idx = 0;
707                         }
708
709                         if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
710                             > (mrpdu_msg_eof - 2))
711                                 goto oops;
712
713                         vattrib = vattrib->next;
714                 }
715
716                 /* handle any trailers */
717                 if (vectevt_idx > 0) {
718                         vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
719                                                         vectevt[1], vectevt[2]);
720
721                         mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
722                             vect_3pack;
723                         vectidx++;
724                 }
725
726                 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]) >
727                     (mrpdu_msg_eof - 2))
728                         goto oops;
729
730                 mrpdu_vectorptr->VectorHeader = MRPDU_VECT_NUMVALUES(numvalues);
731
732                 if (lva)
733                         mrpdu_vectorptr->VectorHeader |= MRPDU_VECT_LVA(0xFFFF);
734
735                 mrpdu_vectorptr->VectorHeader =
736                     htons(mrpdu_vectorptr->VectorHeader);
737
738                 /* 2 byte header, followed by FirstValues/Vectors - remember vectidx starts at 0 */
739                 mrpdu_msg_ptr =
740                     &(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]);
741
742                 attrib = attrib->next;
743
744                 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
745         }
746
747         if (mrpdu_vectorptr == MRPD_GET_MRPDU_MESSAGE_VECTOR(mrpdu_msg, 0)) {
748                 *bytes_used = 0;
749                 return 0;
750         }
751
752         /* endmark */
753         *mrpdu_msg_ptr = 0;
754         mrpdu_msg_ptr++;
755         *mrpdu_msg_ptr = 0;
756         mrpdu_msg_ptr++;
757
758         *bytes_used = (mrpdu_msg_ptr - msgbuf);
759         return 0;
760  oops:
761         /* an internal error - caller should assume TXLAF */
762         *bytes_used = 0;
763         return -1;
764 }
765
766 int mvrp_txpdu(void)
767 {
768         unsigned char *msgbuf, *msgbuf_wrptr;
769         int msgbuf_len;
770         int bytes = 0;
771         eth_hdr_t *eth;
772         mrpdu_t *mrpdu;
773         unsigned char *mrpdu_msg_ptr;
774         unsigned char *mrpdu_msg_eof;
775         int rc;
776         int lva = 0;
777
778         msgbuf = (unsigned char *)malloc(MAX_FRAME_SIZE);
779         if (NULL == msgbuf)
780                 return -1;
781         msgbuf_len = 0;
782
783         msgbuf_wrptr = msgbuf;
784
785         eth = (eth_hdr_t *) msgbuf_wrptr;
786
787         /* note that MVRP frames should always be untagged (no vlan) */
788         eth->typelen = htons(MVRP_ETYPE);
789         memcpy(eth->destaddr, MVRP_CUSTOMER_BRIDGE_ADDR, sizeof(eth->destaddr));
790         memcpy(eth->srcaddr, STATION_ADDR, sizeof(eth->srcaddr));
791
792         msgbuf_wrptr += sizeof(eth_hdr_t);
793
794         mrpdu = (mrpdu_t *) msgbuf_wrptr;
795
796         /*
797          * ProtocolVersion handling - a receiver must process received frames with a lesser
798          * protcol version consistent with the older protocol processing requirements (e.g. a V2
799          * agent receives a V1 message, the V1 message shoudl be parsed with V1 rules).
800          *
801          * However - if an agent receives a NEWER protocol, the agent shoudl still attempt
802          * to parse the frame. If the agent finds an AttributeType not recognized
803          * the agent discards the current message including any associated trailing vectors
804          * up to the end-mark, and resumes with the next message or until the end of the PDU
805          * is reached.
806          *
807          * If a VectorAttribute is found with an unknown Event for the Type, the specific
808          * VectorAttrute is discarded and processing continues with the next VectorAttribute.
809          */
810
811         mrpdu->ProtocolVersion = MVRP_PROT_VER;
812         mrpdu_msg_ptr = MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
813         mrpdu_msg_eof = (unsigned char *)msgbuf + MAX_FRAME_SIZE;
814
815         /*
816          * Iterate over all attributes, transmitting those marked
817          * with 'tx', attempting to coalesce multiple contiguous tx attributes
818          * with appropriate vector encodings.
819          *
820          * MVRP_VID_TYPE FirstValue is the 2-byte VLAN with
821          * corresponding attrib_length=2
822          *
823          * MVRP uses ThreePackedEvents for all vector encodings
824          *
825          * the expanded version of the MRPDU looks like
826          * ProtocolVersion
827          * AttributeType
828          * AttributeLength
829          * <Variable number of>
830          *              LeaveAllEvent | NumberOfValues
831          *              <Variable FirstValue>
832          *              <VectorEventBytes>
833          * EndMark
834          *
835          * in effect, each AttributeType present gets its own 'message' with
836          * variable number of vectors. So with MVRP, you will have at most
837          * one message.
838          */
839
840         if (MVRP_db->mrp_db.lva.tx) {
841                 lva = 1;
842                 MVRP_db->mrp_db.lva.tx = 0;
843         }
844
845         rc = mvrp_emit_vidvectors(mrpdu_msg_ptr, mrpdu_msg_eof, &bytes, lva);
846         if (-1 == rc)
847                 goto out;
848
849         mrpdu_msg_ptr += bytes;
850
851         if (mrpdu_msg_ptr == MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu)) {
852                 goto out;       /* nothing to send */
853         }
854
855         /* endmark */
856         if (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
857                 *mrpdu_msg_ptr = 0;
858                 mrpdu_msg_ptr++;
859                 *mrpdu_msg_ptr = 0;
860                 mrpdu_msg_ptr++;
861         } else
862                 goto out;
863
864         msgbuf_len = mrpdu_msg_ptr - msgbuf;
865
866         bytes = mrpd_send(mvrp_socket, msgbuf, msgbuf_len, 0);
867         if (bytes <= 0)
868                 goto out;
869
870         free(msgbuf);
871         return 0;
872  out:
873         free(msgbuf);
874         /* caller should assume TXLAF */
875         return -1;
876 }
877
878 int mvrp_send_notifications(struct mvrp_attribute *attrib, int notify)
879 {
880         char *msgbuf;
881         char *stage;
882         char *variant;
883         char *regsrc;
884         client_t *client;
885
886         if (NULL == attrib)
887                 return -1;
888
889         msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
890         if (NULL == msgbuf)
891                 return -1;
892
893         stage = variant = regsrc = NULL;
894
895         stage = (char *)malloc(128);
896         variant = (char *)malloc(128);
897         regsrc = (char *)malloc(128);
898
899         if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
900                 goto free_msgbuf;
901
902         memset(msgbuf, 0, MAX_MRPD_CMDSZ);
903
904         sprintf(variant, "%04x", attrib->attribute);
905
906         sprintf(regsrc, "R%02x%02x%02x%02x%02x%02x",
907                 attrib->registrar.macaddr[0],
908                 attrib->registrar.macaddr[1],
909                 attrib->registrar.macaddr[2],
910                 attrib->registrar.macaddr[3],
911                 attrib->registrar.macaddr[4], attrib->registrar.macaddr[5]);
912         switch (attrib->registrar.mrp_state) {
913         case MRP_IN_STATE:
914                 sprintf(stage, "VIN %s %s\n", variant, regsrc);
915                 break;
916         case MRP_LV_STATE:
917                 sprintf(stage, "VLV %s %s\n", variant, regsrc);
918                 break;
919         case MRP_MT_STATE:
920                 sprintf(stage, "VMT %s %s\n", variant, regsrc);
921                 break;
922         default:
923                 break;
924         }
925
926         switch (notify) {
927         case MRP_NOTIFY_NEW:
928                 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VNE %s", stage);
929                 break;
930         case MRP_NOTIFY_JOIN:
931                 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VJO %s", stage);
932                 break;
933         case MRP_NOTIFY_LV:
934                 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VLE %s", stage);
935                 break;
936         default:
937                 goto free_msgbuf;
938                 break;
939         }
940
941         client = MVRP_db->mrp_db.clients;
942         while (NULL != client) {
943                 mrpd_send_ctl_msg(&(client->client), msgbuf, MAX_MRPD_CMDSZ);
944                 client = client->next;
945         }
946
947  free_msgbuf:
948         if (regsrc)
949                 free(regsrc);
950         if (variant)
951                 free(variant);
952         if (stage)
953                 free(stage);
954         free(msgbuf);
955         return 0;
956 }
957
958 int mvrp_dumptable(struct sockaddr_in *client)
959 {
960         char *msgbuf;
961         char *msgbuf_wrptr;
962         char *stage;
963         char *variant;
964         char *regsrc;
965         struct mvrp_attribute *attrib;
966
967         msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
968         if (NULL == msgbuf)
969                 return -1;
970
971         stage = variant = regsrc = NULL;
972
973         stage = (char *)malloc(128);
974         variant = (char *)malloc(128);
975         regsrc = (char *)malloc(128);
976
977         if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
978                 goto free_msgbuf;
979
980         memset(msgbuf, 0, MAX_MRPD_CMDSZ);
981
982         msgbuf_wrptr = msgbuf;
983
984         attrib = MVRP_db->attrib_list;
985
986         while (NULL != attrib) {
987                 sprintf(variant, "%04x", attrib->attribute);
988                 sprintf(regsrc, "R%02x%02x%02x%02x%02x%02x",
989                         attrib->registrar.macaddr[0],
990                         attrib->registrar.macaddr[1],
991                         attrib->registrar.macaddr[2],
992                         attrib->registrar.macaddr[3],
993                         attrib->registrar.macaddr[4],
994                         attrib->registrar.macaddr[5]);
995                 switch (attrib->registrar.mrp_state) {
996                 case MRP_IN_STATE:
997                         sprintf(stage, "VIN %s %s\n", variant, regsrc);
998                         break;
999                 case MRP_LV_STATE:
1000                         sprintf(stage, "VLV %s %s\n", variant, regsrc);
1001                         break;
1002                 case MRP_MT_STATE:
1003                         sprintf(stage, "VMT %s %s\n", variant, regsrc);
1004                         break;
1005                 default:
1006                         break;
1007                 }
1008                 sprintf(msgbuf_wrptr, "%s", stage);
1009                 msgbuf_wrptr += strnlen(stage, 128);
1010                 attrib = attrib->next;
1011         }
1012
1013         mrpd_send_ctl_msg(client, msgbuf, MAX_MRPD_CMDSZ);
1014
1015  free_msgbuf:
1016         if (regsrc)
1017                 free(regsrc);
1018         if (variant)
1019                 free(variant);
1020         if (stage)
1021                 free(stage);
1022         free(msgbuf);
1023         return 0;
1024
1025 }
1026
1027 int mvrp_recv_cmd(char *buf, int buflen, struct sockaddr_in *client)
1028 {
1029         int rc;
1030         char respbuf[8];
1031         struct mvrp_attribute *attrib;
1032         unsigned int vid_firstval;
1033         uint8_t vid_parsestr[8];
1034
1035         if (NULL == MVRP_db) {
1036                 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1037                 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1038                 goto out;
1039         }
1040
1041         rc = mrp_client_add(&(MVRP_db->mrp_db.clients), client);
1042
1043         if (buflen < 3)
1044                 return -1;
1045
1046         if ('V' != buf[0])
1047                 return -1;
1048
1049         /*
1050          * V?? - query MVRP Registrar VID database
1051          * V+? - JOIN a VID
1052          * V++   NEW a VID (XXX: note network disturbance)
1053          * V-- - LV a VID
1054          */
1055         switch (buf[1]) {
1056         case '?':
1057                 mvrp_dumptable(client);
1058                 break;
1059         case '-':
1060                 if (buflen < 5) {
1061                         snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1062                         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1063                         goto out;
1064                 }
1065                 /* buf[] should look similar to 'V--0001' where VID is in hex */
1066                 if (buflen < 7) {
1067                         snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1068                         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1069                         goto out;
1070                 }
1071
1072                 memset(vid_parsestr, 0, sizeof(vid_parsestr));
1073
1074                 rc = sscanf((char *)&buf[3], "%04x", &vid_firstval);
1075                 if (0 == rc) {
1076                         snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1077                         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1078                         goto out;
1079                 }
1080
1081                 attrib = mvrp_alloc();
1082                 if (NULL == attrib) {
1083                         snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
1084                         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1085                         goto out;       /* oops - internal error */
1086                 }
1087                 attrib->attribute = vid_firstval;
1088                 memset(attrib->registrar.macaddr, 0, 6);
1089
1090                 mvrp_event(MRP_EVENT_LV, attrib);
1091                 break;
1092         case '+':
1093                 /* buf[] should look similar to 'V+?0001' where VID is in hex */
1094                 if (('?' != buf[2]) && ('+' != buf[2])) {
1095                         snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1096                         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1097                         goto out;
1098                 }
1099                 if (buflen < 7) {
1100                         snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1101                         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1102                         goto out;
1103                 }
1104                 rc = sscanf((char *)&buf[3], "%04x", &vid_firstval);
1105
1106                 if (0 == rc) {
1107                         snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1108                         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1109                         goto out;
1110                 }
1111
1112                 attrib = mvrp_alloc();
1113                 if (NULL == attrib) {
1114                         snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
1115                         mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1116                         goto out;       /* oops - internal error */
1117                 }
1118                 attrib->attribute = vid_firstval;
1119                 memset(attrib->registrar.macaddr, 0, 6);
1120
1121                 if ('?' == buf[2]) {
1122                         mvrp_event(MRP_EVENT_JOIN, attrib);
1123                 } else {
1124                         mvrp_event(MRP_EVENT_NEW, attrib);
1125                 }
1126                 break;
1127         default:
1128                 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1129                 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1130                 goto out;
1131                 break;
1132         }
1133         return 0;
1134  out:
1135         return -1;
1136 }
1137
1138 int mvrp_init(int mvrp_enable)
1139 {
1140         int rc;
1141
1142         /* XXX doesn't handle re-start */
1143
1144         mvrp_socket = INVALID_SOCKET;
1145         MVRP_db = NULL;
1146
1147         if (0 == mvrp_enable) {
1148                 return 0;
1149         }
1150
1151         rc = mrpd_init_protocol_socket(MVRP_ETYPE, &mvrp_socket,
1152                                        MVRP_CUSTOMER_BRIDGE_ADDR);
1153         if (rc < 0)
1154                 return -1;
1155
1156         MVRP_db = malloc(sizeof(struct mvrp_database));
1157
1158         if (NULL == MVRP_db)
1159                 goto abort_socket;
1160
1161         memset(MVRP_db, 0, sizeof(struct mvrp_database));
1162
1163         /* if registration is FIXED or FORBIDDEN
1164          * updates from MRP are discarded, and
1165          * only IN and JOININ messages are sent
1166          */
1167         MVRP_db->mrp_db.registration = MRP_REGISTRAR_CTL_NORMAL;        /* default */
1168
1169         /* if participant role is 'SILENT' (or non-participant)
1170          * applicant doesn't send any messages -
1171          *
1172          * Note - theoretically configured per-attribute
1173          */
1174         MVRP_db->mrp_db.participant = MRP_APPLICANT_CTL_NORMAL; /* default */
1175
1176         rc = mrpd_init_timers(&(MVRP_db->mrp_db));
1177
1178         if (rc < 0)
1179                 goto abort_alloc;
1180
1181         mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_BEGIN);
1182         return 0;
1183
1184  abort_alloc:
1185         /* free MVRP_db and related structures */
1186         free(MVRP_db);
1187         MVRP_db = NULL;
1188  abort_socket:
1189         mrpd_close_socket(mvrp_socket);
1190         mvrp_socket = INVALID_SOCKET;
1191         /* XXX */
1192         return -1;
1193 }
1194
1195 int mvrp_reclaim(void)
1196 {
1197         struct mvrp_attribute *vattrib, *free_vattrib;
1198         if (NULL == MVRP_db)
1199                 return 0;
1200
1201         vattrib = MVRP_db->attrib_list;
1202         while (NULL != vattrib) {
1203                 if ((vattrib->registrar.mrp_state == MRP_MT_STATE) &&
1204                     ((vattrib->applicant.mrp_state == MRP_VO_STATE) ||
1205                      (vattrib->applicant.mrp_state == MRP_AO_STATE) ||
1206                      (vattrib->applicant.mrp_state == MRP_QO_STATE))) {
1207                         if (NULL != vattrib->prev)
1208                                 vattrib->prev->next = vattrib->next;
1209                         else
1210                                 MVRP_db->attrib_list = vattrib->next;
1211                         if (NULL != vattrib->next)
1212                                 vattrib->next->prev = vattrib->prev;
1213                         free_vattrib = vattrib;
1214                         vattrib = vattrib->next;
1215                         mvrp_send_notifications(free_vattrib, MRP_NOTIFY_LV);
1216                         free(free_vattrib);
1217                 } else
1218                         vattrib = vattrib->next;
1219         }
1220         return 0;
1221 }
1222
1223 void mvrp_bye(struct sockaddr_in *client)
1224 {
1225         if (NULL != MVRP_db)
1226                 mrp_client_delete(&(MVRP_db->mrp_db.clients), client);
1227
1228 }