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